From 75d2bf91bf8d74fb76b950afa7af764dea31b0d5 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Tue, 1 Apr 2014 18:11:00 +0200 Subject: [PATCH] GL3: Even more refactoring --HG-- branch : opengl3 --- .../src/3d/driver/opengl3/driver_opengl.cpp | 10 ++ .../opengl3/driver_opengl_pixel_program.cpp | 135 ++++++++++++------ .../driver/opengl3/driver_opengl_program.cpp | 5 +- .../3d/driver/opengl3/driver_opengl_program.h | 10 +- 4 files changed, 109 insertions(+), 51 deletions(-) diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl.cpp b/code/nel/src/3d/driver/opengl3/driver_opengl.cpp index 7d2459c9e..462549770 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl.cpp +++ b/code/nel/src/3d/driver/opengl3/driver_opengl.cpp @@ -315,6 +315,8 @@ CDriverGL3::CDriverGL3() m_DriverGeometryProgram = NULL; m_DriverPixelProgram = NULL; + m_VPBuiltinTouched = true; + shaderGenerator = new CGLSLShaderGenerator(); usrShaderManager = new CUsrShaderManager(); @@ -690,6 +692,14 @@ bool CDriverGL3::release() m_UserGeometryProgram = NULL; m_UserPixelProgram = NULL; + // Delete all cached programs + for (std::set::iterator it(m_VPBuiltinCache.begin()), end(m_VPBuiltinCache.end()); it != end; ++it) + delete it->VertexProgram; + m_VPBuiltinCache.clear(); + for (std::set::iterator it(m_PPBuiltinCache.begin()), end(m_PPBuiltinCache.end()); it != end; ++it) + delete it->PixelProgram; + m_PPBuiltinCache.clear(); + // Call IDriver::release() before, to destroy textures, shaders and VBs... IDriver::release(); diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl_pixel_program.cpp b/code/nel/src/3d/driver/opengl3/driver_opengl_pixel_program.cpp index 72c030144..6d2ba9a1f 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_pixel_program.cpp +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_pixel_program.cpp @@ -62,6 +62,8 @@ bool operator<(const CPPBuiltin &left, const CPPBuiltin &right) // Material state if (left.Shader != right.Shader) return left.Shader < right.Shader; + if (left.Flags != right.Flags) + return left.Flags < right.Flags; if (left.TextureActive != right.TextureActive) return left.TextureActive < right.TextureActive; uint maxTex = maxTextures(left.Shader); @@ -78,6 +80,8 @@ bool operator<(const CPPBuiltin &left, const CPPBuiltin &right) // Driver state if (left.VertexFormat != right.VertexFormat) return left.VertexFormat < right.VertexFormat; + if (left.Lighting != right.Lighting) + return left.Lighting < right.Lighting; if (left.Fog != right.Fog) return right.Fog; @@ -143,7 +147,7 @@ void ppTexEnv(std::stringstream &ss, const CPPBuiltin &desc) break; } case CMaterial::Diffuse: - rgbArgVec << "diffuse"; + rgbArgVec << "fragColor"; break; case CMaterial::Constant: rgbArgVec << "constant" << stage; @@ -183,7 +187,7 @@ void ppTexEnv(std::stringstream &ss, const CPPBuiltin &desc) break; } case CMaterial::Diffuse: - alphaArgVec << "diffuse"; + alphaArgVec << "fragColor"; break; case CMaterial::Constant: alphaArgVec << "constant" << stage; @@ -222,7 +226,7 @@ void ppTexEnv(std::stringstream &ss, const CPPBuiltin &desc) break; } case CMaterial::InterpolateDiffuse: - ss << "float texop" << stage << "rgbAs = diffuse.a;" << std::endl; + ss << "float texop" << stage << "rgbAs = fragColor.a;" << std::endl; break; case CMaterial::InterpolateTexture: ss << "float texop" << stage << "rgbAs = texel" << stage << ".a;" << std::endl; @@ -268,7 +272,7 @@ void ppTexEnv(std::stringstream &ss, const CPPBuiltin &desc) break; } case CMaterial::InterpolateDiffuse: - ss << "float texop" << stage << "alphaAs = diffuse.a;" << std::endl; + ss << "float texop" << stage << "alphaAs = fragColor.a;" << std::endl; break; case CMaterial::InterpolateTexture: ss << "float texop" << stage << "alphaAs = texel" << stage << ".a;" << std::endl; @@ -303,7 +307,7 @@ void ppTexEnv(std::stringstream &ss, const CPPBuiltin &desc) } else if (stage == 0) { - ss << "vec4 texop" << stage << " = diffuse; // no active texture in stage" << std::endl; + ss << "vec4 texop" << stage << " = fragColor; // no active texture in stage" << std::endl; } else { @@ -315,8 +319,8 @@ void ppTexEnv(std::stringstream &ss, const CPPBuiltin &desc) void ppSpecular(std::stringstream &ss, const CPPBuiltin &desc) { - ss << "vec3 specop0 = texel0.rgb * diffuse.rgb;" << std::endl; - ss << "vec4 specop1 = vec4(texel1.rgb * texel0.a + specop0, diffuse.a);" << std::endl; + ss << "vec3 specop0 = texel0.rgb * fragColor.rgb;" << std::endl; + ss << "vec4 specop1 = vec4(texel1.rgb * texel0.a + specop0, fragColor.a);" << std::endl; ss << "fragColor = specop1;" << std::endl; } @@ -352,18 +356,25 @@ void ppGenerate(std::string &result, const CPPBuiltin &desc) << " sampler" << stage << ";" << std::endl; } } + ss << std::endl; // ??? ss << "uniform vec4 materialColor;" << std::endl; // ?! what is this doing in PP + ss << std::endl; // TexEnv - ss << "uniform vec4 constant0;" << std::endl; // todo: we can optimize this by env!... + ss << "uniform vec4 constant0;" << std::endl; // FIXME: we must optimize this by texenv!... ss << "uniform vec4 constant1;" << std::endl; ss << "uniform vec4 constant2;" << std::endl; ss << "uniform vec4 constant3;" << std::endl; + ss << std::endl; // Alpha test - ss << "uniform float alphaTreshold;" << std::endl; // FIXME: only when driver state has alpha test.... oooh + if (desc.Flags & IDRV_MAT_ALPHA_TEST) + { + ss << "uniform float alphaTreshold;" << std::endl; + ss << std::endl; + } // Fog if (desc.Fog) // FIXME: FogMode! @@ -378,74 +389,94 @@ void ppGenerate(std::string &result, const CPPBuiltin &desc) }*/ ss << "smooth in vec4 ecPos;" << std::endl; + + /*switch(desc->getFogMode()) + { + case CShaderDesc::Linear: + ss << "vec4 applyFog(vec4 col)" << std::endl; + ss << "{" << std::endl; + ss << "float z = ecPos.z / ecPos.w;" << std::endl; + ss << "z = abs(z);" << std::endl; + ss << "float fogFactor = (fogEnd - z) / (fogEnd - fogStart);" << std::endl; + ss << "fogFactor = clamp(fogFactor, 0.0, 1.0);" << std::endl; + ss << "vec4 fColor = mix(fogColor, col, fogFactor);" << std::endl; + ss << "return fColor;" << std::endl; + ss << "}" << std::endl; + ss << std::endl; + break; + }*/ + + ss << std::endl; } - ss << std::endl; - /*if (desc->lightingEnabled()) + if (desc.Lighting) { - addLightUniformsFS(); - addLightInsFS(); - ss << std::endl; - - addLightsFunctionFS(); + ss << "smooth in vec4 lightColor;" << std::endl; // TODO: We probably will always have an incoming vertex color with vertex and light etc premixed. ss << std::endl; } - - if (desc->fogEnabled()) - addFogFunction();*/ ss << "void main(void)" << std::endl; ss << "{" << std::endl; // Light color - /*ss << "vec4 diffuse = vec4(1.0, 1.0, 1.0, 1.0);" << std::endl; - if (desc->lightingEnabled()) + ss << "fragColor = vec4(1.0, 1.0, 1.0, 1.0);" << std::endl; + if (desc.Lighting) + { + ss << "fragColor = lightColor;" << std::endl; + ss << "fragColor.a = 1.0;" << std::endl; + } + if (hasFlag(desc.VertexFormat, g_VertexFlags[PrimaryColor])) // TODO: What about secondary color? { - ss << "diffuse = applyLights(diffuse);" << std::endl; - ss << "diffuse.a = 1.0;" << std::endl; + ss << "fragColor = primaryColor * fragColor;" << std::endl; // TODO: If this is the correct location, we should premultiply light and color in VS. } - if (hasFlag(desc->vbFlags, g_VertexFlags[PrimaryColor])) - ss << "diffuse = color * diffuse;" << std::endl; // TODO: If this is the correct location, we should premultiply light and color in VS. - bool textures = false; - for (int i = 0; i < IDRV_MAT_MAXTEXTURES; i++) + for (uint stage = 0; stage < maxTex; ++stage) { - if (desc->getUseTexStage(i)) + if (useTex(desc, stage)) { - ss << "vec4 texel" << i << " = texture(sampler" << i << ", "; - if (desc->hasVBFlags(g_VertexFlags[TexCoord0 + i])) - ss << g_AttribNames[TexCoord0 + i]; - else if (desc->hasVBFlags(g_VertexFlags[TexCoord0])) + ss << "vec4 texel" << stage << " = texture(sampler" << stage << ", "; + if (hasFlag(desc.VertexFormat, g_VertexFlags[TexCoord0 + stage])) + { + ss << g_AttribNames[TexCoord0 + stage]; + } + else if (hasFlag(desc.VertexFormat, g_VertexFlags[TexCoord0])) + { ss << g_AttribNames[TexCoord0]; + } else { nlwarning("GL3: Pixel Program generated for material with coordinateless texture"); ss << "vec4(0.0, 0.0, 0.0, 0.0)"; } - ss << ((desc->textureSamplerMode[i] == SamplerCube) ? ".str);" : ".st);"); + ss << ((desc.TexSamplerMode[stage] == SamplerCube) ? ".stp);" : ".st);"); ss << std::endl; - textures = true; } - }*/ + } - /*switch (material->getShader()) + switch (desc.Shader) { + case CMaterial::Normal: + case CMaterial::UserColor: + ppTexEnv(ss, desc); + break; case CMaterial::Specular: - generateSpecular(); + ppSpecular(ss, desc); break; default: - generateTexEnv(); + nlwarning("GL3: Try to generate unknown shader type (%s)", s_ShaderNames[desc.Shader]); + // ss << "fragColor = vec(1.0, 0.0, 0.5, 1.0);" << std::endl; break; } - if (desc->fogEnabled()) - addFog(); - - addAlphaTest();*/ - - // ss << "fragColor = fragColor + vec4(0.0, 0.25, 0.0, 0.0);" << std::endl; + if (desc.Flags & IDRV_MAT_ALPHA_TEST) + { + ss << "if (fragColor.a < alphaTreshold) discard;" << std::endl; // TODO: VERIFY < or <= ? + } - // ss << "fragColor.b = diffuse.b;" << std::endl; + if (desc.Fog) + { + ss << "fragColor = applyFog(fragColor);" << std::endl; + } ss << "}" << std::endl; @@ -490,7 +521,7 @@ void CDriverGL3::generateBuiltinPixelProgram(CMaterial &mat) void CPPBuiltin::checkDriverStateTouched(CDriverGL3 *driver) // MUST NOT depend on any state set by checkMaterialStateTouched { - // Add generated texture coordinates to vertex format + // Add generated texture coordinates to vertex format // TODO: Eliminate unused flags uint16 vertexFormat = driver->m_VPBuiltinCurrent.VertexFormat; for (sint stage = 0; stage < IDRV_MAT_MAXTEXTURES; ++stage) if (driver->m_VPBuiltinCurrent.TexGenMode[stage] >= 0) @@ -502,6 +533,11 @@ void CPPBuiltin::checkDriverStateTouched(CDriverGL3 *driver) // MUST NOT depend VertexFormat = vertexFormat; Touched = true; } + if (Lighting != driver->m_VPBuiltinCurrent.Lighting) + { + Lighting = driver->m_VPBuiltinCurrent.Lighting; + Touched = true; + } if (Fog != driver->m_VPBuiltinCurrent.Fog) { Fog = driver->m_VPBuiltinCurrent.Fog; @@ -522,6 +558,13 @@ void CPPBuiltin::checkMaterialStateTouched(CMaterial &mat) // MUST NOT depend on Shader = shader; Touched = true; } + uint32 flags = mat.getFlags(); + flags &= IDRV_MAT_ALPHA_TEST; // TODO: |= with the wanted flags from the VP when flags are added to the VP + if (Flags != flags) + { + Flags = flags; + Touched = true; + } uint maxTex = maxTextures(shader); if (touched & IDRV_TOUCHED_ALLTEX) // Note: There is a case where textures are provided where no texture coordinates are provided, this is handled gracefully by the pixel program generation (it will use a vec(0) texture coordinate). The inverse is an optimization issue { diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl_program.cpp b/code/nel/src/3d/driver/opengl3/driver_opengl_program.cpp index 5a28941ce..d39bd3995 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_program.cpp +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_program.cpp @@ -22,7 +22,6 @@ #include "nel/3d/usr_shader_manager.h" #include "nel/3d/usr_shader_program.h" - namespace NL3D { #ifdef NL_STATIC @@ -54,8 +53,8 @@ const char *g_AttribNames[CVertexBuffer::NumValue] = "position", "weight", "normal", - "color", - "color2", + "primaryColor", + "secondaryColor", "fog", "paletteSkin", "none", diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl_program.h b/code/nel/src/3d/driver/opengl3/driver_opengl_program.h index c4dfe1ed1..7ea98bebc 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_program.h +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_program.h @@ -36,6 +36,8 @@ static sint TexGenEyeLinear = 3; // GL_EYE_LINEAR /// Builtin vertex program description struct CVPBuiltin { + CVPBuiltin() : VertexProgram(NULL) { } + uint16 VertexFormat; bool Lighting; sint LightMode[NL_OPENGL3_MAX_LIGHT]; // -1 when disabled @@ -44,7 +46,7 @@ struct CVPBuiltin bool Fog; // bool VertexColorLighted; - CVertexProgram *VertexProgram; + NLMISC::CRefPtr VertexProgram; }; bool operator<(const CVPBuiltin &left, const CVPBuiltin &right); @@ -55,15 +57,19 @@ static const uint8 SamplerCube = 1; /// Builtin pixel program description struct CPPBuiltin { + CPPBuiltin() : Touched(true) { } + uint16 VertexFormat; + bool Lighting; bool Fog; CMaterial::TShader Shader; + uint32 Flags; uint8 TextureActive; uint8 TexSamplerMode[IDRV_MAT_MAXTEXTURES]; uint32 TexEnvMode[IDRV_MAT_MAXTEXTURES]; // Normal, UserColor - CPixelProgram *PixelProgram; + NLMISC::CRefPtr PixelProgram; bool Touched;