From 76875f0a3c4912b4022b25a127b43fb9f8c28a2f Mon Sep 17 00:00:00 2001 From: Emile Belanger Date: Mon, 20 Sep 2021 20:51:56 +0100 Subject: [PATCH] Fix spot lights for GLES --- .../rendering/gles/gles_renderstate.cpp | 31 ++++++++++++------- src/common/rendering/gles/gles_shader.cpp | 31 ++++++++++--------- src/common/rendering/gles/gles_shader.h | 5 +++ wadsrc/static/shaders_gles/glsl/main.vp | 3 -- .../shaders_gles/glsl/material_normal.fp | 10 ++++-- 5 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/common/rendering/gles/gles_renderstate.cpp b/src/common/rendering/gles/gles_renderstate.cpp index b0ffd6c0f7..fa2561d175 100644 --- a/src/common/rendering/gles/gles_renderstate.cpp +++ b/src/common/rendering/gles/gles_renderstate.cpp @@ -92,11 +92,16 @@ bool FGLRenderState::ApplyShader() { static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; + ShaderFlavourData flavour; + // Need to calc light data now in order to select correct shader float* lightPtr = NULL; int modLights = 0; int subLights = 0; int addLights = 0; + int totalLights = 0; + + flavour.hasSpotLight = false; if (mLightIndex >= 0) { @@ -119,13 +124,25 @@ bool FGLRenderState::ApplyShader() if (modLights + subLights + addLights > gles.maxlights) addLights = gles.maxlights - modLights - subLights; - + + totalLights = modLights + subLights + addLights; // Skip passed the first 4 floats so the upload below only contains light data lightPtr += 4; + + float* findSpotsPtr = lightPtr + 11; // The 11th float contains '1' if the light is a spot light, see hw_dynlightdata.cpp + + for (int n = 0; n < totalLights; n++) + { + if (*findSpotsPtr > 0) // This is a spot light + { + flavour.hasSpotLight = true; + break; + } + findSpotsPtr += LIGHT_VEC4_NUM * 4; + } } - ShaderFlavourData flavour; flavour.textureMode = (mTextureMode == TM_NORMAL && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode) & 0xff; if (mTextureClamp && flavour.textureMode == TM_NORMAL) flavour.textureMode = 5; // fixme. Clamp can now be combined with all modes. @@ -199,14 +216,10 @@ bool FGLRenderState::ApplyShader() if (mHwUniforms) { - //matrixToGL(mHwUniforms->mProjectionMatrix, activeShader->cur->ProjectionMatrix_index); activeShader->cur->muProjectionMatrix.Set(&mHwUniforms->mProjectionMatrix); activeShader->cur->muViewMatrix.Set(&mHwUniforms->mViewMatrix); activeShader->cur->muNormalViewMatrix.Set(&mHwUniforms->mNormalViewMatrix); - //matrixToGL(mHwUniforms->mViewMatrix, activeShader->cur->ViewMatrix_index); - //matrixToGL(mHwUniforms->mNormalViewMatrix, activeShader->cur->NormalViewMatrix_index); - activeShader->cur->muCameraPos.Set(&mHwUniforms->mCameraPos.X); activeShader->cur->muClipLine.Set(&mHwUniforms->mClipLine.X); @@ -318,13 +331,9 @@ bool FGLRenderState::ApplyShader() // Upload the light data if (mLightIndex >= 0) { - int totalLights = modLights + subLights + addLights; - // Calculate the total number of vec4s we need int totalVectors = totalLights * LIGHT_VEC4_NUM; - - // TODO!!! If there are too many lights we need to remove some of the lights and modify the data - // At the moment the shader will just try to read off the end of the array... + if (totalVectors > gles.numlightvectors) totalVectors = gles.numlightvectors; diff --git a/src/common/rendering/gles/gles_shader.cpp b/src/common/rendering/gles/gles_shader.cpp index 4587fd84ad..37a9fd7eda 100644 --- a/src/common/rendering/gles/gles_shader.cpp +++ b/src/common/rendering/gles/gles_shader.cpp @@ -633,11 +633,11 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * char stringbuf[20]; mysnprintf(stringbuf, 20, "texture%d", i); int tempindex = glGetUniformLocation(shaderData->hShader, stringbuf); - if (tempindex > 0) glUniform1i(tempindex, i - 1); + if (tempindex >= 0) glUniform1i(tempindex, i - 1); } int shadowmapindex = glGetUniformLocation(shaderData->hShader, "ShadowMap"); - if (shadowmapindex > 0) glUniform1i(shadowmapindex, 16); + if (shadowmapindex >= 0) glUniform1i(shadowmapindex, 16); glUseProgram(0); @@ -654,13 +654,17 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * FShader::~FShader() { - /* - glDeleteProgram(hShader); - if (hVertProg != 0) - glDeleteShader(hVertProg); - if (hFragProg != 0) - glDeleteShader(hFragProg); - */ + std::map::iterator it = variants.begin(); + + while (it != variants.end()) + { + glDeleteProgram(it->second->hShader); + if (it->second->hVertProg != 0) + glDeleteShader(it->second->hVertProg); + if (it->second->hFragProg != 0) + glDeleteShader(it->second->hFragProg); + it++; + } } @@ -710,14 +714,13 @@ bool FShader::Bind(ShaderFlavourData& flavour) variantConfig.AppendFormat("#define DEF_NPOT_EMULATION %d\n", flavour.npotEmulation); #endif - // Printf("Shader: %s, %08x %s", mFragProg2.GetChars(), tag, variantConfig.GetChars()); + variantConfig.AppendFormat("#define DEF_HAS_SPOTLIGHT %d\n", flavour.hasSpotLight); + + //Printf("Shader: %s, %08x %s", mFragProg2.GetChars(), tag, variantConfig.GetChars()); Load(mName.GetChars(), mVertProg, mFragProg, mFragProg2, mLightProg, mDefinesBase + variantConfig); - if (variants.insert(std::make_pair(tag, cur)).second == false) - { - Printf("ERROR INSERTING"); - } + variants.insert(std::make_pair(tag, cur)); } else { diff --git a/src/common/rendering/gles/gles_shader.h b/src/common/rendering/gles/gles_shader.h index 7f07c8615b..66fcb1ebd5 100644 --- a/src/common/rendering/gles/gles_shader.h +++ b/src/common/rendering/gles/gles_shader.h @@ -275,6 +275,8 @@ public: #ifdef NPOT_EMULATION bool npotEmulation; #endif + + bool hasSpotLight; }; class FShader @@ -417,6 +419,9 @@ public: #ifdef NPOT_EMULATION tag |= (flavour.npotEmulation & 1) << 22; #endif + + tag |= (flavour.hasSpotLight & 1) << 23; + return tag; } diff --git a/wadsrc/static/shaders_gles/glsl/main.vp b/wadsrc/static/shaders_gles/glsl/main.vp index 1e87864c10..9d78e38a1f 100644 --- a/wadsrc/static/shaders_gles/glsl/main.vp +++ b/wadsrc/static/shaders_gles/glsl/main.vp @@ -127,8 +127,5 @@ void main() ClipDistanceA = vec4(ClipDistance0, ClipDistance1, ClipDistance2, ClipDistance3); ClipDistanceB = vec4(ClipDistance4, 0.0, 0.0, 0.0); - - //gl_PointSize = 1.0; - gl_Position = ProjectionMatrix * eyeCoordPos; } diff --git a/wadsrc/static/shaders_gles/glsl/material_normal.fp b/wadsrc/static/shaders_gles/glsl/material_normal.fp index 61d8abbee7..76bad4c934 100644 --- a/wadsrc/static/shaders_gles/glsl/material_normal.fp +++ b/wadsrc/static/shaders_gles/glsl/material_normal.fp @@ -19,7 +19,13 @@ vec3 lightContribution(int i, vec3 normal) float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0); - // NOTE, all spot light stuff gone +#if (DEF_HAS_SPOTLIGHT == 1) // Only perform test below if there are ANY spot lights on this surface. + + if (lightspot1.w == 1.0) + attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y); + +#endif + return lightcolor.rgb * attenuation; /* @@ -55,7 +61,7 @@ vec3 ProcessMaterialLight(Material material, vec3 color) // modulated lights // Some very old GLES2 hardward does not allow non-constants in a for-loop expression because it can not unroll it. - // However they do allow 'break' and use stupid hack + // However they do allow 'break', so use stupid hack #if (USE_GLSL_V100 == 1) for(int i = 0; i < 8; i++) // Max 8 lights