Add SetAmbientBrightness and GetAmbientBrightness script functions

issue1247
Armin Burgmeier 2014-11-19 11:18:07 -05:00
parent d60c74c6b6
commit db6df15377
16 changed files with 133 additions and 23 deletions

View File

@ -54,6 +54,11 @@
<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>
<row>
<literal_col>oc_ambient_brightness</literal_col>
<literal_col>float</literal_col>
<col>Global intensity of the ambient light, as set by the script function <funclink>SetAmbientBrightness</funclink>.</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>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>GetAmbientBrightness</title>
<category>Landscape</category>
<subcat>View</subcat>
<version>5.6 OC</version>
<syntax>
<rtype>int</rtype>
</syntax>
<desc>Queries the ambient brightness value set with <funclink>SetAmbientBrightness</funclink>. The initial brightness value is 100%.</desc>
<examples>
<example>
<code><funclink>SetAmbientBrightness</funclink>(<funclink>Min</funclink>(GetAmbientBrightness() + 10, 100));</code>
<text>Brightens up the ambient lighting by 10%, but does not exceed 100%.</text>
</example>
</examples>
<related>
<funclink>SetAmbientBrightness</funclink>
</related>
</func>
<author>Clonk-Karl</author><date>2014-11</date>
</funcs>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>SetAmbientBrightness</title>
<category>Landscape</category>
<subcat>View</subcat>
<version>5.6 OC</version>
<syntax>
<rtype>void</rtype>
<params>
<param>
<type>int</type>
<name>brightness</name>
<desc>New ambient brightness value. The value should be between 0 and 100, where 0 means no ambient light and 100 means full ambient light.</desc>
</param>
</params>
</syntax>
<desc>Changes the brightness of the ambient light. In regions with less than 100% ambient light, light sources such as Clonks will generate dynamic light.</desc>
<examples>
<example>
<code>SetAmbientBrightness(0);</code>
<text>Disables ambient lighting completely, so that everywhere on the map only dynamic light sources make light.</text>
</example>
</examples>
<related>
<funclink>GetAmbientBrightness</funclink>
</related>
</func>
<author>Clonk-Karl</author><date>2014-11</date>
</funcs>

View File

@ -5,11 +5,12 @@ uniform sampler2D ambientTex;
// Factor between landscape coordinates and ambient map coordinates
uniform vec2 ambientScale;
uniform float ambientBrightness;
slice texture+6
{
// Ambient light
float ambient = texture2D(ambientTex, ambientScale * texCoo).r;
float ambient = texture2D(ambientTex, ambientScale * texCoo).r * ambientBrightness;
}
slice light+1

View File

@ -37,6 +37,7 @@ material NormalMap
param_named_auto oc_UseLight oc_use_light
param_named_auto oc_Light oc_light
param_named_auto oc_Ambient oc_ambient
param_named_auto oc_AmbientBrightness oc_ambient_brightness
param_named basemap int 0
param_named normalmap int 1

View File

