Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
nr-filter-diffuselighting.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * feDiffuseLighting renderer
4 *
5 * Authors:
6 * Niko Kiirala <niko@kiirala.com>
7 * Jean-Rene Reinhard <jr@komite.net>
8 * Krzysztof KosiƄski <tweenk.pl@gmail.com>
9 *
10 * Copyright (C) 2007-2010 Authors
11 *
12 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
13 */
14
15#ifdef HAVE_CONFIG_H
16# include "config.h" // only include where actually required!
17#endif
18
19#include <glib.h>
20
22#include "display/cairo-utils.h"
23#include "display/nr-3dutils.h"
28#include "display/nr-light.h"
29
30namespace Inkscape {
31namespace Filters {
32
34 : light_type(NO_LIGHT)
35 , diffuseConstant(1)
36 , surfaceScale(1)
37 , lighting_color(0xffffffff) {}
38
40
41struct DiffuseLight : public SurfaceSynth
42{
43 DiffuseLight(cairo_surface_t *bumpmap, double scale, double kd)
44 : SurfaceSynth(bumpmap)
45 , _scale(scale)
46 , _kd(kd) {}
47
48protected:
49 guint32 diffuseLighting(int x, int y, NR::Fvector const &light, NR::Fvector const &light_components)
50 {
51 NR::Fvector normal = surfaceNormalAt(x, y, _scale);
52 double k = _kd * NR::scalar_product(normal, light);
53
54 guint32 r = CLAMP_D_TO_U8(k * light_components[LIGHT_RED]);
55 guint32 g = CLAMP_D_TO_U8(k * light_components[LIGHT_GREEN]);
56 guint32 b = CLAMP_D_TO_U8(k * light_components[LIGHT_BLUE]);
57
58 ASSEMBLE_ARGB32(pxout, 255, r, g, b)
59 return pxout;
60 }
61
62 double _scale, _kd;
63};
64
65struct DiffuseDistantLight : public DiffuseLight
66{
67 DiffuseDistantLight(cairo_surface_t *bumpmap, DistantLightData const &light, guint32 color,
68 double scale, double diffuse_constant)
69 : DiffuseLight(bumpmap, scale, diffuse_constant)
70 {
71 DistantLight dl(light, color);
72 dl.light_vector(_lightv);
73 dl.light_components(_light_components);
74 }
75
76 guint32 operator()(int x, int y)
77 {
78 return diffuseLighting(x, y, _lightv, _light_components);
79 }
80
81private:
82 NR::Fvector _lightv, _light_components;
83};
84
85struct DiffusePointLight : public DiffuseLight
86{
87 DiffusePointLight(cairo_surface_t *bumpmap, PointLightData const &light, guint32 color,
88 Geom::Affine const &trans, double scale, double diffuse_constant,
89 double x0, double y0, int device_scale)
90 : DiffuseLight(bumpmap, scale, diffuse_constant)
91 , _light(light, color, trans, device_scale)
92 , _x0(x0)
93 , _y0(y0)
94 {
95 _light.light_components(_light_components);
96 }
97
98 guint32 operator()(int x, int y)
99 {
100 NR::Fvector light;
101 _light.light_vector(light, _x0 + x, _y0 + y, _scale * alphaAt(x, y) / 255.0);
102 return diffuseLighting(x, y, light, _light_components);
103 }
104
105private:
106 PointLight _light;
107 NR::Fvector _light_components;
108 double _x0, _y0;
109};
110
111struct DiffuseSpotLight : public DiffuseLight
112{
113 DiffuseSpotLight(cairo_surface_t *bumpmap, SpotLightData const &light, guint32 color,
114 Geom::Affine const &trans, double scale, double diffuse_constant,
115 double x0, double y0, int device_scale)
116 : DiffuseLight(bumpmap, scale, diffuse_constant)
117 , _light(light, color, trans, device_scale)
118 , _x0(x0)
119 , _y0(y0) {}
120
121 guint32 operator()(int x, int y)
122 {
123 NR::Fvector light, light_components;
124 _light.light_vector(light, _x0 + x, _y0 + y, _scale * alphaAt(x, y)/255.0);
125 _light.light_components(light_components, light);
126 return diffuseLighting(x, y, light, light_components);
127 }
128
129private:
130 SpotLight _light;
131 double _x0, _y0;
132};
133
135{
136 cairo_surface_t *input = slot.getcairo(_input);
137 cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA);
138
139 double r = SP_RGBA32_R_F(lighting_color);
140 double g = SP_RGBA32_G_F(lighting_color);
141 double b = SP_RGBA32_B_F(lighting_color);
142
143 // Only alpha channel of input is used, no need to check input color_interpolation_filter value.
144 // Lighting color is always defined in terms of sRGB, preconvert to linearRGB
145 // if color_interpolation_filters set to linearRGB (for efficiency assuming
146 // next filter primitive has same value of cif).
148 r = srgb_to_linear(r);
149 g = srgb_to_linear(g);
150 b = srgb_to_linear(b);
151 }
153 guint32 color = SP_RGBA32_F_COMPOSE(r, g, b, 1.0);
154
155 int device_scale = slot.get_device_scale();
156
157 Geom::Rect slot_area = slot.get_slot_area();
158 Geom::Point p = slot_area.min();
159
160 // trans has inverse y... so we can't just scale by device_scale! We must instead explicitly
161 // scale the point and spot light coordinates (as well as "scale").
162
164
165 double x0 = p.x(), y0 = p.y();
166 double scale = surfaceScale * trans.descrim() * device_scale;
167
168 switch (light_type) {
169 case DISTANT_LIGHT:
170 ink_cairo_surface_synthesize(out, DiffuseDistantLight(input, light.distant, color, scale, diffuseConstant));
171 break;
172 case POINT_LIGHT:
173 ink_cairo_surface_synthesize(out, DiffusePointLight(input, light.point, color, trans, scale, diffuseConstant, x0, y0, device_scale));
174 break;
175 case SPOT_LIGHT:
176 ink_cairo_surface_synthesize(out, DiffuseSpotLight(input, light.spot, color, trans, scale, diffuseConstant, x0, y0, device_scale));
177 break;
178 default: {
179 cairo_t *ct = cairo_create(out);
180 cairo_set_source_rgba(ct, 0, 0, 0, 1);
181 cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
182 cairo_paint(ct);
183 cairo_destroy(ct);
184 break;
185 }
186 }
187
188 slot.set(_output, out);
189 cairo_surface_destroy(out);
190}
191
193{
194 // TODO: support kernelUnitLength
195
196 // We expand the area by 1 in every direction to avoid artifacts on tile edges.
197 // However, it means that edge pixels will be incorrect.
198 area.expandBy(1);
199}
200
202{
203 return 9.0;
204}
205
206} // namespace Filters
207} // namespace Inkscape
208
209/*
210 Local Variables:
211 mode:c++
212 c-file-style:"stroustrup"
213 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
214 indent-tabs-mode:nil
215 fill-column:99
216 End:
217*/
218// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
double scale
Definition aa.cpp:228
Cairo software blending templates.
void ink_cairo_surface_synthesize(cairo_surface_t *out, cairo_rectangle_t const &out_area, Synth &&synth)
Synthesize surface pixels based on their position.
cairo_surface_t * ink_cairo_surface_create_same_size(cairo_surface_t *s, cairo_content_t c)
static guint32 srgb_to_linear(const guint32 c, const guint32 a)
void set_cairo_surface_ci(cairo_surface_t *surface, SPColorInterpolation ci)
Set the color_interpolation_value for a Cairo surface.
Cairo integration helpers.
3x3 matrix representing an affine transformation.
Definition affine.h:70
Coord descrim() const
Calculate the descriminant.
Definition affine.cpp:434
Axis aligned, non-empty, generic rectangle.
void expandBy(C amount)
Expand the rectangle in both directions by the specified amount.
CPoint min() const
Get the corner of the rectangle with smallest coordinate values.
Two-dimensional point that doubles as a vector.
Definition point.h:66
constexpr Coord y() const noexcept
Definition point.h:106
constexpr Coord x() const noexcept
Definition point.h:104
Axis aligned, non-empty rectangle.
Definition rect.h:92
double complexity(Geom::Affine const &ctm) const override
void area_enlarge(Geom::IntRect &area, Geom::Affine const &trans) const override
void render_cairo(FilterSlot &slot) const override
union Inkscape::Filters::FilterDiffuseLighting::@19 light
cairo_surface_t * getcairo(int slot)
Returns the pixblock in specified slot.
void set(int slot, cairo_surface_t *s)
Sets or re-sets the pixblock associated with given slot.
int get_device_scale() const
Gets the device scale; for high DPI monitors.
FilterUnits const & get_units() const
Geom::Affine get_matrix_primitiveunits2pb() const
Gets the primitiveUnits to pixblock coordinates transformation matrix.
constexpr double SP_RGBA32_G_F(uint32_t v)
Definition utils.h:47
constexpr double SP_RGBA32_R_F(uint32_t v)
Definition utils.h:43
constexpr uint32_t SP_RGBA32_F_COMPOSE(double r, double g, double b, double a)
Definition utils.h:64
constexpr double SP_RGBA32_B_F(uint32_t v)
Definition utils.h:51
unsigned int guint32
struct _cairo_surface cairo_surface_t
Helper class to stream background task notifications as a series of messages.
gdouble scalar_product(const Fvector &a, const Fvector &b)
Computes the scalar product between two Fvectors.
Definition of functions needed by several filters.
TODO: insert short description here.
struct _cairo cairo_t
Definition path-cairo.h:16
a type of 3 gdouble components vectors
Definition nr-3dutils.h:29
guint32 alphaAt(int x, int y) const
NR::Fvector surfaceNormalAt(int x, int y, double scale) const
@ SP_CSS_COLOR_INTERPOLATION_LINEARRGB
void cairo_set_source_rgba(cairo_t *cr, colour c)