forked from Mirrors/openclonk
Add ambient lighting
This introduces a new texture, an ambient light map, that is generated automatically at the beginning of the round by the sky portion of the landscape. This basically makes everything that is close to sky visible by default. The shaders have been adapted so that they deploy direction-independent lighting for the ambient component, and the current (diffuse) behaviour for the diffuse component. This makes the shaders use an additional texture unit that represents the ambient light. We can think about merging this information into the light texture, but the coordinate systems are different at the moment, so this could be performed at the stage of light texture generation. For meshes, the ambient material is not actually used, but instead a diffuse light from the front is used. This makes many meshes look more interesting, maybe also because the ambient material setting of most meshes are not set correctly at the moment.issue1247
parent
e64875d1c7
commit
88f8f75441
|
@ -291,6 +291,8 @@ set(OC_CLONK_SOURCES
|
|||
src/gui/C4UpperBoard.h
|
||||
src/landscape/fow/C4FoW.cpp
|
||||
src/landscape/fow/C4FoW.h
|
||||
src/landscape/fow/C4FoWAmbient.cpp
|
||||
src/landscape/fow/C4FoWAmbient.h
|
||||
src/landscape/fow/C4FoWBeam.cpp
|
||||
src/landscape/fow/C4FoWBeam.h
|
||||
src/landscape/fow/C4FoWLight.cpp
|
||||
|
|
|
@ -49,6 +49,11 @@
|
|||
<literal_col>sampler2D</literal_col>
|
||||
<col>Texture containing the light map. The red component of the map corresponds to the halfed light intensity, and the green and blue components the light direction in x-y, scaled by 1/3 and shifted by +1 in both directions. The fragment coordinates (<code>gl_FragCoord</code>) can be used as texture coordinates to look up the light information when transformed with the texture matrix of 1 plus the last texture unit. Therefore, if the pass uses one texture unit, the second texture unit will be used for the light texture, and the lookup can be performed with <code>texture2D(oc_Light, (gl_TextureMatrix[2] * gl_FragCoord).xy)</code>.</col>
|
||||
</row>
|
||||
<row>
|
||||
<literal_col>oc_ambient</literal_col>
|
||||
<literal_col>sampler2D</literal_col>
|
||||
<col>Texture containing the ambient light map. The red component of the map corresponds to the intensity of ambient light. The texture contains only the red channel. The fragment coordinates (<code>gl_FragCoord</code>) can be used as texture coordinates to look up the ambient light information when transformed with the texture matrix of 2 plus the last texture unit. Therefore, if the pass uses one texture unit, the third texture unit will be used for the light texture, and the lookup can be performed with <code>texture2D(oc_Light, (gl_TextureMatrix[3] * gl_FragCoord).xy)</code>.</col>
|
||||
</row>
|
||||
</table>
|
||||
</text>
|
||||
<text>When a custom fragment shader is used, then that shader is responsible for applying the player color and color modulation to the object, since in that case the engine cannot take care of that. The additional parameters mentioned above can be used for that purpose. Also, when a custom fragment shader is used, the colour_op, colour_op_ex, alpha_op and alpha_op_ex directives in all texture units are ignored.</text>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
// Input textures
|
||||
uniform sampler2D landscapeTex[2];
|
||||
uniform sampler2D lightTex;
|
||||
uniform sampler2D ambientTex;
|
||||
uniform sampler2D scalerTex;
|
||||
uniform sampler3D materialTex;
|
||||
|
||||
|
@ -21,6 +22,9 @@ uniform float matMap[256];
|
|||
uniform int materialDepth;
|
||||
uniform vec2 materialSize;
|
||||
|
||||
// Factor between landscape coordinates and ambient map coordinates
|
||||
uniform vec2 ambientScale;
|
||||
|
||||
// Expected parameters for the scaler
|
||||
const vec2 scalerStepX = vec2(1.0 / 8.0, 0.0);
|
||||
const vec2 scalerStepY = vec2(0.0, 1.0 / 32.0);
|
||||
|
@ -119,7 +123,7 @@ void main()
|
|||
|
||||
// Brightness
|
||||
vec4 lightPx = texture2D(lightTex, gl_TexCoord[1].st);
|
||||
float ambientBright = lightPx.r, shadeBright = ambientBright;
|
||||
float shadeBright = lightPx.r;
|
||||
|
||||
// Normal calculation
|
||||
vec3 landscapeNormal = extend_normal(mix(realLandscapePx.yz, landscapePx.yz, scalerPx.a) - vec2(0.5, 0.5));
|
||||
|
@ -128,16 +132,22 @@ void main()
|
|||
vec3 normal = landscapeNormal + textureNormal;
|
||||
vec3 normal2 = landscapeNormal2 + textureNormal;
|
||||
|
||||
// Light calculation
|
||||
// Ambient light
|
||||
float ambient = texture2D(ambientTex, ambientScale * texCoo).r;
|
||||
float ambient2 = texture2D(ambientTex, ambientScale * otherCoo).r;
|
||||
|
||||
// Light calculation; the ambient part actually uses some shading with
|
||||
// a light direction of (0.0, -1.0, 0.0) so that it does not look utterly
|
||||
// boring at the sky/material edges.
|
||||
vec3 lightDir = extend_normal(vec2(1.0, 1.0) - lightPx.yz * 3.0);
|
||||
float bright = 2.0 * shadeBright * dot(normal, lightDir);
|
||||
float bright2 = 2.0 * shadeBright * dot(normal2, lightDir);
|
||||
float bright = ambient * (1.0 + 1.0 * dot(normal, vec3(0.0, -1.0, 0.0))) + (1.0 - ambient) * 2.0 * shadeBright * dot(normal, lightDir);
|
||||
float bright2 = ambient2 * (1.0 + 1.0 * dot(normal2, vec3(0.0, -1.0, 0.0))) + (1.0 - ambient2) * 2.0 * shadeBright * dot(normal2, lightDir);
|
||||
|
||||
gl_FragColor = mix(
|
||||
vec4(bright2 * otherMaterialPx.rgb, otherMaterialPx.a),
|
||||
vec4(bright * materialPx.rgb, materialPx.a),
|
||||
scalerPx.r);
|
||||
|
||||
|
||||
// uncomment the following lines for debugging light directions:
|
||||
// yellow: light up, blue: light down, turqoise: light right, pink: light left, opacity: light strength
|
||||
//float lightYDir = lightPx.b - 1.0/3.0;
|
||||
|
|
|
@ -8,7 +8,7 @@ material Clonk_Body
|
|||
ambient 0.500000 0.500000 0.500000 1.000000
|
||||
diffuse 0.810000 0.810000 0.810000 1.000000
|
||||
specular 0.000000 0.000000 0.000000 1.000000 3.000000
|
||||
emissive 0.200000 0.200000 0.200000 1.000000
|
||||
emissive 0.000000 0.000000 0.000000 1.000000
|
||||
|
||||
texture_unit Overlay
|
||||
{
|
||||
|
|
|
@ -36,6 +36,7 @@ material NormalMap
|
|||
param_named_auto oc_ColorModulation oc_color_modulation
|
||||
param_named_auto oc_UseLight oc_use_light
|
||||
param_named_auto oc_Light oc_light
|
||||
param_named_auto oc_Ambient oc_ambient
|
||||
|
||||
param_named basemap int 0
|
||||
param_named normalmap int 1
|
||||
|
|
|
@ -6,28 +6,29 @@ uniform int oc_Mod2;
|
|||
uniform vec4 oc_ColorModulation;
|
||||
uniform int oc_UseLight;
|
||||
uniform sampler2D oc_Light;
|
||||
uniform sampler2D oc_Ambient;
|
||||
|
||||
// This is mostly copied from C4DrawMeshGL.cpp -- only the calculation
|
||||
// of the normal has been replaced
|
||||
void main()
|
||||
{
|
||||
vec3 lightDir;
|
||||
float lightIntensity;
|
||||
vec3 normal = normalize((texture2D(normalmap, texcoord).rgb * 2.0 - 1.0)); // TODO: This might be normalized already
|
||||
vec4 diffuse;
|
||||
|
||||
if(oc_UseLight != 0)
|
||||
{
|
||||
vec4 lightPx = texture2D(oc_Light, (gl_TextureMatrix[2] * gl_FragCoord).xy);
|
||||
lightDir = normalize(vec3(vec2(1.0, 1.0) - lightPx.gb * 3.0, 0.3));
|
||||
lightIntensity = 2.0 * lightPx.r;
|
||||
vec3 lightDir = normalize(vec3(vec2(1.0, 1.0) - lightPx.gb * 3.0, 0.3));
|
||||
float lightIntensity = 2.0 * lightPx.r;
|
||||
float ambient = texture2D(oc_Ambient, (gl_TextureMatrix[3] * gl_FragCoord).xy).r;
|
||||
diffuse = ambient * (gl_FrontMaterial.emission + gl_FrontMaterial.diffuse * max(dot(normalize(normal), vec3(0.0, 0.0, 1.0)), 0.0)) + (1.0 - ambient) * lightIntensity * (gl_FrontMaterial.emission + gl_FrontMaterial.diffuse * max(dot(normalize(normal), lightDir), 0.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
lightDir = vec3(0.0, 0.0, 1.0);
|
||||
lightIntensity = 1.0;
|
||||
vec3 lightDir = vec3(0.0, 0.0, 1.0);
|
||||
diffuse = gl_FrontMaterial.emission + gl_FrontMaterial.diffuse * max(dot(normal, lightDir), 0.0);
|
||||
}
|
||||
|
||||
vec3 normal = normalize((texture2D(normalmap, texcoord).rgb * 2.0 - 1.0)); // TODO: This might be normalized already
|
||||
vec4 diffuse = gl_FrontMaterial.emission + 0.0 * gl_FrontMaterial.ambient + gl_FrontMaterial.diffuse * max(dot(normalize(normal), lightDir), 0.0);
|
||||
|
||||
// Modulate with base texture
|
||||
vec4 finalColor = diffuse * texture2D(basemap, texcoord);
|
||||
|
||||
|
|
|
@ -301,6 +301,7 @@ void CStdGL::SetupMultiBlt(const C4BltTransform* pTransform, GLuint baseTex, GLu
|
|||
GLint clrModLocation = glGetUniformLocationARB(multi_blt_program->Program, "clrMod");
|
||||
GLint overlayClrModLocation = glGetUniformLocationARB(multi_blt_program->Program, "overlayClrMod");
|
||||
GLint lightLocation = glGetUniformLocationARB(multi_blt_program->Program, "Light");
|
||||
GLint ambientLocation = glGetUniformLocationARB(multi_blt_program->Program, "Ambient");
|
||||
GLint textureLocation = glGetUniformLocationARB(multi_blt_program->Program, "Texture");
|
||||
GLint overlayLocation = glGetUniformLocationARB(multi_blt_program->Program, "Overlay");
|
||||
GLint normalLocation = glGetUniformLocationARB(multi_blt_program->Program, "Normal");
|
||||
|
@ -334,31 +335,49 @@ void CStdGL::SetupMultiBlt(const C4BltTransform* pTransform, GLuint baseTex, GLu
|
|||
|
||||
if(fUseNormal)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
glActiveTexture(GL_TEXTURE4);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, normalTex);
|
||||
glUniform1iARB(normalLocation, 3);
|
||||
glUniform1iARB(normalLocation, 4);
|
||||
}
|
||||
|
||||
if(fUseLight)
|
||||
{
|
||||
const C4Rect LightRect = pFoW->getRegion();
|
||||
const int32_t iLightWdt = pFoW->getSurface()->Wdt;
|
||||
const int32_t iLightHgt = pFoW->getSurface()->Hgt;
|
||||
|
||||
const int iVpWdt=Min(iClipX2, RenderTarget->Wdt-1)-iClipX1+1;
|
||||
const int iVpHgt=Min(iClipY2, RenderTarget->Hgt-1)-iClipY1+1;
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
|
||||
// Ambient texture
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, pFoW->getFoW()->Ambient.Tex);
|
||||
glUniform1iARB(ambientLocation, 3);
|
||||
|
||||
// Setup the texture matrix
|
||||
glLoadIdentity();
|
||||
glScalef(1.0f/pFoW->getFoW()->Ambient.GetLandscapeWidth(), 1.0f/pFoW->getFoW()->Ambient.GetLandscapeHeight(), 1.0f);
|
||||
glTranslatef(LightRect.x, LightRect.y, 0.0f); // TODO: LightRect should have floating point accuracy for this to work best
|
||||
glScalef( (float)LightRect.Wdt / (float)iVpWdt, (float)LightRect.Hgt / (float)iVpHgt, 1.0f);
|
||||
glTranslatef(0.0f, iVpHgt, 0.0f);
|
||||
glScalef(1.0f, -1.0f, 1.0f);
|
||||
|
||||
// Light texture
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, pFoW->getSurface()->ppTex[0]->texName);
|
||||
glUniform1iARB(lightLocation, 2);
|
||||
|
||||
// Setup the texture matrix such that fragment coordinates
|
||||
// are converted to coordinates inside the light texture.
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
// Setup the texture matrix
|
||||
glLoadIdentity();
|
||||
|
||||
const C4Rect LightRect = pFoW->getRegion();
|
||||
const int32_t iLightWdt = pFoW->getSurface()->Wdt;
|
||||
const int32_t iLightHgt = pFoW->getSurface()->Hgt;
|
||||
|
||||
glTranslatef(0.0f, 1.0f - (float)LightRect.Hgt/(float)iLightHgt, 0.0f);
|
||||
glScalef(1.0f/iLightWdt, 1.0f/iLightHgt, 1.0f);
|
||||
glScalef(1.0f/Zoom, 1.0f/Zoom, 1.0f);
|
||||
glScalef( (float)LightRect.Wdt / (float)iVpWdt, (float)LightRect.Hgt / (float)iVpHgt, 1.0f);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
@ -395,8 +414,8 @@ void CStdGL::SetupMultiBlt(const C4BltTransform* pTransform, GLuint baseTex, GLu
|
|||
void CStdGL::ResetMultiBlt(GLuint baseTex, GLuint overlayTex, GLuint normalTex)
|
||||
{
|
||||
glPopMatrix();
|
||||
if(normalTex != 0) { glActiveTexture(GL_TEXTURE3); glDisable(GL_TEXTURE_2D); }
|
||||
if(pFoW != NULL) { glActiveTexture(GL_TEXTURE2); glDisable(GL_TEXTURE_2D); }
|
||||
if(normalTex != 0) { glActiveTexture(GL_TEXTURE4); glDisable(GL_TEXTURE_2D); }
|
||||
if(pFoW != NULL) { glActiveTexture(GL_TEXTURE3); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE2); glDisable(GL_TEXTURE_2D); }
|
||||
if(overlayTex != 0) { glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); }
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if(baseTex != 0) glDisable(GL_TEXTURE_2D);
|
||||
|
@ -568,7 +587,6 @@ bool CStdGL::RestoreDeviceObjects()
|
|||
const char * linedata = byByteCnt == 2 ? "\xff\xf0\xff\xff" : "\xff\xff\xff\x00\xff\xff\xff\xff";
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 4, 1, 2, 0, GL_BGRA, byByteCnt == 2 ? GL_UNSIGNED_SHORT_4_4_4_4_REV : GL_UNSIGNED_INT_8_8_8_8_REV, linedata);
|
||||
|
||||
|
||||
MaxTexSize = 64;
|
||||
GLint s = 0;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &s);
|
||||
|
@ -606,6 +624,7 @@ bool CStdGL::RestoreDeviceObjects()
|
|||
"uniform sampler2D Texture;"
|
||||
"uniform sampler2D Overlay;"
|
||||
"uniform sampler2D Light;"
|
||||
"uniform sampler2D Ambient;"
|
||||
"uniform sampler2D Normal;"
|
||||
"varying vec2 texcoord;"
|
||||
"void main()"
|
||||
|
@ -624,41 +643,30 @@ bool CStdGL::RestoreDeviceObjects()
|
|||
// Add alpha for base and overlay, and use weighted mean of clrmod alpha
|
||||
" primaryColor.a = clamp(primaryColor.a + overlayColor.a, 0.0, 1.0) * (primaryColor.a * clrMod.a + overlayColor.a * overlayClrMod.a) / (primaryColor.a + overlayColor.a);"
|
||||
// Add fog of war (light)
|
||||
" vec3 lightDir, normalDir;"
|
||||
" float lightIntensity;"
|
||||
|
||||
" vec3 lightClr = vec3(1.0, 1.0, 1.0);"
|
||||
" if(fUseLight != 0)"
|
||||
" {"
|
||||
" vec4 lightPx = texture2D(Light, (gl_TextureMatrix[2] * gl_FragCoord).xy);"
|
||||
" vec3 lightDir = normalize(vec3(vec2(1.0, 1.0) - lightPx.gb * 3.0, 0.3));"
|
||||
" float lightIntensity = 2.0 * lightPx.r;"
|
||||
" vec3 normalDir;"
|
||||
" if(fUseNormal != 0)"
|
||||
" {"
|
||||
" lightDir = normalize(vec3(vec2(1.0, 1.0) - lightPx.gb * 3.0, 0.3));"
|
||||
// Overwrite Z component of normal with 0.3 -- might make this configurable later
|
||||
" vec4 normalPx = texture2D(Normal, texcoord);"
|
||||
" normalDir = normalize(vec3( (normalPx.xy - vec2(0.5, 0.5))*2.0, 0.3));"
|
||||
" lightIntensity = 2.0 * lightPx.r;"
|
||||
" }"
|
||||
" else"
|
||||
" {"
|
||||
// No normal map -- front-facing light and normals, only take light intensity into account
|
||||
" lightDir = vec3(0.0, 0.0, 1.0);"
|
||||
" normalDir = vec3(0.0, 0.0, 1.0);"
|
||||
" lightIntensity = lightPx.r;"
|
||||
" }"
|
||||
" float ambient = texture2D(Ambient, (gl_TextureMatrix[3] * gl_FragCoord).xy).r;"
|
||||
" lightClr = ambient * lightClr + (1.0 - ambient) * vec3(1.0, 1.0, 1.0) * lightIntensity * (0.25 + 0.75 * dot(normalDir, lightDir));"
|
||||
" }"
|
||||
" else"
|
||||
" {"
|
||||
// No light -- place a simple directional light from the front (equivalent to the behaviour in the main branch, modulo interpolated normals)
|
||||
" lightDir = vec3(0.0, 0.0, 1.0);"
|
||||
" normalDir = vec3(0.0, 0.0, 1.0);"
|
||||
" lightIntensity = 1.0;"
|
||||
" }"
|
||||
" vec4 lightClr = vec4(vec3(1.0, 1.0, 1.0) * lightIntensity * dot(normalDir, lightDir), 1.0);"
|
||||
// Final output, depending on blit mode
|
||||
" if(fMod2 != 0)"
|
||||
" gl_FragColor = clamp(2.0 * primaryColor * lightClr - 0.5, 0.0, 1.0);"
|
||||
" gl_FragColor = clamp(2.0 * primaryColor * vec4(lightClr, 1.0) - 0.5, 0.0, 1.0);"
|
||||
" else"
|
||||
" gl_FragColor = clamp(primaryColor * lightClr, 0.0, 1.0);"
|
||||
" gl_FragColor = clamp(primaryColor * vec4(lightClr, 1.0), 0.0, 1.0);"
|
||||
"}";
|
||||
|
||||
C4DrawGLShader vertex_shader(StdMeshMaterialShader::VERTEX);
|
||||
|
|
|
@ -147,6 +147,7 @@ namespace
|
|||
params.AddParameter("oc_Mod2", StdMeshMaterialShaderParameter::AUTO).GetAuto() = StdMeshMaterialShaderParameter::AUTO_OC_MOD2;
|
||||
params.AddParameter("oc_UseLight", StdMeshMaterialShaderParameter::AUTO).GetAuto() = StdMeshMaterialShaderParameter::AUTO_OC_USE_LIGHT;
|
||||
params.AddParameter("oc_Light", StdMeshMaterialShaderParameter::AUTO).GetAuto() = StdMeshMaterialShaderParameter::AUTO_OC_LIGHT;
|
||||
params.AddParameter("oc_Ambient", StdMeshMaterialShaderParameter::AUTO).GetAuto() = StdMeshMaterialShaderParameter::AUTO_OC_AMBIENT;
|
||||
|
||||
return FormatString(
|
||||
"varying vec3 normal;" // linearly interpolated -- not necessarily normalized
|
||||
|
@ -157,29 +158,32 @@ namespace
|
|||
"uniform int oc_Mod2;"
|
||||
"uniform int oc_UseLight;"
|
||||
"uniform sampler2D oc_Light;"
|
||||
"uniform sampler2D oc_Ambient;"
|
||||
"void main()"
|
||||
"{"
|
||||
" vec3 lightDir;"
|
||||
" float lightIntensity;"
|
||||
" vec4 diffuse;"
|
||||
" if(oc_UseLight != 0)"
|
||||
" {"
|
||||
// Light calculation
|
||||
" vec4 lightPx = texture2D(oc_Light, (gl_TextureMatrix[%d] * gl_FragCoord).xy);"
|
||||
" lightDir = normalize(vec3(vec2(1.0, 1.0) - lightPx.gb * 3.0, 0.3));"
|
||||
" lightIntensity = 2.0 * lightPx.r;"
|
||||
" vec3 lightDir = normalize(vec3(vec2(1.0, 1.0) - lightPx.gb * 3.0, 0.3));"
|
||||
" float lightIntensity = 2.0 * lightPx.r;"
|
||||
" float ambient = texture2D(oc_Ambient, (gl_TextureMatrix[%d] * gl_FragCoord).xy).r;"
|
||||
// Don't actually use the ambient part of the material and instead a diffuse light from the front, like in the master branch
|
||||
// Because meshes are not tuned for ambient light at the moment, every mesh material would need to be fixed.
|
||||
// Otherwise the first term would be ambient * gl_FrontMaterial.ambient
|
||||
" diffuse = ambient * (gl_FrontMaterial.emission + gl_FrontMaterial.diffuse * (0.25 + 0.75 * max(dot(normalize(normal), vec3(0.0, 0.0, 1.0)), 0.0))) + (1.0 - ambient) * lightIntensity * (gl_FrontMaterial.emission + gl_FrontMaterial.diffuse * (0.25 + 0.75 * max(dot(normalize(normal), lightDir), 0.0)));"
|
||||
" }"
|
||||
" else"
|
||||
" {"
|
||||
// No light -- place a simple directional light from the front (equivalent to the behaviour in the main branch, modulo interpolated normals)
|
||||
" lightDir = vec3(0.0, 0.0, 1.0);"
|
||||
" lightIntensity = 1.0;"
|
||||
// No light -- place a simple directional light from the front (equivalent to the behaviour in
|
||||
// the master branch, modulo interpolated normals)
|
||||
" vec3 lightDir = vec3(0.0, 0.0, 1.0);"
|
||||
" diffuse = gl_FrontMaterial.emission + gl_FrontMaterial.diffuse * max(dot(normalize(normal), lightDir), 0.0);"
|
||||
" }"
|
||||
" vec4 diffuse = gl_FrontMaterial.emission + 0.0 * gl_FrontMaterial.ambient + gl_FrontMaterial.diffuse * max(dot(normalize(normal), lightDir), 0.0);" // ambient is ignored since we don't have ambient lights
|
||||
// Texture units from material script
|
||||
" vec4 currentColor = diffuse;"
|
||||
" %s"
|
||||
// Intensity (lightPx.r) only applies to RGB components, not A
|
||||
" currentColor = vec4(lightIntensity * currentColor.rgb, currentColor.a);"
|
||||
// Output with color modulation and mod2
|
||||
" if(oc_Mod2 != 0)"
|
||||
" gl_FragColor = clamp(2.0 * currentColor * oc_ColorModulation - 0.5, 0.0, 1.0);"
|
||||
|
@ -187,7 +191,7 @@ namespace
|
|||
" gl_FragColor = clamp(currentColor * oc_ColorModulation, 0.0, 1.0);"
|
||||
"}",
|
||||
textureUnitDeclCode.getData(),
|
||||
(int)texIndex, // The light texture is added after all other textures
|
||||
(int)texIndex, (int)texIndex + 1, // The light and ambient textures are added after all other textures
|
||||
textureUnitCode.getData()
|
||||
);
|
||||
}
|
||||
|
@ -481,7 +485,7 @@ namespace
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ResolveAutoParameter(StdMeshMaterialShaderParameter& parameter, StdMeshMaterialShaderParameter::Auto value, DWORD dwModClr, DWORD dwPlayerColor, DWORD dwBlitMode, const C4FoWRegion* pFoW, float zoom, std::vector<GLint>& textures)
|
||||
bool ResolveAutoParameter(StdMeshMaterialShaderParameter& parameter, StdMeshMaterialShaderParameter::Auto value, DWORD dwModClr, DWORD dwPlayerColor, DWORD dwBlitMode, const C4FoWRegion* pFoW, const C4Rect& clipRect, std::vector<GLint>& textures)
|
||||
{
|
||||
float* out;
|
||||
GLint texIndex;
|
||||
|
@ -524,7 +528,7 @@ namespace
|
|||
|
||||
// Load the texture
|
||||
glActiveTexture(GL_TEXTURE0+texIndex);
|
||||
glClientActiveTexture(GL_TEXTURE0+texIndex);
|
||||
//glClientActiveTexture(GL_TEXTURE0+texIndex);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, pFoW->getSurface()->ppTex[0]->texName);
|
||||
|
||||
|
@ -537,7 +541,36 @@ namespace
|
|||
glLoadIdentity();
|
||||
glTranslatef(0.0f, 1.0f - (float)LightRect.Hgt/(float)iLightHgt, 0.0f);
|
||||
glScalef(1.0f/iLightWdt, 1.0f/iLightHgt, 1.0f);
|
||||
glScalef(1.0f/zoom, 1.0f/zoom, 1.0f);
|
||||
glScalef( (float)LightRect.Wdt / (float)clipRect.Wdt, (float)LightRect.Hgt / (float)clipRect.Hgt, 1.0f);
|
||||
|
||||
parameter.SetType(StdMeshMaterialShaderParameter::INT);
|
||||
parameter.GetInt() = texIndex;
|
||||
return true;
|
||||
case StdMeshMaterialShaderParameter::AUTO_OC_AMBIENT:
|
||||
if(!pFoW) return false;
|
||||
|
||||
texIndex = textures.size();
|
||||
textures.push_back(texIndex);
|
||||
|
||||
// Load the texture
|
||||
glActiveTexture(GL_TEXTURE0+texIndex);
|
||||
//glClientActiveTexture(GL_TEXTURE0+texIndex);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, pFoW->getFoW()->Ambient.Tex);
|
||||
|
||||
// Transformation matrix for the texture coordinates
|
||||
// TODO: Should maybe be a separate uniform variable?
|
||||
LightRect = pFoW->getRegion();
|
||||
iLightWdt = pFoW->getSurface()->Wdt;
|
||||
iLightHgt = pFoW->getSurface()->Hgt;
|
||||
|
||||
// Setup the texture matrix
|
||||
glLoadIdentity();
|
||||
glScalef(1.0f/pFoW->getFoW()->Ambient.GetLandscapeWidth(), 1.0f/pFoW->getFoW()->Ambient.GetLandscapeHeight(), 1.0f);
|
||||
glTranslatef(LightRect.x, LightRect.y, 0.0f);
|
||||
glScalef( (float)LightRect.Wdt / (float)clipRect.Wdt, (float)LightRect.Hgt / (float)clipRect.Hgt, 1.0f);
|
||||
glTranslatef(0.0f, clipRect.Hgt, 0.0f);
|
||||
glScalef(1.0f, -1.0f, 1.0f);
|
||||
|
||||
parameter.SetType(StdMeshMaterialShaderParameter::INT);
|
||||
parameter.GetInt() = texIndex;
|
||||
|
@ -548,7 +581,7 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
void RenderSubMeshImpl(const StdMeshInstance& mesh_instance, const StdSubMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, float zoom, bool parity)
|
||||
void RenderSubMeshImpl(const StdMeshInstance& mesh_instance, const StdSubMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, const C4Rect& clipRect, bool parity)
|
||||
{
|
||||
const StdMeshMaterial& material = instance.GetMaterial();
|
||||
assert(material.BestTechniqueIndex != -1);
|
||||
|
@ -720,7 +753,7 @@ namespace
|
|||
StdMeshMaterialShaderParameter auto_resolved;
|
||||
if(parameter->GetType() == StdMeshMaterialShaderParameter::AUTO)
|
||||
{
|
||||
if(!ResolveAutoParameter(auto_resolved, parameter->GetAuto(), dwModClr, dwPlayerColor, dwBlitMode, pFoW, zoom, textures))
|
||||
if(!ResolveAutoParameter(auto_resolved, parameter->GetAuto(), dwModClr, dwPlayerColor, dwBlitMode, pFoW, clipRect, textures))
|
||||
continue;
|
||||
parameter = &auto_resolved;
|
||||
}
|
||||
|
@ -768,9 +801,9 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
void RenderMeshImpl(StdMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, float zoom, bool parity); // Needed by RenderAttachedMesh
|
||||
void RenderMeshImpl(StdMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, const C4Rect& clipRect, bool parity); // Needed by RenderAttachedMesh
|
||||
|
||||
void RenderAttachedMesh(StdMeshInstance::AttachedMesh* attach, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, float zoom, bool parity)
|
||||
void RenderAttachedMesh(StdMeshInstance::AttachedMesh* attach, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, const C4Rect& clipRect, bool parity)
|
||||
{
|
||||
const StdMeshMatrix& FinalTrans = attach->GetFinalTransformation();
|
||||
|
||||
|
@ -797,7 +830,7 @@ namespace
|
|||
// TODO: Take attach transform's parity into account
|
||||
glPushMatrix();
|
||||
glMultMatrixf(attach_trans_gl);
|
||||
RenderMeshImpl(*attach->Child, dwModClr, dwBlitMode, dwPlayerColor, pFoW, zoom, parity);
|
||||
RenderMeshImpl(*attach->Child, dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, parity);
|
||||
glPopMatrix();
|
||||
|
||||
#if 0
|
||||
|
@ -817,7 +850,7 @@ namespace
|
|||
#endif
|
||||
}
|
||||
|
||||
void RenderMeshImpl(StdMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, float zoom, bool parity)
|
||||
void RenderMeshImpl(StdMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, const C4Rect& clipRect, bool parity)
|
||||
{
|
||||
const StdMesh& mesh = instance.GetMesh();
|
||||
|
||||
|
@ -825,7 +858,7 @@ namespace
|
|||
StdMeshInstance::AttachedMeshIter attach_iter = instance.AttachedMeshesBegin();
|
||||
|
||||
for (; attach_iter != instance.AttachedMeshesEnd() && ((*attach_iter)->GetFlags() & StdMeshInstance::AM_DrawBefore); ++attach_iter)
|
||||
RenderAttachedMesh(*attach_iter, dwModClr, dwBlitMode, dwPlayerColor, pFoW, zoom, parity);
|
||||
RenderAttachedMesh(*attach_iter, dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, parity);
|
||||
|
||||
GLint modes[2];
|
||||
// Check if we should draw in wireframe or normal mode
|
||||
|
@ -838,7 +871,7 @@ namespace
|
|||
|
||||
// Render each submesh
|
||||
for (unsigned int i = 0; i < mesh.GetNumSubMeshes(); ++i)
|
||||
RenderSubMeshImpl(instance, instance.GetSubMeshOrdered(i), dwModClr, dwBlitMode, dwPlayerColor, pFoW, zoom, parity);
|
||||
RenderSubMeshImpl(instance, instance.GetSubMeshOrdered(i), dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, parity);
|
||||
|
||||
// reset old mode to prevent rendering errors
|
||||
if(dwBlitMode & C4GFXBLIT_WIREFRAME)
|
||||
|
@ -868,7 +901,7 @@ namespace
|
|||
|
||||
// Render non-AM_DrawBefore attached meshes
|
||||
for (; attach_iter != instance.AttachedMeshesEnd(); ++attach_iter)
|
||||
RenderAttachedMesh(*attach_iter, dwModClr, dwBlitMode, dwPlayerColor, pFoW, zoom, parity);
|
||||
RenderAttachedMesh(*attach_iter, dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, parity);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1082,7 +1115,12 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw
|
|||
|
||||
DWORD dwModClr = BlitModulated ? BlitModulateClr : 0xffffffff;
|
||||
|
||||
RenderMeshImpl(instance, dwModClr, dwBlitMode, dwPlayerColor, pFoW, Zoom, parity);
|
||||
C4Rect clipRect;
|
||||
clipRect.Wdt = Min(iClipX2, RenderTarget->Wdt-1)-iClipX1+1;
|
||||
clipRect.Hgt = Min(iClipY2, RenderTarget->Hgt-1)-iClipY1+1;
|
||||
clipRect.x = iClipX1; if(clipRect.x < 0) { clipRect.Wdt += clipRect.x; clipRect.x = 0; }
|
||||
clipRect.y = iClipY1; if(clipRect.y < 0) { clipRect.Hgt += clipRect.y; clipRect.y = 0; }
|
||||
RenderMeshImpl(instance, dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, parity);
|
||||
|
||||
glUseProgramObjectARB(0);
|
||||
|
||||
|
|
|
@ -1306,7 +1306,7 @@ bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bo
|
|||
}
|
||||
|
||||
// progress
|
||||
Game.SetInitProgress(80);
|
||||
Game.SetInitProgress(75);
|
||||
|
||||
// copy noscan-var
|
||||
NoScan=Game.C4S.Landscape.NoScan!=0;
|
||||
|
@ -1338,7 +1338,7 @@ bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bo
|
|||
// Init out-of-landscape pixels for bottom
|
||||
InitTopAndBottomRowPix();
|
||||
|
||||
Game.SetInitProgress(84);
|
||||
Game.SetInitProgress(80);
|
||||
|
||||
if (Config.General.DebugRec)
|
||||
{
|
||||
|
@ -1404,6 +1404,9 @@ bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bo
|
|||
// and not creating the map
|
||||
Game.FixRandom(Game.RandomSeed);
|
||||
|
||||
// Create ambient light map after landscape creation
|
||||
pFoW->Ambient.CreateFromLandscape(*this, 10., 50., 0.25);
|
||||
Game.SetInitProgress(84);
|
||||
|
||||
// Success
|
||||
rfLoaded=true;
|
||||
|
|
|
@ -52,12 +52,14 @@ static const char *GetUniformName(int iUniform)
|
|||
case C4LRU_ScalerTex: return "scalerTex";
|
||||
case C4LRU_MaterialTex: return "materialTex";
|
||||
case C4LRU_LightTex: return "lightTex";
|
||||
case C4LRU_AmbientTex: return "ambientTex";
|
||||
case C4LRU_Resolution: return "resolution";
|
||||
case C4LRU_Center: return "center";
|
||||
case C4LRU_MatMap: return "matMap";
|
||||
case C4LRU_MatMapTex: return "matMapTex";
|
||||
case C4LRU_MaterialDepth:return "materialDepth";
|
||||
case C4LRU_MaterialSize: return "materialSize";
|
||||
case C4LRU_AmbientScale: return "ambientScale";
|
||||
}
|
||||
assert(false);
|
||||
return "mysterious";
|
||||
|
@ -1011,7 +1013,16 @@ void C4LandscapeRenderGL::Draw(const C4TargetFacet &cgo, const C4FoWRegion &Ligh
|
|||
if (hUniforms[C4LRU_MaterialSize] != GLhandleARB(-1))
|
||||
glUniform2fARB(hUniforms[C4LRU_MaterialSize], float(iMaterialWidth) / ::Game.C4S.Landscape.MaterialZoom,
|
||||
float(iMaterialHeight) / ::Game.C4S.Landscape.MaterialZoom);
|
||||
|
||||
if (hUniforms[C4LRU_AmbientScale] != GLhandleARB(-1))
|
||||
{
|
||||
// factor between actual landscape size and surface size, so that we can use the landscape
|
||||
// coordinates for the ambient map lookup.
|
||||
// TODO: These could actually be shader constants, and do not really need to be uniforms...
|
||||
const float sx = static_cast<float>(Surfaces[0]->Wdt) / iWidth;
|
||||
const float sy = static_cast<float>(Surfaces[0]->Hgt) / iHeight;
|
||||
glUniform2fARB(hUniforms[C4LRU_AmbientScale], sx, sy);
|
||||
}
|
||||
|
||||
// Setup facilities for texture unit allocation (gimme local functions...)
|
||||
int iUnit = 0; int iUnitMap[32]; ZeroMem(iUnitMap, sizeof(iUnitMap));
|
||||
#define ALLOC_UNIT(hUniform, iType) do { \
|
||||
|
@ -1052,6 +1063,13 @@ void C4LandscapeRenderGL::Draw(const C4TargetFacet &cgo, const C4FoWRegion &Ligh
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
if(hUniforms[C4LRU_AmbientTex] != GLhandleARB(-1))
|
||||
{
|
||||
ALLOC_UNIT(hUniforms[C4LRU_AmbientTex], GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, Light.getFoW()->Ambient.Tex);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
if(hUniforms[C4LRU_ScalerTex] != GLhandleARB(-1))
|
||||
{
|
||||
ALLOC_UNIT(hUniforms[C4LRU_ScalerTex], GL_TEXTURE_2D);
|
||||
|
|
|
@ -24,6 +24,7 @@ enum C4LR_Uniforms
|
|||
C4LRU_ScalerTex,
|
||||
C4LRU_MaterialTex,
|
||||
C4LRU_LightTex,
|
||||
C4LRU_AmbientTex,
|
||||
|
||||
C4LRU_Resolution,
|
||||
C4LRU_Center,
|
||||
|
@ -31,6 +32,7 @@ enum C4LR_Uniforms
|
|||
C4LRU_MatMapTex,
|
||||
C4LRU_MaterialDepth,
|
||||
C4LRU_MaterialSize,
|
||||
C4LRU_AmbientScale,
|
||||
|
||||
C4LRU_Count
|
||||
};
|
||||
|
|
|
@ -39,7 +39,6 @@ void C4FoW::Add(C4Object *pObj)
|
|||
pLight->pNext = pLights;
|
||||
pLights = pLight;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void C4FoW::Remove(C4Object *pObj)
|
||||
|
@ -73,4 +72,4 @@ void C4FoW::Render(C4FoWRegion *pRegion, const C4TargetFacet *pOnScreen)
|
|||
{
|
||||
for (C4FoWLight *pLight = pLights; pLight; pLight = pLight->getNext())
|
||||
pLight->Render(pRegion, pOnScreen);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "C4Rect.h"
|
||||
#include "C4Object.h"
|
||||
#include "C4FoWLight.h"
|
||||
#include "C4FoWAmbient.h"
|
||||
|
||||
/**
|
||||
This class holds all lights for the objects. It forwards the update, invalidation and render calls each to the
|
||||
|
@ -22,6 +23,8 @@ private:
|
|||
class C4FoWLight *pLights;
|
||||
|
||||
public:
|
||||
C4FoWAmbient Ambient;
|
||||
|
||||
void Clear();
|
||||
|
||||
/** Updates the view range of the given object in its associated light or create a new light if none exists yet. */
|
||||
|
@ -37,4 +40,4 @@ public:
|
|||
void Render(class C4FoWRegion *pRegion, const C4TargetFacet *pOnScreen = NULL);
|
||||
};
|
||||
|
||||
#endif // C4FOW_H
|
||||
#endif // C4FOW_H
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
|
||||
#include "C4Include.h"
|
||||
#include "C4FoWAmbient.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template<typename IFT>
|
||||
double AmbientForPix(int x0, int y0, int R, const IFT& ift)
|
||||
{
|
||||
double d = 0.;
|
||||
|
||||
for(int y = y0 - R; y <= y0 + R; ++y)
|
||||
{
|
||||
for(int x = x0 - R; x <= x0 + R; ++x)
|
||||
{
|
||||
const double l2 = (x - x0) * (x - x0) + (y - y0) * (y - y0);
|
||||
if(l2 > R*R || ift(x, y)) continue;
|
||||
|
||||
if(x == x0 && y == y0)
|
||||
{
|
||||
// Central pixel, this corresponds to the integral
|
||||
// for a round pixel with the same area as a square pixel
|
||||
d += 2 * sqrt(M_PI);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non-central pixel; assume same weight over the full
|
||||
// pixel.
|
||||
d += 1. / sqrt(l2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
// Everything is sky, independent of the landscape
|
||||
// This is used to obtain the normalization factor
|
||||
struct IFTFull {
|
||||
IFTFull() {}
|
||||
bool operator()(int x, int y) const { return false; }
|
||||
};
|
||||
|
||||
struct IFTZoom {
|
||||
IFTZoom(const C4Landscape& landscape, double sx, double sy):
|
||||
Landscape(landscape), sx(sx), sy(sy) {}
|
||||
|
||||
// Returns whether zoomed coordinate is IFT or not
|
||||
bool operator()(int x, int y) const
|
||||
{
|
||||
// Landscape coordinates
|
||||
const int lx = static_cast<int>((x + 0.5) * sx);
|
||||
const int ly = static_cast<int>((y + 0.5) * sy);
|
||||
// IFT check
|
||||
//return (Landscape.GetPix(lx, ly) & IFT) != 0;
|
||||
return Landscape.GetPix(lx, ly) != 0;
|
||||
}
|
||||
|
||||
const C4Landscape& Landscape;
|
||||
const double sx;
|
||||
const double sy;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
C4FoWAmbient::C4FoWAmbient()
|
||||
: Tex(0), SizeX(0), SizeY(0), LandscapeX(0), LandscapeY(0)
|
||||
{
|
||||
}
|
||||
|
||||
C4FoWAmbient::~C4FoWAmbient()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void C4FoWAmbient::Clear()
|
||||
{
|
||||
if(Tex != 0) glDeleteTextures(1, &Tex);
|
||||
Tex = 0;
|
||||
SizeX = SizeY = 0;
|
||||
LandscapeX = LandscapeY = 0;
|
||||
}
|
||||
|
||||
void C4FoWAmbient::CreateFromLandscape(const C4Landscape& landscape, double resolution, double radius, double full_coverage)
|
||||
{
|
||||
// Clear old map
|
||||
if(Tex != 0) Clear();
|
||||
|
||||
// Number of zoomed pixels
|
||||
LandscapeX = landscape.Width;
|
||||
LandscapeY = landscape.Height;
|
||||
SizeX = Min<unsigned int>(static_cast<unsigned int>(ceil(LandscapeX / resolution)), pDraw->MaxTexSize);
|
||||
SizeY = Min<unsigned int>(static_cast<unsigned int>(ceil(LandscapeY / resolution)), pDraw->MaxTexSize);
|
||||
|
||||
// Factor to go from zoomed to landscape coordinates
|
||||
const double zoom_x = static_cast<double>(landscape.Width) / (float)(SizeX);
|
||||
const double zoom_y = static_cast<double>(landscape.Height) / (float)(SizeY);
|
||||
|
||||
// Zoomed radius
|
||||
const double R = (radius / sqrt(zoom_x * zoom_y) + 0.5);
|
||||
// Normalization factor with the full circle
|
||||
// The analytic result is 2*R*M_PI, and this number is typically close to it
|
||||
const double norm = AmbientForPix(0, 0, R, IFTFull()) * full_coverage;
|
||||
// Create the ambient map
|
||||
IFTZoom iftZoom(landscape, zoom_x, zoom_y);
|
||||
float* ambient = new float[SizeX * SizeY];
|
||||
for(unsigned int y = 0; y < SizeY; ++y)
|
||||
{
|
||||
for(unsigned int x = 0; x < SizeX; ++x)
|
||||
{
|
||||
ambient[y * SizeX + x] = Min(AmbientForPix(x, y, R, iftZoom) / norm, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
CSurface8 debug(SizeX, SizeY);
|
||||
for(unsigned int y = 0; y < SizeY; ++y)
|
||||
{
|
||||
for(unsigned int x = 0; x < SizeX; ++x)
|
||||
{
|
||||
debug.SetPix(x, y, int(ambient[y * SizeX + x] * 255. + 0.5));
|
||||
CStdPalette pal;
|
||||
for(int i = 0; i < 256; ++i)
|
||||
pal.Colors[i] = i + (i << 8) + (i << 16);
|
||||
debug.Save("Ambient.bmp", &pal);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Store it in a GL texture
|
||||
glGenTextures(1, &Tex);
|
||||
glBindTexture(GL_TEXTURE_2D, Tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 1, SizeX, SizeY, 0, GL_RED, GL_FLOAT, ambient);
|
||||
delete[] ambient;
|
||||
|
||||
LogF("Created %ux%u ambient map", SizeX, SizeY);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
#ifndef C4FOWAMBIENT_H
|
||||
#define C4FOWAMBIENT_H
|
||||
|
||||
//#include <GL/gl.h>
|
||||
#include <C4Landscape.h>
|
||||
|
||||
/**
|
||||
This class manages a texture that holds the ambient light intensity
|
||||
*/
|
||||
class C4FoWAmbient
|
||||
{
|
||||
public:
|
||||
C4FoWAmbient();
|
||||
~C4FoWAmbient();
|
||||
|
||||
GLuint Tex;
|
||||
|
||||
private:
|
||||
// Landscape size
|
||||
unsigned int LandscapeX;
|
||||
unsigned int LandscapeY;
|
||||
// Size of ambient map
|
||||
unsigned int SizeX;
|
||||
unsigned int SizeY;
|
||||
|
||||
public:
|
||||
void Clear();
|
||||
|
||||
// High resolution will make the map coarser, but speed up the generation process
|
||||
// and save video memory.
|
||||
// The radius specifies the radius of landscape pixels that are sampled around each pixel
|
||||
// to obtain the ambient light.
|
||||
// full_coverage is a number between 0 and 1, and it specifies what portion of the full circle
|
||||
// needs to be illuminated for full ambient light intensity.
|
||||
void CreateFromLandscape(const C4Landscape& landscape, double resolution, double radius, double full_coverage);
|
||||
|
||||
unsigned int GetLandscapeWidth() const { return LandscapeX; }
|
||||
unsigned int GetLandscapeHeight() const { return LandscapeY; }
|
||||
};
|
||||
|
||||
#endif // C4FOWAMBIENT_H
|
|
@ -21,6 +21,7 @@ private:
|
|||
GLuint hFrameBufDraw, hFrameBufRead;
|
||||
|
||||
public:
|
||||
const C4FoW* getFoW() const { return pFoW; }
|
||||
const C4Rect &getRegion() const { return Region; }
|
||||
const C4Surface *getSurface() const { return pSurface; }
|
||||
const C4Surface *getBackSurface() const { return pBackSurface; }
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace
|
|||
{ "oc_mod2", StdMeshMaterialShaderParameter::AUTO_OC_MOD2 },
|
||||
{ "oc_use_light", StdMeshMaterialShaderParameter::AUTO_OC_USE_LIGHT },
|
||||
{ "oc_light", StdMeshMaterialShaderParameter::AUTO_OC_LIGHT },
|
||||
{ "oc_ambient", StdMeshMaterialShaderParameter::AUTO_OC_AMBIENT },
|
||||
{ NULL, static_cast<StdMeshMaterialShaderParameter::Auto>(0) }
|
||||
};
|
||||
|
||||
|
|
|
@ -59,7 +59,8 @@ public:
|
|||
AUTO_OC_COLOR_MODULATION,
|
||||
AUTO_OC_MOD2,
|
||||
AUTO_OC_USE_LIGHT,
|
||||
AUTO_OC_LIGHT
|
||||
AUTO_OC_LIGHT,
|
||||
AUTO_OC_AMBIENT
|
||||
|
||||
// TODO: Other ogre auto values
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue