Code

Patch by Jean-René Reinhard: better SVG compliance for lighting effects
authorkiirala <kiirala@users.sourceforge.net>
Mon, 23 Jul 2007 08:12:06 +0000 (08:12 +0000)
committerkiirala <kiirala@users.sourceforge.net>
Mon, 23 Jul 2007 08:12:06 +0000 (08:12 +0000)
src/display/Makefile_insert
src/display/nr-filter-composite.cpp
src/display/nr-filter-diffuselighting.cpp
src/display/nr-filter-specularlighting.cpp
src/display/nr-filter-utils.cpp [new file with mode: 0644]
src/display/nr-filter-utils.h [new file with mode: 0644]

index eaa2f584f311dbf8647e36235f2d3b575f689f9e..a72175b3f1a38ff3a2514a3bac727440557fe5c7 100644 (file)
@@ -89,6 +89,8 @@ display_libspdisplay_a_SOURCES = \
        display/nr-filter-getalpha.h    \
        display/nr-filter-pixops.h      \
        display/nr-filter-types.h       \
+       display/nr-filter-utils.h       \
+       display/nr-filter-utils.cpp     \
        display/pixblock-scaler.cpp     \
        display/pixblock-scaler.h       \
        display/pixblock-transform.cpp  \
index 43580191e761e0ddef1d30e9b27c33214ffb582d..a5b1d52976ee59a44ab54621c5c570d85440f075 100644 (file)
@@ -16,6 +16,7 @@
 #include "display/nr-filter-composite.h"
 #include "display/nr-filter-pixops.h"
 #include "display/nr-filter-slot.h"
+#include "display/nr-filter-utils.h"
 #include "libnr/nr-blit.h"
 #include "libnr/nr-pixblock.h"
 #include "libnr/nr-pixops.h"
@@ -66,25 +67,19 @@ composite_xor(unsigned char *r, unsigned char const *a, unsigned char const *b)
     r[3] = NR_NORMALIZE_21(a[3] * (255 - b[3]) + b[3] * (255 - a[3]));
 }
 
-static int clamp(int val) {
-    if (val < 0) return 0;
-    if (val > 255) return 255;
-    return val;
-}
-
 // BUGBUG / TODO
 // This makes arithmetic compositing non re-entrant and non thread safe.
 static int arith_k1, arith_k2, arith_k3, arith_k4;
 inline void
 composite_arithmetic(unsigned char *r, unsigned char const *a, unsigned char const *b)
 {
-    r[0] = clamp(NR_NORMALIZE_31(arith_k1 * a[0] * b[0]
+    r[0] = NR::clamp(NR_NORMALIZE_31(arith_k1 * a[0] * b[0]
                  + arith_k2 * a[0] + arith_k3 * b[0] + arith_k4));
-    r[1] = clamp(NR_NORMALIZE_31(arith_k1 * a[1] * b[1]
+    r[1] = NR::clamp(NR_NORMALIZE_31(arith_k1 * a[1] * b[1]
                  + arith_k2 * a[1] + arith_k3 * b[1] + arith_k4));
-    r[2] = clamp(NR_NORMALIZE_31(arith_k1 * a[2] * b[2]
+    r[2] = NR::clamp(NR_NORMALIZE_31(arith_k1 * a[2] * b[2]
                  + arith_k2 * a[2] + arith_k3 * b[2] + arith_k4));
-    r[3] = clamp(NR_NORMALIZE_31(arith_k1 * a[3] * b[3]
+    r[3] = NR::clamp(NR_NORMALIZE_31(arith_k1 * a[3] * b[3]
                  + arith_k2 * a[3] + arith_k3 * b[3] + arith_k4));
 }
 
index 736055f32b96167d7836b3174ebbb1c5f084d9d2..96a2e9ca6b24c5dd82e1fcb57a83c9d8b1b8b6dc 100644 (file)
 #include "display/nr-filter-diffuselighting.h"
 #include "display/nr-filter-getalpha.h"
 #include "display/nr-filter-slot.h"
+#include "display/nr-filter-utils.h"
 #include "display/nr-light.h"
 #include "libnr/nr-blit.h"
 #include "libnr/nr-pixblock.h"
 #include "libnr/nr-matrix.h"
 #include "libnr/nr-rect-l.h"
 #include "color.h"
-#include "round.h"
 
 namespace NR {
 
@@ -48,6 +48,7 @@ do {\
     if ((inter) < 0) (inter) = 0; \
 }while(0)
 
+
 int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) {
     NRPixBlock *in = filter_get_alpha(slot.get(_input));
     NRPixBlock *out = new NRPixBlock;
@@ -87,9 +88,9 @@ int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) {
                 compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
                 COMPUTE_INTER(inter, N, L, kd);
 
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]);
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]);
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
                 data_o[j++] = 255;
             }
             out->empty = FALSE;
@@ -113,9 +114,9 @@ int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) {
                         ss * (double) data_i[4*i+3]/ 255);
                 COMPUTE_INTER(inter, N, L, kd);
 
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]);
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]);
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
                 data_o[j++] = 255;
             }
             out->empty = FALSE;