@ -7,6 +7,7 @@ uniform vec4 oc_ColorModulation;
uniform int oc_UseLight;
uniform sampler2D oc_Light;
uniform sampler2D oc_Ambient;
uniform float oc_AmbientBrightness;
// This is mostly copied from C4DrawMeshGL.cpp -- only the calculation
// of the normal has been replaced
@ -19,8 +20,8 @@ void main()
vec4 lightPx = texture2D(oc_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;
float ambient = texture2D(oc_Ambient, (gl_TextureMatrix[3] * gl_FragCoord).xy).r;
lightClr = vec4(ambient * (gl_FrontMaterial.emission.rgb + gl_FrontMaterial.diffuse.rgb * (0.25 + 0.75 * max(dot(normalDir, vec3(0.0, 0.0, 1.0)), 0.0))) + (1.0 - ambient) * lightIntensity * (gl_FrontMaterial.emission.rgb + gl_FrontMaterial.diffuse.rgb * (0.25 + 0.75 * max(dot(normalDir, lightDir), 0.0))), gl_FrontMaterial.emission.a + gl_FrontMaterial.diffuse.a);
float ambient = texture2D(oc_Ambient, (gl_TextureMatrix[3] * gl_FragCoord).xy).r * oc_AmbientBrightness;
lightClr = vec4(ambient * (gl_FrontMaterial.emission.rgb + gl_FrontMaterial.diffuse.rgb * (0.25 + 0.75 * max(dot(normalDir, vec3(0.0, 0.0, 1.0)), 0.0))) + (1.0 - min(ambient, 1.0)) * lightIntensity * (gl_FrontMaterial.emission.rgb + gl_FrontMaterial.diffuse.rgb * (0.25 + 0.75 * max(dot(normalDir, lightDir), 0.0))), gl_FrontMaterial.emission.a + gl_FrontMaterial.diffuse.a);
}
else
{

View File

@ -41,6 +41,7 @@
#include <C4Texture.h>
#include <C4Weather.h>
#include <C4Viewport.h>
#include <C4FoW.h>
// undocumented!
static bool FnIncinerateLandscape(C4PropList * _this, long iX, long iY)
@ -1088,6 +1089,20 @@ static long FnGetTemperature(C4PropList * _this)
return ::Weather.GetTemperature();
}
static C4Void FnSetAmbientBrightness(C4PropList * _this, long iBrightness)
{
if (::Landscape.pFoW)
::Landscape.pFoW->Ambient.SetBrightness(iBrightness / 100.);
return C4Void();
}
static long FnGetAmbientBrightness(C4PropList * _this)
{
if (!::Landscape.pFoW)
return 100;
return static_cast<long>(::Landscape.pFoW->Ambient.GetBrightness() * 100. + 0.5);
}
static C4Void FnSetSeason(C4PropList * _this, long iSeason)
{
::Weather.SetSeason(iSeason);
@ -2577,6 +2592,8 @@ void InitGameFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "CanInsertMaterial", FnCanInsertMaterial);
AddFunc(pEngine, "LandscapeWidth", FnLandscapeWidth);
AddFunc(pEngine, "LandscapeHeight", FnLandscapeHeight);
AddFunc(pEngine, "SetAmbientBrightness", FnSetAmbientBrightness);
AddFunc(pEngine, "GetAmbientBrightness", FnGetAmbientBrightness);
AddFunc(pEngine, "SetSeason", FnSetSeason);
AddFunc(pEngine, "GetSeason", FnGetSeason);
AddFunc(pEngine, "SetClimate", FnSetClimate);

View File

