GL3: Initial lightmap shader implementation

--HG--
branch : opengl3
hg/feature/opengl3
kaetemi 11 years ago
parent 9df1935f5e
commit 181db9adb9

@ -482,6 +482,9 @@ bool CDriverGL3::setupMaterial(CMaterial& mat)
// ===================== // =====================
switch (matShader) switch (matShader)
{ {
case CMaterial::LightMap:
// Programs are setup in multipass
return true;
default: default:
return setupBuiltinPrograms(); 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) H_AUTO_OGL(CDriverGL3_computeLightMapInfos)
static const uint32 RGBMaskPacked = CRGBA(255,255,255,0).getPacked(); 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) H_AUTO_OGL(CDriverGL3_beginLightMapMultiPass)
@ -655,7 +658,7 @@ sint CDriverGL3::beginLightMapMultiPass ()
// FIXME GL3 LIGHTMAP // FIXME GL3 LIGHTMAP
// Manage too if no lightmaps. // Manage too if no lightmaps.
return std::max (_NLightMapPass, (uint)1); return std::max(_NLightMapPass, (uint)1);
} }
// *************************************************************************** // ***************************************************************************
@ -668,22 +671,21 @@ void CDriverGL3::setupLightMapPass(uint pass)
const CMaterial &mat= *_CurrentMaterial; const CMaterial &mat= *_CurrentMaterial;
// common colors // common colors
static uint32 packedColorBlack= CRGBA(0,0,0,255).getPacked(); static const GLfloat glcolBlack[4] = { 0.f, 0.f, 0.f, 1.f };
static 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 uint32 packedColorWhite= CRGBA(255,255,255,255).getPacked(); static const GLfloat glcolGrey[4] = { 0.5f, 0.5f, 0.5f, 1.f };
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};
// No lightmap or all blacks??, just setup "black texture" for stage 0. // No lightmap or all blacks??, just setup "black texture" for stage 0.
if (_NLightMaps==0) if (_NLightMaps == 0)
{ {
ITexture *text= mat.getTexture(0); nldebug("No lightmaps");
activateTexture(0,text);
ITexture *text = mat.getTexture(0);
activateTexture(0, text);
// setup std modulate env // setup std modulate env
//CMaterial::CTexEnv env; // CMaterial::CTexEnv env;
//activateTexEnvMode(0, env); // FIXME GL3 // activateTexEnvMode(0, env); // FIXME GL3: standard modulate env
// Since Lighting is disabled, as well as colorArray, must setup alpha. // 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 // 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 // FIXME GL3 LIGHTMAP
// Setup gen tex off // Setup gen tex off
// setTexGenModeVP(0, TexGenDisabled); // FIXME GL3 setTexGenModeVP(0, TexGenDisabled);
// And disable other stages. // And disable other stages.
for (uint stage = 1; stage < IDRV_MAT_MAXTEXTURES; stage++) for (uint stage = 1; stage < IDRV_MAT_MAXTEXTURES; stage++)
@ -700,56 +702,57 @@ void CDriverGL3::setupLightMapPass(uint pass)
activateTexture(stage, NULL); activateTexture(stage, NULL);
} }
// Setup the programs now
setupBuiltinPrograms();
return; return;
} }
nlassert(pass<_NLightMapPass); nlassert(pass < _NLightMapPass);
// setup Texture Pass. // setup Texture Pass.
//========================= //=========================
uint lmapId; uint lmapId;
uint nstages; uint nstages;
lmapId= pass * _NLightMapPerPass; // Nb lightmaps already processed lmapId = pass * _NLightMapPerPass; // Nb lightmaps already processed
// N lightmaps for this pass, plus the texture. // 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 // For LMC (lightmap 8Bit compression) compute the total AmbientColor in vertex diffuse
// need only if standard MulADD version // need only if standard MulADD version
{ uint32 r = 0;
uint32 r=0; uint32 g = 0;
uint32 g=0; uint32 b = 0;
uint32 b=0;
// sum only the ambient of lightmaps that will be drawn this pass // sum only the ambient of lightmaps that will be drawn this pass
for (uint sa=0;sa<nstages-1;sa++) for (uint sa = 0; sa < nstages - 1; ++sa)
{ {
uint wla= _LightMapLUT[lmapId+sa]; uint wla = _LightMapLUT[lmapId + sa];
// must mul them by their respective mapFactor too // must mul them by their respective mapFactor too
CRGBA ambFactor = mat._LightMaps[wla].Factor; CRGBA ambFactor = mat._LightMaps[wla].Factor;
CRGBA lmcAmb= mat._LightMaps[wla].LMCAmbient; CRGBA lmcAmb = mat._LightMaps[wla].LMCAmbient;
r+= ((uint32)ambFactor.R * ((uint32)lmcAmb.R+(lmcAmb.R>>7))) >>8; r += ((uint32)ambFactor.R * ((uint32)lmcAmb.R + (lmcAmb.R >> 7))) >> 8;
g+= ((uint32)ambFactor.G * ((uint32)lmcAmb.G+(lmcAmb.G>>7))) >>8; g += ((uint32)ambFactor.G * ((uint32)lmcAmb.G + (lmcAmb.G >> 7))) >> 8;
b+= ((uint32)ambFactor.B * ((uint32)lmcAmb.B+(lmcAmb.B>>7))) >>8; b += ((uint32)ambFactor.B * ((uint32)lmcAmb.B + (lmcAmb.B >> 7))) >> 8;
} }
r= std::min(r, (uint32)255); r = std::min(r, (uint32)255);
g= std::min(g, (uint32)255); g = std::min(g, (uint32)255);
b= std::min(b, (uint32)255); b = std::min(b, (uint32)255);
// this color will be added to the first lightmap (with help of emissive) // this color will be added to the first lightmap (with help of emissive)
// CRGBA col((uint8)r,(uint8)g,(uint8)b,255); CRGBA col((uint8)r,(uint8)g,(uint8)b,255);
// GLfloat glcol[4];
// convColor(col, glcol); // Lightmap factors
// _DriverGLStates.setEmissive(col.getPacked(), glcol); NLMISC::CRGBAF selfIllumination(col);
// FIXME GL3 LIGHTMAP NLMISC::CRGBAF constant[IDRV_MAT_MAXTEXTURES];
}
// setup all stages. // setup all stages.
for (uint stage= 0; stage<IDRV_MAT_MAXTEXTURES; stage++) for (uint stage = 0; stage < IDRV_MAT_MAXTEXTURES; ++stage)
{ {
// if must setup a lightmap stage. // if must setup a lightmap stage
if (stage<nstages-1) if (stage < nstages - 1) // last stage is user texture
{ {
// setup lightMap. // setup lightMap.
uint whichLightMap= _LightMapLUT[lmapId]; uint whichLightMap = _LightMapLUT[lmapId];
// get text and factor. // get text and factor.
ITexture *text = mat._LightMaps[whichLightMap].Texture; ITexture *text = mat._LightMaps[whichLightMap].Texture;
CRGBA lmapFactor = mat._LightMaps[whichLightMap].Factor; CRGBA lmapFactor = mat._LightMaps[whichLightMap].Factor;
@ -761,20 +764,24 @@ void CDriverGL3::setupLightMapPass(uint pass)
lmapFactor.B = (uint8)(((uint32)lmapFactor.B * ((uint32)lmcDiff.B+(lmcDiff.B>>7))) >>8); lmapFactor.B = (uint8)(((uint32)lmapFactor.B * ((uint32)lmcDiff.B+(lmcDiff.B>>7))) >>8);
lmapFactor.A = 255; lmapFactor.A = 255;
activateTexture(stage,text); activateTexture(stage, text);
// If texture not NULL, Change texture env fonction. // If texture not NULL, Change texture env fonction.
//================================================== //==================================================
if (text) if (text)
{ {
static CMaterial::CTexEnv stdEnv; // Setup env for texture stage.
setTexGenModeVP(stage, TexGenDisabled);
{ // FIXME GL3: builtin TexEnv[stage] = TexEnvSpecialLightMap
// Here, we are sure that texEnvCombine4 or texEnvCombine3 is OK.
// nlassert(_Extensions.ATITextureEnvCombine3);
// Setup constant color with Lightmap factor.
constant[stage] = NLMISC::CRGBAF(lmapFactor);
/*static CMaterial::CTexEnv stdEnv;
{
// setup constant color with Lightmap factor. // setup constant color with Lightmap factor.
stdEnv.ConstantColor=lmapFactor; stdEnv.ConstantColor = lmapFactor;
int cl = m_DriverPixelProgram->getUniformIndex(CProgramIndex::TName(CProgramIndex::Constant0 + stage)); int cl = m_DriverPixelProgram->getUniformIndex(CProgramIndex::TName(CProgramIndex::Constant0 + stage));
if (cl != -1) if (cl != -1)
@ -786,36 +793,33 @@ void CDriverGL3::setupLightMapPass(uint pass)
// activateTexEnvColor(stage, stdEnv); // FIXME GL3 // activateTexEnvColor(stage, stdEnv); // FIXME GL3
// Setup env for texture stage.
// setTexGenModeVP(stage, TexGenDisabled); // FIXME GL3
// setup TexEnvCombine4 (ignore alpha part). // setup TexEnvCombine4 (ignore alpha part).
/*if (_CurrentTexEnvSpecial[stage] != TexEnvSpecialLightMap) /*if (_CurrentTexEnvSpecial[stage] != TexEnvSpecialLightMap)
{ {
// TexEnv is special. // TexEnv is special.
_CurrentTexEnvSpecial[stage] = TexEnvSpecialLightMap; _CurrentTexEnvSpecial[stage] = TexEnvSpecialLightMap;
}*/ // FIXME GL3 }*/ // FIXME GL3
} /*}*/
} }
// Next lightmap. // Next lightmap.
lmapId++; lmapId++;
} }
else if (stage<nstages) else if (stage < nstages)
{ {
// optim: do this only for first pass, and last pass only if stage!=nLMapPerPass // optim: do this only for first pass, and last pass only if stage != nLMapPerPass
// (meaning not the same stage as preceding passes). // (meaning not the same stage as preceding passes).
if (pass==0 || (pass==_NLightMapPass-1 && stage!=_NLightMapPerPass)) if (pass == 0 || (pass == _NLightMapPass - 1 && stage != _NLightMapPerPass))
{ {
// activate the texture at last stage. // activate the texture at last stage.
ITexture *text= mat.getTexture(0); ITexture *text = mat.getTexture(0);
activateTexture(stage,text); activateTexture(stage, text);
// setup ModulateRGB/ReplaceAlpha env. (this may disable possible COMBINE4_NV setup). // setup ModulateRGB/ReplaceAlpha env. (this may disable possible COMBINE4_NV setup).
// activateTexEnvMode(stage, _LightMapLastStageEnv); // FIXME GL3 // activateTexEnvMode(stage, _LightMapLastStageEnv); // SHADER BUILTIN
// Setup gen tex off // Setup gen tex off
// setTexGenModeVP(stage, TexGenDisabled); // FIXME GL3 setTexGenModeVP(stage, TexGenDisabled);
} }
} }
else else
@ -894,6 +898,22 @@ void CDriverGL3::setupLightMapPass(uint pass)
// _DriverGLStates.setDiffuse(packedColorBlack, glcolBlack); // _DriverGLStates.setDiffuse(packedColorBlack, glcolBlack);
// FIXME GL3 LIGHTMAP // FIXME GL3 LIGHTMAP
} }
// Setup the programs now
setupBuiltinPrograms();
// Set constants
for (uint stage = 0; stage < IDRV_MAT_MAXTEXTURES; ++stage)
{
uint constantIdx = m_DriverPixelProgram->getUniformIndex(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
} }
// *************************************************************************** // ***************************************************************************