@@ -139,9 +140,9 @@ int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) {
                 sl->light_components(LC, L);
                 COMPUTE_INTER(inter, N, L, kd);
                 
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]);
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]);
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
                 data_o[j++] = 255;
             }
             out->empty = FALSE;
index 117df28f7843832c45caef10927b8fb305325849..9957f4d591a01c50c86fe8ea5ebd3bc2f33d4ad0 100644 (file)
 #include "display/nr-filter-specularlighting.h"
 #include "display/nr-filter-getalpha.h"
 #include "display/nr-filter-slot.h"
+#include "display/nr-filter-utils.h"
 #include "display/nr-light.h"
 #include "libnr/nr-blit.h"
 #include "libnr/nr-pixblock.h"
 #include "libnr/nr-matrix.h"
 #include "libnr/nr-rect-l.h"
 #include "color.h"
-#include "round.h"
 
 namespace NR {
 
@@ -46,10 +46,12 @@ FilterSpecularLighting::~FilterSpecularLighting()
 
 //Investigating Phong Lighting model we should not take N.H but
 //R.E which equals to 2*N.H^2 - 1
+//replace the second line by 
+//gdouble scal = scalar_product((N), (H)); scal = 2 * scal * scal - 1;\
+//to get the expected formula
 #define COMPUTE_INTER(inter, H, N, ks, speculaExponent) \
 do {\
-    gdouble scal = scalar_product((N), (H));\
-    scal = 2 * scal * scal - 1;\
+    gdouble scal = scalar_product((N), (H)); \
     if (scal <= 0)\
         (inter) = 0;\
     else\
@@ -97,9 +99,9 @@ int FilterSpecularLighting::render(FilterSlot &slot, Matrix const &trans) {
                 compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
                 COMPUTE_INTER(inter, N, H, ks, specularExponent);
 
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]);
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]);
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
                 data_o[j++] = MAX(MAX(data_o[j-3], data_o[j-2]), data_o[j-1]);
             }
             out->empty = FALSE;
@@ -124,9 +126,9 @@ int FilterSpecularLighting::render(FilterSlot &slot, Matrix const &trans) {
                 normalized_sum(H, L, EYE_VECTOR);
                 COMPUTE_INTER(inter, N, H, ks, specularExponent);
                 
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]);
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]);
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
                 data_o[j++] = MAX(MAX(data_o[j-3], data_o[j-2]), data_o[j-1]);
             }
             out->empty = FALSE;
@@ -151,9 +153,9 @@ int FilterSpecularLighting::render(FilterSlot &slot, Matrix const &trans) {
                 normalized_sum(H, L, EYE_VECTOR);
                 COMPUTE_INTER(inter, N, H, ks, specularExponent);
                 
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]);
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]);
-                data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
                 data_o[j++] = MAX(MAX(data_o[j-3], data_o[j-2]), data_o[j-1]);
             }
             out->empty = FALSE;
diff --git a/src/display/nr-filter-utils.cpp b/src/display/nr-filter-utils.cpp
new file mode 100644 (file)
index 0000000..85faade
--- /dev/null
@@ -0,0 +1,11 @@
+#include "nr-filter-utils.h"
+
+namespace NR {
+
+int clamp(int val) {
+    if (val < 0) return 0;
+    if (val > 255) return 255;
+    return val;
+}
+       
+} //namespace NR
diff --git a/src/display/nr-filter-utils.h b/src/display/nr-filter-utils.h
new file mode 100644 (file)
index 0000000..b591b37
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __NR_FILTER_UTILS_H__
+#define __NR_FILTER_UTILS_H__
+
+/** \file
+ * filter utils. Definition of functions needed by several filters.
+ *
+ * Authors:
+ *   Jean-Rene Reinhard <jr@komite.net>
+ *
+ * Copyright (C) 2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "round.h"
+
+namespace NR {
+
+/**
+ * Clamps an integer value to a value between 0 and 255. Needed by filters where
+ * rendering computations can lead to component values out of bound.
+ *
+ * \return 0 if the value is smaller than 0, 255 if it is greater 255, else v
+ * \param v the value to clamp
+ */
+int clamp(int val);
+
+/**
+ * Macro to use the clamp function with double inputs and unsigned char output
+ */
+#define CLAMP_D_TO_U8(v) (unsigned char) clamp((int)round((v)))
+
+} /* namespace NR */
+
+#endif /* __NR_FILTER_UTILS_H__ */
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :