From 861616bf693b78b070ada6cbc6aa79eb807fdde8 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sun, 13 Mar 2016 02:00:12 +0100 Subject: Full Inverse-Quadratic-Equation Lamp Falloff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a new `falloff_type` ('Inverse Coefficients') for Lamps in Blender-Internal and GLSL. The current falloff modes use a formula like this inverse-square one: `I = E × (D^2 / (D^2 + Q × r^2))` While such a formula is simple for 3D-artists to use, it's algebraically cumbersome to work with. Game-designers authoring their own shaders could benefit much more by having direct control of falloff-coefficients: `I = E × (1.0 / (coefC + coefL × r + coefQ × r^2))` In this mode, the `distance` parameter is unused (except for 'Sphere' mode); instead relying on the designer to mathematically-model the falloff-behavior. The UI has been patched like so: {F153843} Reviewers: brecht, psy-fi Reviewed By: psy-fi Subscribers: brita_, antidote, campbellbarton, psy-fi Differential Revision: https://developer.blender.org/D1194 --- .../scripts/startup/bl_ui/properties_data_lamp.py | 7 +++++++ source/blender/blenkernel/intern/lamp.c | 3 +++ source/blender/gpu/GPU_material.h | 6 +++++- source/blender/gpu/intern/gpu_material.c | 16 +++++++++++++++- .../blender/gpu/shaders/gpu_shader_material.glsl | 11 +++++++++++ source/blender/makesdna/DNA_lamp_types.h | 10 ++++++---- source/blender/makesrna/intern/rna_lamp.c | 22 ++++++++++++++++++++++ .../blender/render/intern/include/render_types.h | 1 + .../blender/render/intern/source/convertblender.c | 3 +++ source/blender/render/intern/source/shadeoutput.c | 11 ++++++++++- .../Converter/BL_BlenderDataConversion.cpp | 3 +++ source/gameengine/Rasterizer/RAS_ILightObject.h | 1 + .../RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp | 4 ++-- 13 files changed, 89 insertions(+), 9 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_lamp.py b/release/scripts/startup/bl_ui/properties_data_lamp.py index 0121ad46c86..30cd39d2e2f 100644 --- a/release/scripts/startup/bl_ui/properties_data_lamp.py +++ b/release/scripts/startup/bl_ui/properties_data_lamp.py @@ -103,6 +103,13 @@ class DATA_PT_lamp(DataButtonsPanel, Panel): sub.prop(lamp, "linear_attenuation", slider=True, text="Linear") sub.prop(lamp, "quadratic_attenuation", slider=True, text="Quadratic") + elif lamp.falloff_type == 'INVERSE_COEFFICIENTS': + col.label(text="Inverse Coefficients:") + sub = col.column(align=True) + sub.prop(lamp, "constant_coefficient", text="Constant") + sub.prop(lamp, "linear_coefficient", text="Linear") + sub.prop(lamp, "quadratic_coefficient", text="Quadratic") + col.prop(lamp, "use_sphere") if lamp.type == 'AREA': diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 9601a93b1f1..49a573489ef 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -79,6 +79,9 @@ void BKE_lamp_init(Lamp *la) la->adapt_thresh = 0.001f; la->preview = NULL; la->falloff_type = LA_FALLOFF_INVSQUARE; + la->coeff_const = 1.0f; + la->coeff_lin = 0.0f; + la->coeff_quad = 0.0f; la->curfalloff = curvemapping_add(1, 0.0f, 1.0f, 1.0f, 0.0f); la->sun_effect_type = 0; la->horizon_brightness = 1.0; diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 3bcc7e23f06..f150b7215e1 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -166,6 +166,9 @@ typedef enum GPUDynamicType { GPU_DYNAMIC_LAMP_SPOTSIZE = 10 | GPU_DYNAMIC_GROUP_LAMP, GPU_DYNAMIC_LAMP_SPOTBLEND = 11 | GPU_DYNAMIC_GROUP_LAMP, GPU_DYNAMIC_LAMP_SPOTSCALE = 12 | GPU_DYNAMIC_GROUP_LAMP, + GPU_DYNAMIC_LAMP_COEFFCONST = 13 | GPU_DYNAMIC_GROUP_LAMP, + GPU_DYNAMIC_LAMP_COEFFLIN = 14 | GPU_DYNAMIC_GROUP_LAMP, + GPU_DYNAMIC_LAMP_COEFFQUAD = 15 | GPU_DYNAMIC_GROUP_LAMP, GPU_DYNAMIC_SAMPLER_2DBUFFER = 1 | GPU_DYNAMIC_GROUP_SAMPLER, GPU_DYNAMIC_SAMPLER_2DIMAGE = 2 | GPU_DYNAMIC_GROUP_SAMPLER, @@ -318,7 +321,8 @@ float *GPU_lamp_dynpersmat(GPULamp *lamp); void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]); void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy); -void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2); +void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2, + float coeff_const, float coeff_lin, float coeff_quad); void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend); int GPU_lamp_shadow_layer(GPULamp *lamp); GPUNodeLink *GPU_lamp_get_data( diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index cc401dc63c4..c32326889d1 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -148,6 +148,7 @@ struct GPULamp { float spotvec[2]; float dyndist, dynatt1, dynatt2; float dist, att1, att2; + float coeff_const, coeff_lin, coeff_quad; float shadow_color[3]; float bias, d, clipend; @@ -550,6 +551,12 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode GPU_dynamic_uniform(&lamp->att1, GPU_DYNAMIC_LAMP_ATT1, lamp->ob), GPU_dynamic_uniform(&lamp->att2, GPU_DYNAMIC_LAMP_ATT2, lamp->ob), *dist, &visifac); break; + case LA_FALLOFF_INVCOEFFICIENTS: + GPU_link(mat, "lamp_falloff_invcoefficients", + GPU_dynamic_uniform(&lamp->coeff_const, GPU_DYNAMIC_LAMP_COEFFCONST, lamp->ob), + GPU_dynamic_uniform(&lamp->coeff_lin, GPU_DYNAMIC_LAMP_COEFFLIN, lamp->ob), + GPU_dynamic_uniform(&lamp->coeff_quad, GPU_DYNAMIC_LAMP_COEFFQUAD, lamp->ob), *dist, &visifac); + break; case LA_FALLOFF_CURVE: { float *array; @@ -2209,11 +2216,15 @@ void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float ener lamp->col[2] = b; } -void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2) +void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2, + float coeff_const, float coeff_lin, float coeff_quad) { lamp->dist = distance; lamp->att1 = att1; lamp->att2 = att2; + lamp->coeff_const = coeff_const; + lamp->coeff_lin = coeff_lin; + lamp->coeff_quad = coeff_quad; } void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend) @@ -2254,6 +2265,9 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l lamp->falloff_type = la->falloff_type; lamp->att1 = la->att1; lamp->att2 = la->att2; + lamp->coeff_const = la->coeff_const; + lamp->coeff_lin = la->coeff_lin; + lamp->coeff_quad = la->coeff_quad; lamp->curfalloff = la->curfalloff; /* initshadowbuf */ diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 51d4706d91e..05853c3e2d3 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -1627,6 +1627,17 @@ void lamp_falloff_sliders(float lampdist, float ld1, float ld2, float dist, out visifac *= lampdistkw/(lampdistkw + ld2*dist*dist); } +void lamp_falloff_invcoefficients(float coeff_const, float coeff_lin, float coeff_quad, float dist, out float visifac) +{ + vec3 coeff = vec3(coeff_const, coeff_lin, coeff_quad); + vec3 d_coeff = vec3(1.0, dist, dist*dist); + float visifac_r = dot(coeff, d_coeff); + if (visifac_r > 0.0) + visifac = 1.0 / visifac_r; + else + visifac = 0.0; +} + void lamp_falloff_curve(float lampdist, sampler2D curvemap, float dist, out float visifac) { visifac = texture2D(curvemap, vec2(dist/lampdist, 0.0)).x; diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h index 8f0112294f3..a2e39f93875 100644 --- a/source/blender/makesdna/DNA_lamp_types.h +++ b/source/blender/makesdna/DNA_lamp_types.h @@ -61,6 +61,7 @@ typedef struct Lamp { float att1, att2; /* Quad1 and Quad2 attenuation */ + float coeff_const, coeff_lin, coeff_quad, coeff_pad; struct CurveMapping *curfalloff; short falloff_type; short pad2; @@ -161,11 +162,12 @@ typedef struct Lamp { #define LA_SUN_EFFECT_AP 2 /* falloff_type */ -#define LA_FALLOFF_CONSTANT 0 +#define LA_FALLOFF_CONSTANT 0 #define LA_FALLOFF_INVLINEAR 1 -#define LA_FALLOFF_INVSQUARE 2 -#define LA_FALLOFF_CURVE 3 -#define LA_FALLOFF_SLIDERS 4 +#define LA_FALLOFF_INVSQUARE 2 +#define LA_FALLOFF_CURVE 3 +#define LA_FALLOFF_SLIDERS 4 +#define LA_FALLOFF_INVCOEFFICIENTS 5 /* buftype, no flag */ diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index 85a2623dc35..b6b97d37c0f 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -420,6 +420,7 @@ static void rna_def_lamp_falloff(StructRNA *srna) {LA_FALLOFF_CONSTANT, "CONSTANT", 0, "Constant", ""}, {LA_FALLOFF_INVLINEAR, "INVERSE_LINEAR", 0, "Inverse Linear", ""}, {LA_FALLOFF_INVSQUARE, "INVERSE_SQUARE", 0, "Inverse Square", ""}, + {LA_FALLOFF_INVCOEFFICIENTS, "INVERSE_COEFFICIENTS", 0, "Inverse Coefficients", ""}, {LA_FALLOFF_CURVE, "CUSTOM_CURVE", 0, "Custom Curve", ""}, {LA_FALLOFF_SLIDERS, "LINEAR_QUADRATIC_WEIGHTED", 0, "Lin/Quad Weighted", ""}, {0, NULL, 0, NULL, NULL} @@ -451,6 +452,27 @@ static void rna_def_lamp_falloff(StructRNA *srna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Quadratic Attenuation", "Quadratic distance attenuation"); RNA_def_property_update(prop, 0, "rna_Lamp_draw_update"); + + prop = RNA_def_property(srna, "constant_coefficient", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "coeff_const"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_text(prop, "Constant Coefficient", + "Constant distance attenuation coefficient"); + RNA_def_property_update(prop, 0, "rna_Lamp_draw_update"); + + prop = RNA_def_property(srna, "linear_coefficient", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "coeff_lin"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_text(prop, "Linear Coefficient", + "Linear distance attenuation coefficient"); + RNA_def_property_update(prop, 0, "rna_Lamp_draw_update"); + + prop = RNA_def_property(srna, "quadratic_coefficient", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "coeff_quad"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_text(prop, "Quadratic Coefficient", + "Quadratic distance attenuation coefficient"); + RNA_def_property_update(prop, 0, "rna_Lamp_draw_update"); } static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area) diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index ed83cfec764..cef3a073084 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -569,6 +569,7 @@ typedef struct LampRen { short falloff_type; float ld1, ld2; + float coeff_const, coeff_lin, coeff_quad; struct CurveMapping *curfalloff; /* copied from Lamp, to decouple more rendering stuff */ diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 64fd56715c7..ccf54cb6bcd 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -3801,6 +3801,9 @@ static GroupObject *add_render_lamp(Render *re, Object *ob) lar->falloff_type = la->falloff_type; lar->ld1= la->att1; lar->ld2= la->att2; + lar->coeff_const= la->coeff_const; + lar->coeff_lin= la->coeff_lin; + lar->coeff_quad= la->coeff_quad; lar->curfalloff = curvemapping_copy(la->curfalloff); if (lar->curfalloff) { diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 71b409dbba7..9dec2698720 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -1188,7 +1188,7 @@ float lamp_get_visibility(LampRen *lar, const float co[3], float lv[3], float *d return 1.0f; } else { - float visifac= 1.0f; + float visifac= 1.0f, visifac_r; sub_v3_v3v3(lv, co, lar->co); mul_v3_fl(lv, 1.0f / (*dist = len_v3(lv))); @@ -1223,6 +1223,15 @@ float lamp_get_visibility(LampRen *lar, const float co[3], float lv[3], float *d if (lar->ld2>0.0f) visifac*= lar->distkw/(lar->distkw+lar->ld2*dist[0]*dist[0]); break; + case LA_FALLOFF_INVCOEFFICIENTS: + visifac_r = lar->coeff_const + + lar->coeff_lin * dist[0] + + lar->coeff_quad * dist[0] * dist[0]; + if (visifac_r > 0.0) + visifac = 1.0 / visifac_r; + else + visifac = 0.0; + break; case LA_FALLOFF_CURVE: /* curvemapping_initialize is called from #add_render_lamp */ visifac = curvemapping_evaluateF(lar->curfalloff, 0, dist[0]/lar->dist); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 20281eb986e..c2cfd8808a9 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1417,6 +1417,9 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l lightobj->m_att1 = la->att1; lightobj->m_att2 = (la->mode & LA_QUAD) ? la->att2 : 0.0f; + lightobj->m_coeff_const = la->coeff_const; + lightobj->m_coeff_lin = la->coeff_lin; + lightobj->m_coeff_quad = la->coeff_quad; lightobj->m_color[0] = la->r; lightobj->m_color[1] = la->g; lightobj->m_color[2] = la->b; diff --git a/source/gameengine/Rasterizer/RAS_ILightObject.h b/source/gameengine/Rasterizer/RAS_ILightObject.h index 59475200a73..a3d55c925d6 100644 --- a/source/gameengine/Rasterizer/RAS_ILightObject.h +++ b/source/gameengine/Rasterizer/RAS_ILightObject.h @@ -69,6 +69,7 @@ public: float m_att1; float m_att2; + float m_coeff_const, m_coeff_lin, m_coeff_quad; float m_spotsize; float m_spotblend; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp index 7639189a6f0..e15ae4bd0d7 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp @@ -59,7 +59,7 @@ RAS_OpenGLLight::~RAS_OpenGLLight() if ((lamp = GetGPULamp())) { float obmat[4][4] = {{0}}; GPU_lamp_update(lamp, 0, 0, obmat); - GPU_lamp_update_distance(lamp, la->dist, la->att1, la->att2); + GPU_lamp_update_distance(lamp, la->dist, la->att1, la->att2, la->coeff_const, la->coeff_lin, la->coeff_quad); GPU_lamp_update_spot(lamp, la->spotsize, la->spotblend); } } @@ -291,7 +291,7 @@ void RAS_OpenGLLight::Update() GPU_lamp_update(lamp, m_layer, hide, obmat); GPU_lamp_update_colors(lamp, m_color[0], m_color[1], m_color[2], m_energy); - GPU_lamp_update_distance(lamp, m_distance, m_att1, m_att2); + GPU_lamp_update_distance(lamp, m_distance, m_att1, m_att2, m_coeff_const, m_coeff_lin, m_coeff_quad); GPU_lamp_update_spot(lamp, m_spotsize, m_spotblend); } } -- cgit v1.2.3