Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2015-10-15 14:36:31 +0300
committerCampbell Barton <ideasman42@gmail.com>2015-10-15 14:36:31 +0300
commite60d535443824f44cd6e18280570cd066c1b3dc2 (patch)
treebc7c323d0103e58fdc978806b5690df3f8124db3 /source/blender/gpu
parent3de81314fa61f9b123e5d10cbe4176718479be10 (diff)
3D View: support non-uniform scaled lamps
D1378 by @youle Non-uniform scaled lamps now cast oval/rectangular shadows, viewport & BGE.
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/GPU_material.h1
-rw-r--r--source/blender/gpu/intern/gpu_material.c40
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl22
3 files changed, 47 insertions, 16 deletions
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 9a850757496..25a4f33b526 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -160,6 +160,7 @@ typedef enum GPUDynamicType {
GPU_DYNAMIC_LAMP_ATT2 = 9 | GPU_DYNAMIC_GROUP_LAMP,
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_SAMPLER_2DBUFFER = 1 | GPU_DYNAMIC_GROUP_SAMPLER,
GPU_DYNAMIC_SAMPLER_2DIMAGE = 2 | GPU_DYNAMIC_GROUP_SAMPLER,
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 5b647232934..82902f8d69c 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -141,6 +141,7 @@ struct GPULamp {
float dynimat[4][4];
float spotsi, spotbl, k;
+ float spotvec[2];
float dyndist, dynatt1, dynatt2;
float dist, att1, att2;
float shadow_color[3];
@@ -536,12 +537,15 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
if (lamp->type == LA_SPOT) {
if (lamp->mode & LA_SQUARE) {
- mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_IMAT;
- GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), GPU_dynamic_uniform((float*)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob), *lv, &inpr);
+ mat->dynproperty |= DYN_LAMP_VEC | DYN_LAMP_IMAT;
+ GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), GPU_dynamic_uniform((float*)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob),
+ GPU_dynamic_uniform((float *)lamp->spotvec, GPU_DYNAMIC_LAMP_SPOTSCALE, lamp->ob), *lv, &inpr);
}
else {
- mat->dynproperty |= DYN_LAMP_VEC;
- GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), *lv, &inpr);
+ mat->dynproperty |= DYN_LAMP_VEC | DYN_LAMP_IMAT;
+ GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob),
+ GPU_dynamic_uniform((float *)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob),
+ GPU_dynamic_uniform((float *)lamp->spotvec, GPU_DYNAMIC_LAMP_SPOTSCALE, lamp->ob), *lv, &inpr);
}
GPU_link(mat, "lamp_visibility_spot", GPU_dynamic_uniform(&lamp->spotsi, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), inpr, visifac, &visifac);
@@ -1854,24 +1858,41 @@ static void gpu_lamp_calc_winmat(GPULamp *lamp)
temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
pixsize = lamp->d / temp;
wsize = pixsize * 0.5f * lamp->size;
- perspective_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
+ if (lamp->type & LA_SPOT) {
+ /* compute shadows according to X and Y scaling factors */
+ perspective_m4(
+ lamp->winmat,
+ -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0],
+ -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1],
+ lamp->d, lamp->clipend);
+ }
+ else {
+ perspective_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
+ }
}
}
void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4])
{
float mat[4][4];
+ float obmat_scale[3];
lamp->lay = lay;
lamp->hide = hide;
- copy_m4_m4(mat, obmat);
- normalize_m4(mat);
+ normalize_m4_m4_ex(mat, obmat, obmat_scale);
copy_v3_v3(lamp->vec, mat[2]);
copy_v3_v3(lamp->co, mat[3]);
copy_m4_m4(lamp->obmat, mat);
invert_m4_m4(lamp->imat, mat);
+
+ /* update spotlamp scale on X and Y axis */
+ lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2];
+ lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2];
+
+ /* makeshadowbuf */
+ gpu_lamp_calc_winmat(lamp);
}
void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
@@ -1895,8 +1916,6 @@ void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend)
{
lamp->spotsi = cosf(spotsize * 0.5f);
lamp->spotbl = (1.0f - lamp->spotsi) * spotblend;
-
- gpu_lamp_calc_winmat(lamp);
}
static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
@@ -1941,9 +1960,6 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l
/* arbitrary correction for the fact we do no soft transition */
lamp->bias *= 0.25f;
-
- /* makeshadowbuf */
- gpu_lamp_calc_winmat(lamp);
}
static void gpu_lamp_shadow_free(GPULamp *lamp)
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 311fcb8ead2..5b62739b0eb 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1584,11 +1584,13 @@ void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float
outvisifac= visifac*max(t, 0.0)/lampdist;
}
-void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec3 lv, out float inpr)
+void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec2 scale, vec3 lv, out float inpr)
{
if(dot(lv, lampvec) > 0.0) {
vec3 lvrot = (lampimat*vec4(lv, 0.0)).xyz;
- float x = max(abs(lvrot.x/lvrot.z), abs(lvrot.y/lvrot.z));
+ /* without clever non-uniform scale, we could do: */
+ // float x = max(abs(lvrot.x / lvrot.z), abs(lvrot.y / lvrot.z));
+ float x = max(abs((lvrot.x / scale.x) / lvrot.z), abs((lvrot.y / scale.y) / lvrot.z));
inpr = 1.0/sqrt(1.0 + x*x);
}
@@ -1596,9 +1598,21 @@ void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec3 lv, out float
inpr = 0.0;
}
-void lamp_visibility_spot_circle(vec3 lampvec, vec3 lv, out float inpr)
+void lamp_visibility_spot_circle(vec3 lampvec, mat4 lampimat, vec2 scale, vec3 lv, out float inpr)
{
- inpr = dot(lv, lampvec);
+ /* without clever non-uniform scale, we could do: */
+ // inpr = dot(lv, lampvec);
+ if (dot(lv, lampvec) > 0.0) {
+ vec3 lvrot = (lampimat * vec4(lv, 0.0)).xyz;
+ float x = abs(lvrot.x / lvrot.z);
+ float y = abs(lvrot.y / lvrot.z);
+
+ float ellipse = abs((x * x) / (scale.x * scale.x) + (y * y) / (scale.y * scale.y));
+
+ inpr = 1.0 / sqrt(1.0 + ellipse);
+ }
+ else
+ inpr = 0.0;
}
void lamp_visibility_spot(float spotsi, float spotbl, float inpr, float visifac, out float outvisifac)