From 966e86cd2dbe2c627e65766d0361cc79f63d7cc7 Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Thu, 4 Apr 2013 03:55:43 +0000 Subject: [PATCH] Fix for [#34754] "Revision 55527 provokes glitchy GLSL shadow map rendering" reported by Alain Ducharme. Per material uniforms and per object uniforms are now better separated. --- source/blender/gpu/GPU_material.h | 4 +- source/blender/gpu/intern/gpu_draw.c | 4 +- source/blender/gpu/intern/gpu_material.c | 82 +++++++++---------- source/gameengine/Ketsji/BL_BlenderShader.cpp | 23 ++++-- source/gameengine/Ketsji/BL_BlenderShader.h | 2 +- .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 2 +- 6 files changed, 60 insertions(+), 57 deletions(-) diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 17d3ce3cd73..29da72a00fe 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -129,8 +129,8 @@ void GPU_material_free(struct Material *ma); void GPU_materials_free(void); -void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap); -void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float viewinv[4][4], float obcol[4], float autobumpscale); +void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4]); +void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale); void GPU_material_unbind(GPUMaterial *material); int GPU_material_bound(GPUMaterial *material); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index b772507e0cc..c78961e6308 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -1457,10 +1457,10 @@ int GPU_enable_material(int nr, void *attribs) gpumat = GPU_material_from_blender(GMS.gscene, mat); GPU_material_vertex_attributes(gpumat, gattribs); - GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT)); + GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT), GMS.gviewmat, GMS.gviewinv); auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f; - GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gviewinv, GMS.gob->col, auto_bump_scale); + GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gob->col, auto_bump_scale); GMS.gboundmat= mat; /* for glsl use alpha blend mode, unless it's set to solid and diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 999e3b5c20e..075a670e06e 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -257,11 +257,12 @@ void GPU_material_free(Material *ma) BLI_freelistN(&ma->gpumaterial); } -void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap) +void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4]) { if (material->pass) { LinkData *nlink; GPULamp *lamp; + GPUShader *shader = GPU_pass_shader(material->pass); /* handle layer lamps */ for (nlink=material->lamps.first; nlink; nlink=nlink->next) { @@ -275,47 +276,6 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim lamp->dynenergy = 0.0f; lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f; } - } - - GPU_pass_bind(material->pass, time, mipmap); - GPU_pass_update_uniforms(material->pass); - material->bound = 1; - } -} - -void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float viewinv[4][4], float obcol[4], float autobumpscale) -{ - if (material->pass) { - GPUShader *shader = GPU_pass_shader(material->pass); - LinkData *nlink; - GPULamp *lamp; - float invmat[4][4], col[4]; - - /* handle builtins */ - if (material->builtins & GPU_VIEW_MATRIX) { - GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float*)viewmat); - } - if (material->builtins & GPU_INVERSE_VIEW_MATRIX) { - GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv); - } - if (material->builtins & GPU_OBJECT_MATRIX) { - GPU_shader_uniform_vector(shader, material->obmatloc, 16, 1, (float*)obmat); - } - if (material->builtins & GPU_INVERSE_OBJECT_MATRIX) { - invert_m4_m4(invmat, obmat); - GPU_shader_uniform_vector(shader, material->invobmatloc, 16, 1, (float*)invmat); - } - if (material->builtins & GPU_OBCOLOR) { - copy_v4_v4(col, obcol); - CLAMP(col[3], 0.0f, 1.0f); - GPU_shader_uniform_vector(shader, material->obcolloc, 4, 1, col); - } - if (material->builtins & GPU_AUTO_BUMPSCALE) { - GPU_shader_uniform_vector(shader, material->obautobumpscaleloc, 1, 1, &autobumpscale); - } - /* update lamps */ - for (nlink=material->lamps.first; nlink; nlink=nlink->next) { - lamp= nlink->data; if (material->dynproperty & DYN_LAMP_VEC) { copy_v3_v3(lamp->dynvec, lamp->vec); @@ -339,6 +299,44 @@ void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float mult_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv); } } + + /* handle per material built-ins */ + if (material->builtins & GPU_VIEW_MATRIX) { + GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float*)viewmat); + } + if (material->builtins & GPU_INVERSE_VIEW_MATRIX) { + GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv); + } + + GPU_pass_bind(material->pass, time, mipmap); + GPU_pass_update_uniforms(material->pass); + + material->bound = 1; + } +} + +void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale) +{ + if (material->pass) { + GPUShader *shader = GPU_pass_shader(material->pass); + float invmat[4][4], col[4]; + + /* handle per object builtins */ + if (material->builtins & GPU_OBJECT_MATRIX) { + GPU_shader_uniform_vector(shader, material->obmatloc, 16, 1, (float*)obmat); + } + if (material->builtins & GPU_INVERSE_OBJECT_MATRIX) { + invert_m4_m4(invmat, obmat); + GPU_shader_uniform_vector(shader, material->invobmatloc, 16, 1, (float*)invmat); + } + if (material->builtins & GPU_OBCOLOR) { + copy_v4_v4(col, obcol); + CLAMP(col[3], 0.0f, 1.0f); + GPU_shader_uniform_vector(shader, material->obcolloc, 4, 1, col); + } + if (material->builtins & GPU_AUTO_BUMPSCALE) { + GPU_shader_uniform_vector(shader, material->obautobumpscaleloc, 1, 1, &autobumpscale); + } } } diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index f5f9b344b87..3f2a9a6df6a 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -46,11 +46,20 @@ void BL_BlenderShader::ReloadMaterial() mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat) : NULL; } -void BL_BlenderShader::SetProg(bool enable, double time) +void BL_BlenderShader::SetProg(bool enable, double time, RAS_IRasterizer* rasty) { if (VerifyShader()) { - if (enable) - GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1); + if (enable) { + assert(rasty != NULL); // XXX Kinda hacky, but SetProg() should always have the rasterizer if enable is true + + float viewmat[4][4], viewinvmat[4][4]; + const MT_Matrix4x4& view = rasty->GetViewMatrix(); + const MT_Matrix4x4& viewinv = rasty->GetViewInvMatrix(); + view.getValue((float*)viewmat); + viewinv.getValue((float*)viewinvmat); + + GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1, viewmat, viewinvmat); + } else GPU_material_unbind(mGPUMat); } @@ -120,7 +129,7 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) { - float obmat[4][4], viewmat[4][4], viewinvmat[4][4], obcol[4]; + float obmat[4][4], obcol[4]; GPUMaterial *gpumat; gpumat = mGPUMat; @@ -130,13 +139,9 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) MT_Matrix4x4 model; model.setValue(ms.m_OpenGLMatrix); - const MT_Matrix4x4& view = rasty->GetViewMatrix(); - const MT_Matrix4x4& viewinv = rasty->GetViewInvMatrix(); // note: getValue gives back column major as needed by OpenGL model.getValue((float*)obmat); - view.getValue((float*)viewmat); - viewinv.getValue((float*)viewinvmat); if (ms.m_bObjectColor) ms.m_RGBAcolor.getValue((float *)obcol); @@ -144,7 +149,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) obcol[0] = obcol[1] = obcol[2] = obcol[3] = 1.0f; float auto_bump_scale = ms.m_pDerivedMesh!=0 ? ms.m_pDerivedMesh->auto_bump_scale : 1.0f; - GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol, auto_bump_scale); + GPU_material_bind_uniforms(gpumat, obmat, obcol, auto_bump_scale); mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol); } diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h index 626c65baadd..71f66c2a49d 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.h +++ b/source/gameengine/Ketsji/BL_BlenderShader.h @@ -78,7 +78,7 @@ public: // same as VerifyShared return (NULL != mGPUMat); } - void SetProg(bool enable, double time=0.0); + void SetProg(bool enable, double time=0.0, RAS_IRasterizer* rasty=NULL); int GetAttribNum(); void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 231ec27030d..853cfa53da2 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -314,7 +314,7 @@ void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras else BL_Texture::DisableAllTextures(); - mBlenderShader->SetProg(true, ras->GetTime()); + mBlenderShader->SetProg(true, ras->GetTime(), ras); mLastBlenderShader= mBlenderShader; } }