@ -341,11 +341,39 @@ void ppSpecular(std::stringstream &ss, const CPPBuiltin &desc)
} }
else else
{ {
nlwarning("No textures defined in Specular shader"); nlwarning("PP: No textures defined in Specular shader");
// do nothing // 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) void ppGenerate(std::string &result, const CPPBuiltin &desc)
{ {
std::stringstream ss; std::stringstream ss;
@ -452,7 +480,15 @@ void ppGenerate(std::string &result, const CPPBuiltin &desc)
else if (useTex(desc, stage)) else if (useTex(desc, stage))
{ {
ss << "vec4 texel" << stage << " = texture(sampler" << stage << ", "; ss << "vec4 texel" << stage << " = texture(sampler" << stage << ", ";
if (hasFlag(desc.VertexFormat, g_VertexFlags[TexCoord0 + 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]; ss << g_AttribNames[TexCoord0 + stage];
} }
@ -479,6 +515,9 @@ void ppGenerate(std::string &result, const CPPBuiltin &desc)
case CMaterial::Specular: case CMaterial::Specular:
ppSpecular(ss, desc); ppSpecular(ss, desc);
break; break;
case CMaterial::LightMap:
ppLightmap(ss, desc);
break;
default: default:
nlwarning("GL3: Try to generate unknown shader type (%s)", s_ShaderNames[desc.Shader]); 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; // 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 void CPPBuiltin::checkMaterialStateTouched(CMaterial &mat) // MUST NOT depend on any state set by checkDriverStateTouched
{ {
// Optimize // Optimize
@ -582,6 +656,11 @@ void CPPBuiltin::checkMaterialStateTouched(CMaterial &mat) // MUST NOT depend on
uint maxTex = maxTextures(shader); 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 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
{ {
switch (shader)
{
case CMaterial::LightMap:
default:
// Use textures directly from the CMaterial
uint8 textureActive = 0x00; uint8 textureActive = 0x00;
for (uint stage = 0; stage < maxTex; ++stage) for (uint stage = 0; stage < maxTex; ++stage)
{ {
@ -604,6 +683,8 @@ void CPPBuiltin::checkMaterialStateTouched(CMaterial &mat) // MUST NOT depend on
TextureActive = textureActive; TextureActive = textureActive;
Touched = true; Touched = true;
} }
break;
}
} }
if (useTexEnv(shader) && (touched & IDRV_TOUCHED_TEXENV)) if (useTexEnv(shader) && (touched & IDRV_TOUCHED_TEXENV))
{ {

@ -667,6 +667,7 @@ bool CDriverGL3::setupBuiltinPixelProgram()
nlassert(matDrv); nlassert(matDrv);
matDrv->PPBuiltin.checkDriverStateTouched(this); matDrv->PPBuiltin.checkDriverStateTouched(this);
matDrv->PPBuiltin.checkDriverMaterialStateTouched(this, mat);
matDrv->PPBuiltin.checkMaterialStateTouched(mat); matDrv->PPBuiltin.checkMaterialStateTouched(mat);
if (matDrv->PPBuiltin.Touched) if (matDrv->PPBuiltin.Touched)

@ -73,6 +73,7 @@ struct CPPBuiltin
bool Touched; bool Touched;
void checkDriverStateTouched(CDriverGL3 *driver); void checkDriverStateTouched(CDriverGL3 *driver);
void checkDriverMaterialStateTouched(CDriverGL3 *driver, CMaterial &mat);
void checkMaterialStateTouched(CMaterial &mat); void checkMaterialStateTouched(CMaterial &mat);
}; };

Loading…
Cancel
Save