diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl_material.cpp b/code/nel/src/3d/driver/opengl3/driver_opengl_material.cpp index ec0835d1e..2d6dc19d2 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_material.cpp +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_material.cpp @@ -482,6 +482,9 @@ bool CDriverGL3::setupMaterial(CMaterial& mat) // ===================== switch (matShader) { + case CMaterial::LightMap: + // Programs are setup in multipass + return true; default: return setupBuiltinPrograms(); } @@ -596,7 +599,7 @@ void CDriverGL3::setupNormalPass() } // *************************************************************************** -void CDriverGL3::computeLightMapInfos (const CMaterial &mat) +void CDriverGL3::computeLightMapInfos(const CMaterial &mat) { H_AUTO_OGL(CDriverGL3_computeLightMapInfos) static const uint32 RGBMaskPacked = CRGBA(255,255,255,0).getPacked(); @@ -627,7 +630,7 @@ void CDriverGL3::computeLightMapInfos (const CMaterial &mat) } // *************************************************************************** -sint CDriverGL3::beginLightMapMultiPass () +sint CDriverGL3::beginLightMapMultiPass() { H_AUTO_OGL(CDriverGL3_beginLightMapMultiPass) @@ -655,11 +658,11 @@ sint CDriverGL3::beginLightMapMultiPass () // FIXME GL3 LIGHTMAP // Manage too if no lightmaps. - return std::max (_NLightMapPass, (uint)1); + return std::max(_NLightMapPass, (uint)1); } // *************************************************************************** -void CDriverGL3::setupLightMapPass(uint pass) +void CDriverGL3::setupLightMapPass(uint pass) { nlassert(m_DriverPixelProgram); nlassert(!m_UserPixelProgram); @@ -668,22 +671,21 @@ void CDriverGL3::setupLightMapPass(uint pass) const CMaterial &mat= *_CurrentMaterial; // common colors - static uint32 packedColorBlack= CRGBA(0,0,0,255).getPacked(); - static GLfloat glcolBlack[4]= {0.f,0.f,0.f,1.f}; - static uint32 packedColorWhite= CRGBA(255,255,255,255).getPacked(); - static GLfloat glcolWhite[4]= {1.f,1.f,1.f,1.f}; - static uint32 packedColorGrey= CRGBA(128,128,128,128).getPacked(); - static GLfloat glcolGrey[4]= {0.5f,0.5f,0.5f,1.f}; + static const GLfloat glcolBlack[4] = { 0.f, 0.f, 0.f, 1.f }; + static const GLfloat glcolWhite[4] = { 1.f, 1.f, 1.f, 1.f }; + static const GLfloat glcolGrey[4] = { 0.5f, 0.5f, 0.5f, 1.f }; // No lightmap or all blacks??, just setup "black texture" for stage 0. - if (_NLightMaps==0) + if (_NLightMaps == 0) { - ITexture *text= mat.getTexture(0); - activateTexture(0,text); + nldebug("No lightmaps"); + + ITexture *text = mat.getTexture(0); + activateTexture(0, text); // setup std modulate env - //CMaterial::CTexEnv env; - //activateTexEnvMode(0, env); // FIXME GL3 + // CMaterial::CTexEnv env; + // activateTexEnvMode(0, env); // FIXME GL3: standard modulate env // Since Lighting is disabled, as well as colorArray, must setup alpha. // setup color to 0 => blackness. in emissive cause texture can still be lighted by dynamic light @@ -691,7 +693,7 @@ void CDriverGL3::setupLightMapPass(uint pass) // FIXME GL3 LIGHTMAP // Setup gen tex off - // setTexGenModeVP(0, TexGenDisabled); // FIXME GL3 + setTexGenModeVP(0, TexGenDisabled); // And disable other stages. for (uint stage = 1; stage < IDRV_MAT_MAXTEXTURES; stage++) @@ -700,58 +702,59 @@ void CDriverGL3::setupLightMapPass(uint pass) activateTexture(stage, NULL); } + // Setup the programs now + setupBuiltinPrograms(); + return; } - nlassert(pass<_NLightMapPass); + nlassert(pass < _NLightMapPass); // setup Texture Pass. //========================= uint lmapId; uint nstages; - lmapId= pass * _NLightMapPerPass; // Nb lightmaps already processed + lmapId = pass * _NLightMapPerPass; // Nb lightmaps already processed // N lightmaps for this pass, plus the texture. - nstages= std::min(_NLightMapPerPass, _NLightMaps-lmapId) + 1; + nstages = std::min(_NLightMapPerPass, _NLightMaps - lmapId) + 1; // at most 4 // For LMC (lightmap 8Bit compression) compute the total AmbientColor in vertex diffuse // need only if standard MulADD version + uint32 r = 0; + uint32 g = 0; + uint32 b = 0; + // sum only the ambient of lightmaps that will be drawn this pass + for (uint sa = 0; sa < nstages - 1; ++sa) { - uint32 r=0; - uint32 g=0; - uint32 b=0; - // sum only the ambient of lightmaps that will be drawn this pass - for (uint sa=0;sa>7))) >>8; - g+= ((uint32)ambFactor.G * ((uint32)lmcAmb.G+(lmcAmb.G>>7))) >>8; - b+= ((uint32)ambFactor.B * ((uint32)lmcAmb.B+(lmcAmb.B>>7))) >>8; - } - r= std::min(r, (uint32)255); - g= std::min(g, (uint32)255); - b= std::min(b, (uint32)255); - - // this color will be added to the first lightmap (with help of emissive) - // CRGBA col((uint8)r,(uint8)g,(uint8)b,255); - // GLfloat glcol[4]; - // convColor(col, glcol); - // _DriverGLStates.setEmissive(col.getPacked(), glcol); - // FIXME GL3 LIGHTMAP + uint wla = _LightMapLUT[lmapId + sa]; + // must mul them by their respective mapFactor too + CRGBA ambFactor = mat._LightMaps[wla].Factor; + CRGBA lmcAmb = mat._LightMaps[wla].LMCAmbient; + r += ((uint32)ambFactor.R * ((uint32)lmcAmb.R + (lmcAmb.R >> 7))) >> 8; + g += ((uint32)ambFactor.G * ((uint32)lmcAmb.G + (lmcAmb.G >> 7))) >> 8; + b += ((uint32)ambFactor.B * ((uint32)lmcAmb.B + (lmcAmb.B >> 7))) >> 8; } + r = std::min(r, (uint32)255); + g = std::min(g, (uint32)255); + b = std::min(b, (uint32)255); + + // this color will be added to the first lightmap (with help of emissive) + CRGBA col((uint8)r,(uint8)g,(uint8)b,255); + + // Lightmap factors + NLMISC::CRGBAF selfIllumination(col); + NLMISC::CRGBAF constant[IDRV_MAT_MAXTEXTURES]; // setup all stages. - for (uint stage= 0; stage>7))) >>8); lmapFactor.A = 255; - activateTexture(stage,text); + activateTexture(stage, text); // If texture not NULL, Change texture env fonction. //================================================== if (text) { - static CMaterial::CTexEnv stdEnv; + // Setup env for texture stage. + setTexGenModeVP(stage, TexGenDisabled); - { - // Here, we are sure that texEnvCombine4 or texEnvCombine3 is OK. - // nlassert(_Extensions.ATITextureEnvCombine3); + // FIXME GL3: builtin TexEnv[stage] = TexEnvSpecialLightMap + + // Setup constant color with Lightmap factor. + constant[stage] = NLMISC::CRGBAF(lmapFactor); + /*static CMaterial::CTexEnv stdEnv; + { // setup constant color with Lightmap factor. - stdEnv.ConstantColor=lmapFactor; + stdEnv.ConstantColor = lmapFactor; int cl = m_DriverPixelProgram->getUniformIndex(CProgramIndex::TName(CProgramIndex::Constant0 + stage)); if (cl != -1) @@ -786,36 +793,33 @@ void CDriverGL3::setupLightMapPass(uint pass) // activateTexEnvColor(stage, stdEnv); // FIXME GL3 - // Setup env for texture stage. - // setTexGenModeVP(stage, TexGenDisabled); // FIXME GL3 - // setup TexEnvCombine4 (ignore alpha part). /*if (_CurrentTexEnvSpecial[stage] != TexEnvSpecialLightMap) { // TexEnv is special. _CurrentTexEnvSpecial[stage] = TexEnvSpecialLightMap; }*/ // FIXME GL3 - } + /*}*/ } // Next lightmap. lmapId++; } - else if (stagegetUniformIndex(CProgramIndex::TName(CProgramIndex::Constant0 + stage)); + if (constantIdx != ~0) + { + setUniform4f(IDriver::PixelProgram, constantIdx, constant[stage].R, constant[stage].G, constant[stage].B, constant[stage].A); + } + } + + // Set self illumination + // FIXME GL3: selfIllumination } // *************************************************************************** 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 190eb5e11..88ef5857c 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 @@ -341,11 +341,39 @@ void ppSpecular(std::stringstream &ss, const CPPBuiltin &desc) } else { - nlwarning("No textures defined in Specular shader"); + nlwarning("PP: No textures defined in Specular shader"); // do nothing } } +void ppLightmap(std::stringstream &ss, const CPPBuiltin &desc) +{ + uint nstages; + for (nstages = 0; nstages < IDRV_MAT_MAXTEXTURES; ++nstages) + if (!useTex(desc, nstages)) + break; + if (nstages == 0) + { + // do nothing + nlwarning("PP: Lightmap without textures setup"); + } + else if (nstages == 1) + { + // single map (doesn't support alpha) + nlwarning("PP: Lightmap material without lightmaps setup %i %i %i %i", useTex(desc, 0), useTex(desc, 1), useTex(desc, 2), useTex(desc, 3)); + ss << "fragColor = vec4(1.0, 1.0, 1.0, 1.0);" << std::endl; // HACK FIXME GL3 + ss << "fragColor = texel" << (nstages - 1) << " * fragColor;" << std::endl; + } + else + { + ss << "fragColor = vec4(1.0, 1.0, 1.0, 1.0);" << std::endl; // HACK FIXME GL3 + ss << "vec4 lightmapop = vec4(0.0, 0.0, 0.0, 0.0);" << std::endl; + for (uint stage = 0; stage < (nstages - 1); ++stage) + ss << "lightmapop = lightmapop + texel" << stage << " * constant" << stage << " * texel" << (nstages - 1) << ";" << std::endl; + ss << "fragColor = fragColor * lightmapop;" << std::endl; + } +} + void ppGenerate(std::string &result, const CPPBuiltin &desc) { std::stringstream ss; @@ -451,8 +479,16 @@ void ppGenerate(std::string &result, const CPPBuiltin &desc) } else if (useTex(desc, stage)) { - ss << "vec4 texel" << stage << " = texture(sampler" << stage << ", "; - if (hasFlag(desc.VertexFormat, g_VertexFlags[TexCoord0 + stage])) + ss << "vec4 texel" << stage << " = texture(sampler" << stage << ", "; + if (desc.Shader == CMaterial::LightMap && stage != (maxTex - 1) && hasFlag(desc.VertexFormat, g_VertexFlags[TexCoord1])) + { + ss << g_AttribNames[TexCoord1]; + } + else if (desc.Shader == CMaterial::LightMap && hasFlag(desc.VertexFormat, g_VertexFlags[TexCoord0])) + { + ss << g_AttribNames[TexCoord0]; + } + else if (hasFlag(desc.VertexFormat, g_VertexFlags[TexCoord0 + stage])) { ss << g_AttribNames[TexCoord0 + stage]; } @@ -479,6 +515,9 @@ void ppGenerate(std::string &result, const CPPBuiltin &desc) case CMaterial::Specular: ppSpecular(ss, desc); break; + case CMaterial::LightMap: + ppLightmap(ss, desc); + break; default: 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; @@ -559,6 +598,41 @@ void CPPBuiltin::checkDriverStateTouched(CDriverGL3 *driver) // MUST NOT depend } } +void CPPBuiltin::checkDriverMaterialStateTouched(CDriverGL3 *driver, CMaterial &mat) +{ + CMaterial::TShader shader = getSupportedShader(mat.getShader()); + switch (shader) + { + case CMaterial::LightMap: + // Use Textures from current driver state + // NB: Might be necessary to use this for every material type and remove the one from the other function + uint maxTex = maxTextures(shader); + uint8 textureActive = 0x00; + for (uint stage = 0; stage < maxTex; ++stage) + { + NL3D::ITexture *tex = driver->_CurrentTexture[stage]; + if (tex) + { + textureActive |= (1 << stage); + + uint8 texSamplerMode = tex->isTextureCube() ? SamplerCube : Sampler2D; + if (TexSamplerMode[stage] != texSamplerMode) + { + TexSamplerMode[stage] = texSamplerMode; + Touched = true; + } + } + } + if (TextureActive != textureActive) + { + TextureActive = textureActive; + Touched = true; + } + // nldebug("TextureActive: %i", TextureActive); + break; + } +} + void CPPBuiltin::checkMaterialStateTouched(CMaterial &mat) // MUST NOT depend on any state set by checkDriverStateTouched { // Optimize @@ -582,27 +656,34 @@ void CPPBuiltin::checkMaterialStateTouched(CMaterial &mat) // MUST NOT depend on 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 { - uint8 textureActive = 0x00; - for (uint stage = 0; stage < maxTex; ++stage) + switch (shader) { - NL3D::ITexture *tex = mat._Textures[stage]; - if (tex) + case CMaterial::LightMap: + default: + // Use textures directly from the CMaterial + uint8 textureActive = 0x00; + for (uint stage = 0; stage < maxTex; ++stage) { - textureActive |= (1 << stage); - - // Issue: Due to the IDRV_TOUCHED_ALLTEX check, the sampler mode of an ITexture cannot be modified after it has been added to the CMaterial - uint8 texSamplerMode = tex->isTextureCube() ? SamplerCube : Sampler2D; - if (TexSamplerMode[stage] != texSamplerMode) + NL3D::ITexture *tex = mat._Textures[stage]; + if (tex) { - TexSamplerMode[stage] = texSamplerMode; - Touched = true; + textureActive |= (1 << stage); + + // Issue: Due to the IDRV_TOUCHED_ALLTEX check, the sampler mode of an ITexture cannot be modified after it has been added to the CMaterial + uint8 texSamplerMode = tex->isTextureCube() ? SamplerCube : Sampler2D; + if (TexSamplerMode[stage] != texSamplerMode) + { + TexSamplerMode[stage] = texSamplerMode; + Touched = true; + } } } - } - if (TextureActive != textureActive) - { - TextureActive = textureActive; - Touched = true; + if (TextureActive != textureActive) + { + TextureActive = textureActive; + Touched = true; + } + break; } } if (useTexEnv(shader) && (touched & IDRV_TOUCHED_TEXENV)) 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 bcf3cc97c..4b9391dad 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_program.cpp +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_program.cpp @@ -667,6 +667,7 @@ bool CDriverGL3::setupBuiltinPixelProgram() nlassert(matDrv); matDrv->PPBuiltin.checkDriverStateTouched(this); + matDrv->PPBuiltin.checkDriverMaterialStateTouched(this, mat); matDrv->PPBuiltin.checkMaterialStateTouched(mat); if (matDrv->PPBuiltin.Touched) 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 570b3cb0f..d99200ba8 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_program.h +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_program.h @@ -73,6 +73,7 @@ struct CPPBuiltin bool Touched; void checkDriverStateTouched(CDriverGL3 *driver); + void checkDriverMaterialStateTouched(CDriverGL3 *driver, CMaterial &mat); void checkMaterialStateTouched(CMaterial &mat); };