@ -300,6 +300,7 @@ void CStdGL::SetupMultiBlt(const C4BltTransform* pTransform, GLuint baseTex, GLu
GLint fUseNormalLocation = glGetUniformLocationARB(multi_blt_program->Program, "fUseNormal");
GLint clrModLocation = glGetUniformLocationARB(multi_blt_program->Program, "clrMod");
GLint overlayClrModLocation = glGetUniformLocationARB(multi_blt_program->Program, "overlayClrMod");
GLint ambientBrightnessLocation = glGetUniformLocationARB(multi_blt_program->Program, "ambientBrightness");
GLint lightLocation = glGetUniformLocationARB(multi_blt_program->Program, "Light");
GLint ambientLocation = glGetUniformLocationARB(multi_blt_program->Program, "Ambient");
GLint textureLocation = glGetUniformLocationARB(multi_blt_program->Program, "Texture");
@ -383,6 +384,8 @@ void CStdGL::SetupMultiBlt(const C4BltTransform* pTransform, GLuint baseTex, GLu
glTranslatef(-iX, -iY, 0.0f);
glMatrixMode(GL_MODELVIEW);
glUniform1fARB(ambientBrightnessLocation, pFoW->getFoW()->Ambient.GetBrightness());
}
if(overlayTex != 0)
@ -624,6 +627,7 @@ bool CStdGL::RestoreDeviceObjects()
"uniform int fUseNormal;"
"uniform vec4 clrMod;"
"uniform vec4 overlayClrMod;"
"uniform float ambientBrightness;"
"uniform sampler2D Texture;"
"uniform sampler2D Overlay;"
"uniform sampler2D Light;"
@ -662,8 +666,8 @@ bool CStdGL::RestoreDeviceObjects()
" {"
" normalDir = vec3(0.0, 0.0, 1.0);"
" }"
" 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));"
" float ambient = texture2D(Ambient, (gl_TextureMatrix[3] * gl_FragCoord).xy).r * ambientBrightness;"
" lightClr = ambient * lightClr + (1.0 - min(ambient, 1.0)) * vec3(1.0, 1.0, 1.0) * lightIntensity * (0.25 + 0.75 * dot(normalDir, lightDir));"
" }"
// Final output, depending on blit mode
" if(fMod2 != 0)"

View File

@ -148,6 +148,7 @@ namespace
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;
params.AddParameter("oc_AmbientBrightness", StdMeshMaterialShaderParameter::AUTO).GetAuto() = StdMeshMaterialShaderParameter::AUTO_OC_AMBIENT_BRIGHTNESS;
return FormatString(
"varying vec3 normal;" // linearly interpolated -- not necessarily normalized
@ -159,6 +160,7 @@ namespace
"uniform int oc_UseLight;"
"uniform sampler2D oc_Light;"
"uniform sampler2D oc_Ambient;"
"uniform float oc_AmbientBrightness;"
"void main()"
"{"
" vec4 lightClr;"
@ -169,11 +171,11 @@ namespace
" vec4 lightPx = texture2D(oc_Light, (gl_TextureMatrix[%d] * gl_FragCoord).xy);"
" 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;"
" float ambient = texture2D(oc_Ambient, (gl_TextureMatrix[%d] * gl_FragCoord).xy).r * oc_AmbientBrightness;"
// 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
" lightClr = vec4(ambient * (gl_FrontMaterial.emission.rgb + gl_FrontMaterial.diffuse.rgb * (0.25 + 0.75 * max(dot(normalDir, vec3(0.0, 0.0, 1.0)), 0.0))) + (1.0 - ambient) * lightIntensity * (gl_FrontMaterial.emission.rgb + gl_FrontMaterial.diffuse.rgb * (0.25 + 0.75 * max(dot(normalDir, lightDir), 0.0))), gl_FrontMaterial.emission.a + gl_FrontMaterial.diffuse.a);"
" lightClr = vec4(ambient * (gl_FrontMaterial.emission.rgb + gl_FrontMaterial.diffuse.rgb * (0.25 + 0.75 * max(dot(normalDir, vec3(0.0, 0.0, 1.0)), 0.0))) + (1.0 - min(ambient, 1.0)) * lightIntensity * (gl_FrontMaterial.emission.rgb + gl_FrontMaterial.diffuse.rgb * (0.25 + 0.75 * max(dot(normalDir, lightDir), 0.0))), gl_FrontMaterial.emission.a + gl_FrontMaterial.diffuse.a);"
" }"
" else"
" {"
@ -578,6 +580,11 @@ namespace
parameter.SetType(StdMeshMaterialShaderParameter::INT);
parameter.GetInt() = texIndex;
return true;
case StdMeshMaterialShaderParameter::AUTO_OC_AMBIENT_BRIGHTNESS:
if(!pFoW) return false;
parameter.SetType(StdMeshMaterialShaderParameter::FLOAT);
parameter.GetFloat() = pFoW->getFoW()->Ambient.GetBrightness();
return true;
default:
assert(false);
return false;

View File

@ -124,6 +124,10 @@ public:
if (pShader->HaveUniform(iUniform))
glUniform1iARB(pShader->GetUniform(iUniform), iX);
}
void SetUniform1f(int iUniform, float gX) const {
if (pShader->HaveUniform(iUniform))
glUniform1fARB(pShader->GetUniform(iUniform), gX);
}
void SetUniform2f(int iUniform, float gX, float gY) const {
if (pShader->HaveUniform(iUniform))
glUniform2fARB(pShader->GetUniform(iUniform), gX, gY);

View File

@ -34,6 +34,7 @@ const int C4LR_BiasDistanceY = 8;
// Name used for the seperator texture
const char *const SEPERATOR_TEXTURE = "--SEP--";
C4LandscapeRenderGL::C4LandscapeRenderGL()
{
ZeroMem(Surfaces, sizeof(Surfaces));
@ -523,18 +524,19 @@ bool C4LandscapeRenderGL::LoadShaders(C4GroupSet *pGroups)
// Make uniform name map
ZeroMem(UniformNames, sizeof(UniformNames));
UniformNames[C4LRU_LandscapeTex] = "landscapeTex";
UniformNames[C4LRU_ScalerTex] = "scalerTex";
UniformNames[C4LRU_MaterialTex] = "materialTex";
UniformNames[C4LRU_LightTex] = "lightTex";
UniformNames[C4LRU_AmbientTex] = "ambientTex";
UniformNames[C4LRU_Resolution] = "resolution";
UniformNames[C4LRU_Center] = "center";
UniformNames[C4LRU_MatMap] = "matMap";
UniformNames[C4LRU_MatMapTex] = "matMapTex";
UniformNames[C4LRU_MaterialDepth]= "materialDepth";
UniformNames[C4LRU_MaterialSize] = "materialSize";
UniformNames[C4LRU_AmbientScale] = "ambientScale";
UniformNames[C4LRU_LandscapeTex] = "landscapeTex";
UniformNames[C4LRU_ScalerTex] = "scalerTex";
UniformNames[C4LRU_MaterialTex] = "materialTex";
UniformNames[C4LRU_LightTex] = "lightTex";
UniformNames[C4LRU_AmbientTex] = "ambientTex";
UniformNames[C4LRU_Resolution] = "resolution";
UniformNames[C4LRU_Center] = "center";
UniformNames[C4LRU_MatMap] = "matMap";
UniformNames[C4LRU_MatMapTex] = "matMapTex";
UniformNames[C4LRU_MaterialDepth] = "materialDepth";
UniformNames[C4LRU_MaterialSize] = "materialSize";
UniformNames[C4LRU_AmbientBrightness] = "ambientBrightness";
UniformNames[C4LRU_AmbientScale] = "ambientScale";
// Initialise!
if (!Shader.Init("landscape", UniformNames)) {
@ -836,13 +838,13 @@ void C4LandscapeRenderGL::Draw(const C4TargetFacet &cgo, const C4FoWRegion &Ligh
float(iMaterialWidth) / ::Game.C4S.Landscape.MaterialZoom,
float(iMaterialHeight) / ::Game.C4S.Landscape.MaterialZoom);
// 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...
ShaderCall.SetUniform2f(C4LRU_AmbientScale,
static_cast<float>(Surfaces[0]->Wdt) / iWidth,
static_cast<float>(Surfaces[0]->Hgt) / iHeight);
ShaderCall.SetUniform1f(C4LRU_AmbientBrightness, Light.getFoW()->Ambient.GetBrightness());
// Start binding textures
if(Shader.HaveUniform(C4LRU_LandscapeTex))

View File

@ -33,6 +33,7 @@ enum C4LR_Uniforms
C4LRU_MatMapTex,
C4LRU_MaterialDepth,
C4LRU_MaterialSize,
C4LRU_AmbientBrightness,
C4LRU_AmbientScale,
C4LRU_Count

View File

@ -70,7 +70,8 @@ struct IFTZoom {
C4FoWAmbient::C4FoWAmbient()
: Tex(0), Resolution(0.), Radius(0.), FullCoverage(0.),
SizeX(0), SizeY(0), LandscapeX(0), LandscapeY(0)
SizeX(0), SizeY(0), LandscapeX(0), LandscapeY(0),
Brightness(1.)
{
}
@ -86,6 +87,7 @@ void C4FoWAmbient::Clear()
Resolution = Radius = FullCoverage = 0.;
SizeX = SizeY = 0;
LandscapeX = LandscapeY = 0;
Brightness = 1.;
}
void C4FoWAmbient::CreateFromLandscape(const C4Landscape& landscape, double resolution, double radius, double full_coverage)

View File

@ -27,10 +27,14 @@ private:
// Size of ambient map
unsigned int SizeX;
unsigned int SizeY;
// Brightness (not premultiplied)
double Brightness;
public:
void Clear();
void SetBrightness(double brightness) { Brightness = brightness; }
double GetBrightness() const { return Brightness; }
// 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

View File

@ -62,6 +62,7 @@ namespace
{ "oc_use_light", StdMeshMaterialShaderParameter::AUTO_OC_USE_LIGHT },
{ "oc_light", StdMeshMaterialShaderParameter::AUTO_OC_LIGHT },
{ "oc_ambient", StdMeshMaterialShaderParameter::AUTO_OC_AMBIENT },
{ "oc_ambient_brightness", StdMeshMaterialShaderParameter::AUTO_OC_AMBIENT_BRIGHTNESS },
{ NULL, static_cast<StdMeshMaterialShaderParameter::Auto>(0) }
};

View File

@ -60,7 +60,8 @@ public:
AUTO_OC_MOD2,
AUTO_OC_USE_LIGHT,
AUTO_OC_LIGHT,
AUTO_OC_AMBIENT
AUTO_OC_AMBIENT,
AUTO_OC_AMBIENT_BRIGHTNESS
// TODO: Other ogre auto values
};