Index: ps/trunk/binaries/data/mods/public/gui/session/developer_overlay/DeveloperOverlayControlDropDowns.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/developer_overlay/DeveloperOverlayControlDropDowns.js (revision 25995)
+++ ps/trunk/binaries/data/mods/public/gui/session/developer_overlay/DeveloperOverlayControlDropDowns.js (revision 25996)
@@ -1,37 +1,39 @@
/**
* This class stores the handlers for the individual dropdowns available in the developer overlay.
* Such a class must have onSelectionChange function.
* If the class has a selected property, then that will be called every simulation update to
* synchronize the state of the dropdown (only if the developer overaly is opened).
*/
class DeveloperOverlayControlDrowDowns
{
}
DeveloperOverlayControlDrowDowns.prototype.RenderDebugMode = class
{
constructor()
{
this.selectedIndex = this.values().map(e => e.value).indexOf(
Engine.Renderer_GetRenderDebugMode());
}
values()
{
return [
{ "value": "RENDER_DEBUG_MODE_NONE", "label": translate("Render Debug Mode Disabled") },
- { "value": "RENDER_DEBUG_MODE_AO", "label": translate("Render Debug Mode AO") }
+ { "value": "RENDER_DEBUG_MODE_AO", "label": translate("Render Debug Mode AO") },
+ { "value": "RENDER_DEBUG_MODE_ALPHA", "label": translate("Render Debug Mode Alpha") },
+ { "value": "RENDER_DEBUG_MODE_CUSTOM", "label": translate("Render Debug Mode Custom") }
];
}
onSelectionChange(selectedIndex)
{
this.selectedIndex = selectedIndex;
Engine.Renderer_SetRenderDebugMode(this.values()[this.selectedIndex].value);
}
selected()
{
return this.selectedIndex;
}
};
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/common/debug_fragment.h
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/common/debug_fragment.h (revision 25995)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/common/debug_fragment.h (revision 25996)
@@ -1,20 +1,26 @@
#ifndef INCLUDED_DEBUG_FRAGMENT
#define INCLUDED_DEBUG_FRAGMENT
#define RENDER_DEBUG_MODE_NONE 0
#define RENDER_DEBUG_MODE_AO 1
+#define RENDER_DEBUG_MODE_ALPHA 2
+#define RENDER_DEBUG_MODE_CUSTOM 3
#ifndef RENDER_DEBUG_MODE
#define RENDER_DEBUG_MODE RENDER_DEBUG_MODE_NONE
#endif
-vec3 applyDebugColor(vec3 color, float ao)
+vec3 applyDebugColor(vec3 color, float ao, float alpha, float custom)
{
#if RENDER_DEBUG_MODE == RENDER_DEBUG_MODE_AO
return vec3(ao);
+#elif RENDER_DEBUG_MODE == RENDER_DEBUG_MODE_ALPHA
+ return vec3(alpha);
+#elif RENDER_DEBUG_MODE == RENDER_DEBUG_MODE_CUSTOM
+ return vec3(custom);
#else
return color;
#endif
}
#endif // INCLUDED_DEBUG_FRAGMENT
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/model_common.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/model_common.fs (revision 25995)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/model_common.fs (revision 25996)
@@ -1,180 +1,180 @@
#version 120
#include "common/debug_fragment.h"
#include "common/fog.h"
#include "common/los_fragment.h"
#include "common/shadows_fragment.h"
uniform sampler2D baseTex;
uniform sampler2D aoTex;
uniform sampler2D normTex;
uniform sampler2D specTex;
#if USE_OBJECTCOLOR
uniform vec3 objectColor;
#else
#if USE_PLAYERCOLOR
uniform vec3 playerColor;
#endif
#endif
uniform vec3 shadingColor;
uniform vec3 ambient;
uniform vec3 sunColor;
uniform vec3 sunDir;
varying vec4 v_lighting;
varying vec2 v_tex;
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO
varying vec2 v_tex2;
#endif
#if USE_SPECULAR
uniform float specularPower;
uniform vec3 specularColor;
#endif
#if USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX || USE_AO
uniform vec4 effectSettings;
#endif
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX
varying vec4 v_normal;
#if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_NORMAL_MAP || USE_PARALLAX)
varying vec4 v_tangent;
//varying vec3 v_bitangent;
#endif
#if USE_SPECULAR || USE_SPECULAR_MAP
varying vec3 v_half;
#endif
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_PARALLAX
varying vec3 v_eyeVec;
#endif
#endif
void main()
{
vec2 coord = v_tex;
#if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_PARALLAX || USE_NORMAL_MAP)
vec3 bitangent = vec3(v_normal.w, v_tangent.w, v_lighting.w);
mat3 tbn = mat3(v_tangent.xyz, bitangent, v_normal.xyz);
#endif
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_PARALLAX
{
float h = texture2D(normTex, coord).a;
vec3 eyeDir = normalize(v_eyeVec * tbn);
float dist = length(v_eyeVec);
vec2 move;
float height = 1.0;
float scale = effectSettings.z;
int iter = int(min(20.0, 25.0 - dist/10.0));
if (iter > 0)
{
float s = 1.0/float(iter);
float t = s;
move = vec2(-eyeDir.x, eyeDir.y) * scale / (eyeDir.z * float(iter));
vec2 nil = vec2(0.0);
for (int i = 0; i < iter; ++i) {
height -= t;
t = (h < height) ? s : 0.0;
vec2 temp = (h < height) ? move : nil;
coord += temp;
h = texture2D(normTex, coord).a;
}
// Move back to where we collided with the surface.
// This assumes the surface is linear between the sample point before we
// intersect the surface and after we intersect the surface
float hp = texture2D(normTex, coord - move).a;
coord -= move * ((h - height) / (s + h - hp));
}
}
#endif
vec4 tex = texture2D(baseTex, coord);
// Alpha-test as early as possible
#ifdef REQUIRE_ALPHA_GEQUAL
if (tex.a < REQUIRE_ALPHA_GEQUAL)
discard;
#endif
#if USE_TRANSPARENT
- gl_FragColor.a = tex.a;
+ float alpha = tex.a;
#else
- gl_FragColor.a = 1.0;
+ float alpha = 1.0;
#endif
vec3 texdiffuse = tex.rgb;
// Apply-coloring based on texture alpha
#if USE_OBJECTCOLOR
texdiffuse *= mix(objectColor, vec3(1.0, 1.0, 1.0), tex.a);
#else
#if USE_PLAYERCOLOR
texdiffuse *= mix(playerColor, vec3(1.0, 1.0, 1.0), tex.a);
#endif
#endif
#if USE_SPECULAR || USE_SPECULAR_MAP || USE_NORMAL_MAP
vec3 normal = v_normal.xyz;
#endif
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_NORMAL_MAP
vec3 ntex = texture2D(normTex, coord).rgb * 2.0 - 1.0;
ntex.y = -ntex.y;
normal = normalize(tbn * ntex);
vec3 bumplight = max(dot(-sunDir, normal), 0.0) * sunColor;
vec3 sundiffuse = (bumplight - v_lighting.rgb) * effectSettings.x + v_lighting.rgb;
#else
vec3 sundiffuse = v_lighting.rgb;
#endif
vec4 specular = vec4(0.0);
#if USE_SPECULAR || USE_SPECULAR_MAP
vec3 specCol;
float specPow;
#if USE_SPECULAR_MAP
vec4 s = texture2D(specTex, coord);
specCol = s.rgb;
specular.a = s.a;
specPow = effectSettings.y;
#else
specCol = specularColor;
specPow = specularPower;
#endif
specular.rgb = sunColor * specCol * pow(max(0.0, dot(normalize(normal), v_half)), specPow);
#endif
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO
float ao = texture2D(aoTex, v_tex2).r;
ao = mix(1.0, ao * 2.0, effectSettings.w);
#else
float ao = 1.0;
#endif
vec3 ambientColor = texdiffuse * ambient * ao;
vec3 color = (texdiffuse * sundiffuse + specular.rgb) * getShadow() + ambientColor;
#if USE_SPECULAR_MAP && USE_SELF_LIGHT
color = mix(texdiffuse, color, specular.a);
#endif
color = applyFog(color);
color *= getLOS();
color *= shadingColor;
- color = applyDebugColor(color, ao);
+ color = applyDebugColor(color, ao, alpha, 0.0);
- gl_FragColor.rgb = color;
+ gl_FragColor = vec4(color, alpha);
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/model_water.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/model_water.fs (revision 25995)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/model_water.fs (revision 25996)
@@ -1,102 +1,102 @@
#version 120
#include "common/debug_fragment.h"
#include "common/los_fragment.h"
#include "common/shadows_fragment.h"
uniform sampler2D baseTex;
uniform sampler2D aoTex;
uniform sampler2D normTex;
uniform sampler2D specTex;
uniform sampler2D waterTex;
uniform samplerCube skyCube;
#if USE_OBJECTCOLOR
uniform vec3 objectColor;
#else
#if USE_PLAYERCOLOR
uniform vec3 playerColor;
#endif
#endif
uniform vec3 shadingColor;
uniform vec3 ambient;
uniform vec3 sunColor;
uniform vec3 sunDir;
uniform vec3 cameraPos;
uniform float specularStrength;
uniform float waviness;
uniform vec3 waterTint;
uniform float murkiness;
uniform vec3 reflectionTint;
uniform float reflectionTintStrength;
float waterDepth = 4.0;
float fullDepth = 5.0; // Depth at which to use full murkiness (shallower water will be clearer)
varying vec4 worldPos;
varying vec4 v_tex;
void main()
{
vec3 n, l, h, v; // Normal, light vector, half-vector and view vector (vector to eye)
float ndotl, ndoth, ndotv;
float fresnel;
float t; // Temporary variable
vec2 reflCoords, refrCoords;
vec3 reflColor, refrColor, specular;
//vec4 wtex = textureGrad(waterTex, vec3(fract(v_tex.xy), v_tex.z), dFdx(v_tex.xy), dFdy(v_tex.xy));
vec4 wtex = texture2D(waterTex, fract(v_tex.xy));
n = normalize(wtex.xzy - vec3(0.5, 0.5, 0.5));
l = -sunDir;
v = normalize(cameraPos - worldPos.xyz);
h = normalize(l + v);
ndotl = dot(n, l);
ndoth = dot(n, h);
ndotv = dot(n, v);
fresnel = pow(1.0 - ndotv, 0.8); // A rather random Fresnel approximation
//refrCoords = (0.5*gl_TexCoord[2].xy - 0.8*waviness*n.xz) / gl_TexCoord[2].w + 0.5; // Unbias texture coords
//reflCoords = (0.5*gl_TexCoord[1].xy + waviness*n.xz) / gl_TexCoord[1].w + 0.5; // Unbias texture coords
//vec3 dir = normalize(v + vec3(waviness*n.x, 0.0, waviness*n.z));
vec3 eye = reflect(v, n);
vec3 tex = textureCube(skyCube, eye).rgb;
reflColor = mix(tex, sunColor * reflectionTint,
reflectionTintStrength);
//waterDepth = 4.0 + 2.0 * dot(abs(v_tex.zw - 0.5), vec2(0.5));
waterDepth = 4.0;
//refrColor = (0.5 + 0.5*ndotl) * mix(texture2D(refractionMap, refrCoords).rgb, sunColor * tint,
refrColor = (0.5 + 0.5*ndotl) * mix(vec3(0.3), sunColor * waterTint,
murkiness * clamp(waterDepth / fullDepth, 0.0, 1.0)); // Murkiness and tint at this pixel (tweaked based on lighting and depth)
specular = pow(max(0.0, ndoth), 150.0f) * sunColor * specularStrength;
#if USE_SHADOW
float shadow = getShadowOnLandscape();
float fresShadow = mix(fresnel, fresnel*shadow, dot(sunColor, vec3(0.16666)));
#else
float fresShadow = fresnel;
#endif
vec3 color = mix(refrColor + 0.3*specular, reflColor + specular, fresShadow);
color *= getLOS();
- gl_FragColor.rgb = applyDebugColor(color, 1.0);
-
// Make alpha vary based on both depth (so it blends with the shore) and view angle (make it
// become opaque faster at lower view angles so we can't look "underneath" the water plane)
t = 18.0 * max(0.0, 0.7 - v.y);
- gl_FragColor.a = 0.15 * waterDepth * (1.2 + t + fresnel);
+ float alpha = 0.15 * waterDepth * (1.2 + t + fresnel);
+
+ gl_FragColor = vec4(applyDebugColor(color, 1.0, alpha, 0.0), alpha);
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/model_waterfall.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/model_waterfall.fs (revision 25995)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/model_waterfall.fs (revision 25996)
@@ -1,43 +1,42 @@
#version 120
#include "common/debug_fragment.h"
#include "common/los_fragment.h"
#include "common/shadows_fragment.h"
uniform sampler2D baseTex;
uniform vec3 shadingColor;
uniform vec3 ambient;
uniform vec3 sunColor;
uniform vec3 sunDir;
uniform vec3 cameraPos;
uniform float specularPower;
uniform vec3 specularColor;
varying vec4 v_tex;
varying vec3 v_half;
varying vec3 v_normal;
varying float v_transp;
varying vec3 v_lighting;
void main()
{
//vec4 texdiffuse = textureGrad(baseTex, vec3(fract(v_tex.xy), v_tex.z), dFdx(v_tex.xy), dFdy(v_tex.xy));
vec4 texdiffuse = texture2D(baseTex, fract(v_tex.xy));
if (texdiffuse.a < 0.25)
discard;
texdiffuse.a *= v_transp;
vec3 specular = sunColor * specularColor * pow(max(0.0, dot(normalize(v_normal), v_half)), specularPower);
vec3 color = (texdiffuse.rgb * v_lighting + specular) * getShadowOnLandscape();
color += texdiffuse.rgb * ambient;
color *= getLOS();
- gl_FragColor.rgb = applyDebugColor(color, 1.0);
- gl_FragColor.a = texdiffuse.a;
+ gl_FragColor = vec4(applyDebugColor(color, 1.0, texdiffuse.a, 0.0), texdiffuse.a);
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/overlayline.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/overlayline.fs (revision 25995)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/overlayline.fs (revision 25996)
@@ -1,34 +1,34 @@
#version 120
#include "common/debug_fragment.h"
#include "common/los_fragment.h"
uniform sampler2D baseTex;
uniform sampler2D maskTex;
#if USE_OBJECTCOLOR
uniform vec4 objectColor;
#else
varying vec4 v_color;
#endif
varying vec2 v_tex;
void main()
{
#if USE_OBJECTCOLOR
vec3 color = objectColor.rgb;
float alpha = objectColor.a;
#else
vec3 color = v_color.rgb;
float alpha = v_color.a;
#endif
vec4 base = texture2D(baseTex, v_tex);
vec4 mask = texture2D(maskTex, v_tex);
color = mix(base.rgb, color, mask.r);
color *= getLOS();
- gl_FragColor = vec4(applyDebugColor(color, 1.0), alpha * base.a);
+ gl_FragColor = vec4(applyDebugColor(color, 1.0, alpha * base.a, 0.0), alpha * base.a);
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/terrain_common.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/terrain_common.fs (revision 25995)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/terrain_common.fs (revision 25996)
@@ -1,192 +1,194 @@
#version 120
#include "common/debug_fragment.h"
#include "common/fog.h"
#include "common/los_fragment.h"
#include "common/shadows_fragment.h"
uniform sampler2D baseTex;
uniform sampler2D blendTex;
uniform sampler2D normTex;
uniform sampler2D specTex;
uniform vec3 shadingColor;
uniform vec3 ambient;
uniform vec3 sunColor;
uniform vec3 sunDir;
uniform vec2 textureTransform;
varying vec3 v_lighting;
varying vec2 v_blend;
#if USE_TRIPLANAR
varying vec3 v_tex;
#else
varying vec2 v_tex;
#endif
#if USE_SPECULAR
uniform float specularPower;
uniform vec3 specularColor;
#endif
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_AO
uniform vec4 effectSettings;
#endif
varying vec3 v_normal;
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP
#if USE_NORMAL_MAP
varying vec4 v_tangent;
varying vec3 v_bitangent;
#endif
#if USE_SPECULAR || USE_SPECULAR_MAP
varying vec3 v_half;
#endif
#endif
#if USE_TRIPLANAR
vec4 triplanar(sampler2D sampler, vec3 wpos)
{
float tighten = 0.4679;
vec3 blending = abs(normalize(v_normal)) - tighten;
blending = max(blending, 0.0);
blending /= vec3(blending.x + blending.y + blending.z);
vec3 signedBlending = sign(v_normal) * blending;
vec3 coords = wpos;
coords.xyz /= 32.0; // Ugh.
vec4 col1 = texture2D(sampler, coords.yz);
vec4 col2 = texture2D(sampler, coords.zx);
vec4 col3 = texture2D(sampler, coords.yx);
vec4 colBlended = col1 * blending.x + col2 * blending.y + col3 * blending.z;
return colBlended;
}
vec4 triplanarNormals(sampler2D sampler, vec3 wpos)
{
float tighten = 0.4679;
vec3 blending = abs(normalize(v_normal)) - tighten;
blending = max(blending, 0.0);
blending /= vec3(blending.x + blending.y + blending.z);
vec3 signedBlending = sign(v_normal) * blending;
vec3 coords = wpos;
coords.xyz /= 32.0; // Ugh.
vec4 col1 = texture2D(sampler, coords.yz).xyzw;
col1.y = 1.0 - col1.y;
vec4 col2 = texture2D(sampler, coords.zx).yxzw;
col2.y = 1.0 - col2.y;
vec4 col3 = texture2D(sampler, coords.yx).yxzw;
col3.y = 1.0 - col3.y;
vec4 colBlended = col1 * blending.x + col2 * blending.y + col3 * blending.z;
return colBlended;
}
#endif
void main()
{
+ float alpha = 0.0;
+
#if BLEND
// Use alpha from blend texture
- gl_FragColor.a = 1.0 - texture2D(blendTex, v_blend).a;
+ alpha = 1.0 - texture2D(blendTex, v_blend).a;
#if USE_GRASS
- if (gl_FragColor.a < LAYER / 10.0)
+ if (alpha < LAYER / 10.0)
discard;
#endif
#else
- gl_FragColor.a = 1.0;
+ alpha = 1.0;
#endif
#if USE_TRIPLANAR
vec4 tex = triplanar(baseTex, v_tex);
#else
vec4 tex = texture2D(baseTex, v_tex.xy);
#endif
#if USE_GRASS && LAYER
if (tex.a < 0.05)
discard;
#endif
#if DECAL
// Use alpha from main texture
- gl_FragColor.a = tex.a;
+ alpha = tex.a;
#endif
vec3 texdiffuse = tex.rgb;
#if USE_SPECULAR || USE_SPECULAR_MAP || USE_NORMAL_MAP
vec3 normal = v_normal;
#endif
#if USE_NORMAL_MAP
float sign = v_tangent.w;
mat3 tbn = mat3(v_tangent.xyz, v_bitangent * -sign, v_normal);
#if USE_TRIPLANAR
vec3 ntex = triplanarNormals(normTex, v_tex).rgb * 2.0 - 1.0;
#else
vec3 ntex = texture2D(normTex, v_tex).rgb * 2.0 - 1.0;
#endif
normal = normalize(tbn * ntex);
vec3 bumplight = max(dot(-sunDir, normal), 0.0) * sunColor;
vec3 sundiffuse = (bumplight - v_lighting.rgb) * effectSettings.x + v_lighting.rgb;
#else
vec3 sundiffuse = v_lighting;
#endif
vec4 specular = vec4(0.0);
#if USE_SPECULAR || USE_SPECULAR_MAP
vec3 specCol;
float specPow;
#if USE_SPECULAR_MAP
#if USE_TRIPLANAR
vec4 s = triplanar(specTex, v_tex);
#else
vec4 s = texture2D(specTex, v_tex);
#endif
specCol = s.rgb;
specular.a = s.a;
specPow = effectSettings.y;
#else
specCol = specularColor;
specPow = specularPower;
#endif
specular.rgb = sunColor * specCol * pow(max(0.0, dot(normalize(normal), v_half)), specPow);
#endif
vec3 color = (texdiffuse * sundiffuse + specular.rgb) * getShadowOnLandscape() + texdiffuse * ambient;
#if USE_SPECULAR_MAP && USE_SELF_LIGHT
color = mix(texdiffuse, color, specular.a);
#endif
color = applyFog(color);
color *= getLOS();
#if DECAL
color *= shadingColor;
#endif
- gl_FragColor.rgb = applyDebugColor(color, 1.0);
-
#if USE_GRASS
- gl_FragColor.a = tex.a;
+ alpha = tex.a;
#endif
+
+ gl_FragColor = vec4(applyDebugColor(color, 1.0, 1.0, 0.0), alpha);
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/water_high.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/water_high.fs (revision 25995)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/water_high.fs (revision 25996)
@@ -1,309 +1,310 @@
#version 110
+#include "common/debug_fragment.h"
#include "common/fog.h"
#include "common/los_fragment.h"
#include "common/shadows_fragment.h"
// Environment settings
uniform vec3 ambient;
uniform vec3 sunDir;
uniform vec3 sunColor;
uniform mat4 skyBoxRot;
uniform float waviness; // "Wildness" of the reflections and refractions; choose based on texture
uniform vec3 color; // color of the water
uniform vec3 tint; // Tint for refraction (used to simulate particles in water)
uniform float murkiness; // Amount of tint to blend in with the refracted color
uniform float windAngle;
varying vec2 WindCosSin;
uniform vec2 screenSize;
varying float moddedTime;
varying vec3 worldPos;
varying float waterDepth;
varying vec2 waterInfo;
varying vec3 v_eyeVec;
varying vec4 normalCoords;
#if USE_REFLECTION
varying vec3 reflectionCoords;
#endif
#if USE_REFRACTION
varying vec3 refractionCoords;
#endif
varying float fwaviness;
uniform samplerCube skyCube;
uniform sampler2D normalMap;
uniform sampler2D normalMap2;
#if USE_FANCY_EFFECTS
uniform sampler2D waterEffectsTex;
#endif
uniform vec4 waveParams1; // wavyEffect, BaseScale, Flattenism, Basebump
uniform vec4 waveParams2; // Smallintensity, Smallbase, Bigmovement, Smallmovement
#if USE_REFLECTION
uniform sampler2D reflectionMap;
#endif
#if USE_REFRACTION
uniform sampler2D refractionMap;
#if USE_REAL_DEPTH
uniform sampler2D depthTex;
uniform mat4 projInvTransform;
uniform mat4 viewInvTransform;
#endif
#endif
vec3 getNormal(vec4 fancyeffects)
{
float wavyEffect = waveParams1.r;
float baseScale = waveParams1.g;
float flattenism = waveParams1.b;
float baseBump = waveParams1.a;
float BigMovement = waveParams2.b;
// This method uses 60 animated water frames. We're blending between each two frames
// Scale the normal textures by waviness so that big waviness means bigger waves.
vec3 ww1 = texture2D(normalMap, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).xzy;
vec3 ww2 = texture2D(normalMap2, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).xzy;
vec3 wwInterp = mix(ww1, ww2, moddedTime) - vec3(0.5, 0.0, 0.5);
ww1.x = wwInterp.x * WindCosSin.x - wwInterp.z * WindCosSin.y;
ww1.z = wwInterp.x * WindCosSin.y + wwInterp.z * WindCosSin.x;
ww1.y = wwInterp.y;
// Flatten them based on waviness.
vec3 normal = normalize(mix(vec3(0.0, 1.0, 0.0), ww1, clamp(baseBump + fwaviness / flattenism, 0.0, 1.0)));
#if USE_FANCY_EFFECTS
normal = mix(vec3(0.0, 1.0, 0.0), normal, 0.5 + waterInfo.r / 2.0);
normal.xz = mix(normal.xz, fancyeffects.rb, fancyeffects.a / 2.0);
#else
normal = mix(vec3(0.0, 1.0, 0.0), normal, 0.5 + waterInfo.r / 2.0);
#endif
return vec3(-normal.x, normal.y, -normal.z);
}
vec3 getSpecular(vec3 normal, vec3 eyeVec)
{
// Specular lighting vectors
vec3 specularVector = reflect(sunDir, normal);
// pow is undefined for null or negative values, except on intel it seems.
float specularIntensity = pow(max(dot(specularVector, eyeVec), 0.0), 100.0);
// Workaround to fix too flattened water.
specularIntensity = smoothstep(0.6, 1.0, specularIntensity) * 1.2;
return clamp(specularIntensity * sunColor, 0.0, 1.0);
}
vec4 getReflection(vec3 normal, vec3 eyeVec)
{
// Reflections
// 3 level of settings:
// -If a player has refraction and reflection disabled, we return a gradient of blue based on the Y component.
// -If a player has refraction OR reflection, we return a reflection of the actual skybox used.
// -If a player has reflection enabled, we also return a reflection of actual entities where applicable.
// reflMod reduces the intensity of reflections somewhat since they kind of wash refractions out otherwise.
float reflMod = 0.75;
vec3 eye = reflect(eyeVec, normal);
#if USE_REFLECTION
float refVY = clamp(eyeVec.y * 2.0, 0.05, 1.0);
// Distort the reflection coords based on waves.
vec2 reflCoords = (0.5 * reflectionCoords.xy - 15.0 * normal.zx / refVY) / reflectionCoords.z + 0.5;
vec4 refTex = texture2D(reflectionMap, reflCoords);
vec3 reflColor = refTex.rgb;
// Interpolate between the sky color and nearby objects.
// Only do this when alpha is rather low, or transparent leaves show up as extremely white.
if (refTex.a < 0.4)
reflColor = mix(textureCube(skyCube, (vec4(eye, 0.0) * skyBoxRot).xyz).rgb, refTex.rgb, refTex.a);
// Let actual objects be reflected fully.
reflMod = max(refTex.a, 0.75);
#else
vec3 reflColor = textureCube(skyCube, (vec4(eye, 0.0) * skyBoxRot).xyz).rgb;
#endif
return vec4(reflColor, reflMod);
}
#if USE_REFRACTION && USE_REAL_DEPTH
vec3 getWorldPositionFromRefractionDepth(vec2 uv)
{
float depth = texture2D(depthTex, uv).x;
vec4 viewPosition = projInvTransform * (vec4((uv - vec2(0.5)) * 2.0, depth * 2.0 - 1.0, 1.0));
viewPosition /= viewPosition.w;
vec3 refrWorldPos = (viewInvTransform * viewPosition).xyz;
// Depth buffer precision errors can give heights above the water.
refrWorldPos.y = min(refrWorldPos.y, worldPos.y);
return refrWorldPos;
}
#endif
vec4 getRefraction(vec3 normal, vec3 eyeVec, float depthLimit)
{
#if USE_REFRACTION && USE_REAL_DEPTH
// Compute real depth at the target point.
vec2 coords = (0.5 * refractionCoords.xy) / refractionCoords.z + 0.5;
vec3 refrWorldPos = getWorldPositionFromRefractionDepth(coords);
// Set depth to the depth at the undistorted point.
float depth = distance(refrWorldPos, worldPos);
#else
// fake depth computation: take the value at the vertex, add some if we are looking at a more oblique angle.
float depth = waterDepth / (min(0.5, eyeVec.y) * 1.5 * min(0.5, eyeVec.y) * 2.0);
#endif
#if USE_REFRACTION
// for refraction we want to distort more as depth goes down.
// 1) compute a distortion based on depth at the pixel.
// 2) Re-sample the depth at the target point
// 3) Sample refraction texture
// distoFactor controls the amount of distortion relative to wave normals.
float distoFactor = 0.5 + clamp(depth / 2.0, 0.0, 7.0);
#if USE_REAL_DEPTH
// Distort the texture coords under where the water is to simulate refraction.
vec2 shiftedCoords = (0.5 * refractionCoords.xy - normal.xz * distoFactor) / refractionCoords.z + 0.5;
vec3 refrWorldPos2 = getWorldPositionFromRefractionDepth(shiftedCoords);
float newDepth = distance(refrWorldPos2, worldPos);
// try to correct for fish. In general they'd look weirder without this fix.
if (depth > newDepth + 3.0)
distoFactor /= 2.0; // this in general will not fall on the fish but still look distorted.
else
depth = newDepth;
#endif
#if USE_FANCY_EFFECTS
depth = max(depth, depthLimit);
if (waterDepth < 0.0)
depth = 0.0;
#endif
// Distort the texture coords under where the water is to simulate refraction.
vec2 refrCoords = (0.5 * refractionCoords.xy - normal.xz * distoFactor) / refractionCoords.z + 0.5;
vec3 refColor = texture2D(refractionMap, refrCoords).rgb;
// Note, the refraction map is cleared using (255, 0, 0), so pixels outside of the water plane are pure red.
// If we get a pure red fragment, use an undistorted/less distorted coord instead.
// blur the refraction map, distoring using normal so that it looks more random than it really is
// and thus looks much better.
float blur = (0.1 + clamp(normal.x, -0.1, 0.1)) / refractionCoords.z;
vec4 blurColor = vec4(refColor, 1.0);
vec4 tex = texture2D(refractionMap, refrCoords + vec2(blur + normal.x, blur + normal.z));
blurColor += vec4(tex.rgb * tex.a, tex.a);
tex = texture2D(refractionMap, refrCoords + vec2(-blur, blur + normal.z));
blurColor += vec4(tex.rgb * tex.a, tex.a);
tex = texture2D(refractionMap, refrCoords + vec2(-blur, -blur + normal.x));
blurColor += vec4(tex.rgb * tex.a, tex.a);
tex = texture2D(refractionMap, refrCoords + vec2(blur + normal.z, -blur));
blurColor += vec4(tex.rgb * tex.a, tex.a);
blurColor /= blurColor.a;
float blurFactor = (distoFactor / 7.0);
refColor = (refColor + blurColor.rgb * blurFactor) / (1.0 + blurFactor);
#else // !USE_REFRACTION
#if USE_FANCY_EFFECTS
depth = max(depth, depthLimit);
#endif
vec3 refColor = color;
#endif
// for refraction, we want to adjust the value by v.y slightly otherwise it gets too different between "from above" and "from the sides".
// And it looks weird (again, we are not used to seeing water from above).
float fixedVy = max(eyeVec.y, 0.01);
float murky = mix(200.0, 0.1, pow(murkiness, 0.25));
// Apply water tint and murk color.
float extFact = max(0.0, 1.0 - (depth * fixedVy / murky));
float ColextFact = max(0.0, 1.0 - (depth * fixedVy / murky));
vec3 colll = mix(refColor * tint, refColor, ColextFact);
vec3 refrColor = mix(color, colll, extFact);
float alpha = clamp(depth, 0.0, 1.0);
#if !USE_REFRACTION
alpha = (1.4 - extFact) * alpha;
#endif
return vec4(refrColor, alpha);
}
vec4 getFoam(vec4 fancyeffects, float shadow)
{
#if USE_FANCY_EFFECTS
float wavyEffect = waveParams1.r;
float baseScale = waveParams1.g;
float BigMovement = waveParams2.b;
vec3 foam1 = texture2D(normalMap, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).aaa;
vec3 foam2 = texture2D(normalMap2, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).aaa;
vec3 foam3 = texture2D(normalMap, normalCoords.st / 6.0 - normalCoords.zw * 0.02).aaa;
vec3 foam4 = texture2D(normalMap2, normalCoords.st / 6.0 - normalCoords.zw * 0.02).aaa;
vec3 foaminterp = mix(foam1, foam2, moddedTime);
foaminterp *= mix(foam3, foam4, moddedTime);
foam1.x = abs(foaminterp.x * WindCosSin.x) + abs(foaminterp.z * WindCosSin.y);
float alpha = (fancyeffects.g + pow(foam1.x * (3.0 + waviness), 2.6 - waviness / 5.5)) * 2.0;
return vec4(sunColor * shadow + ambient, clamp(alpha, 0.0, 1.0));
#else
return vec4(0.0);
#endif
}
void main()
{
#if USE_FANCY_EFFECTS
vec4 fancyeffects = texture2D(waterEffectsTex, gl_FragCoord.xy / screenSize);
#else
vec4 fancyeffects = vec4(0.0);
#endif
vec3 eyeVec = normalize(v_eyeVec);
vec3 normal = getNormal(fancyeffects);
vec4 refrColor = getRefraction(normal, eyeVec, fancyeffects.a);
vec4 reflColor = getReflection(normal, eyeVec);
// How perpendicular to the normal our view is. Used for fresnel.
float ndotv = clamp(dot(normal, eyeVec), 0.0, 1.0);
// Fresnel for "how much reflection vs how much refraction".
float fresnel = clamp(((pow(1.1 - ndotv, 2.0)) * 1.5), 0.1, 0.75); // Approximation. I'm using 1.1 and not 1.0 because it causes artifacts, see #1714
vec3 specular = getSpecular(normal, eyeVec);
#if USE_SHADOW
float shadow = getShadowOnLandscape();
fresnel = mix(fresnel, fresnel * shadow, 0.05 + murkiness * 0.2);
#else
float shadow = 1.0;
#endif
vec3 color = mix(refrColor.rgb, reflColor.rgb, fresnel * reflColor.a);
color += shadow * specular;
vec4 foam = getFoam(fancyeffects, shadow);
color = clamp(mix(color, foam.rgb, foam.a), 0.0, 1.0);
color = applyFog(color);
- gl_FragColor = vec4(color * getLOS(), refrColor.a);
+ gl_FragColor = vec4(applyDebugColor(color * getLOS(), 1.0, refrColor.a, 0.0), refrColor.a);
}
Index: ps/trunk/source/ps/CStrInternStatic.h
===================================================================
--- ps/trunk/source/ps/CStrInternStatic.h (revision 25995)
+++ ps/trunk/source/ps/CStrInternStatic.h (revision 25996)
@@ -1,185 +1,187 @@
/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
// This file defines global CStrIntern variables, to avoid the cost of
// constructing CStrInterns frequently at runtime.
//
// A line like
// X(foo)
// defines a variable str_foo with value "foo".
//
// A line like
// X2(foo_0, "foo[0]")
// defines a variable str_foo_0 with value "foo[0]".
// For direct inclusion, we presumably just want the extern definitions.
#ifndef X
#include "CStrIntern.h"
#define X(id) extern CStrIntern str_##id;
#define X2(id, str) extern CStrIntern str_##id;
#endif
X(0)
X(1)
X(2)
X(3)
X(4)
X(ALPHABLEND_PASS_BLEND)
X(ALPHABLEND_PASS_OPAQUE)
X(BLEND)
X(BLOOM_NOP)
X(BLOOM_PASS_H)
X(BLOOM_PASS_V)
X(DECAL)
X(DISABLE_RECEIVE_SHADOWS)
X(IGNORE_LOS)
X(MINIMAP_BASE)
X(MINIMAP_LINE)
X(MINIMAP_LOS)
X(MINIMAP_MASK)
X(MINIMAP_POINT)
X(MODE_SHADOWCAST)
X(MODE_SILHOUETTEDISPLAY)
X(MODE_SILHOUETTEOCCLUDER)
X(MODE_WIREFRAME)
X(RENDER_DEBUG_MODE)
X(RENDER_DEBUG_MODE_AO)
+X(RENDER_DEBUG_MODE_ALPHA)
+X(RENDER_DEBUG_MODE_CUSTOM)
X(RENDER_DEBUG_MODE_NONE)
X(SHADOWS_CASCADE_COUNT)
X(SYS_HAS_ARB)
X(SYS_HAS_GLSL)
X(SYS_PREFER_GLSL)
X(USE_FANCY_EFFECTS)
X(USE_FP_SHADOW)
X(USE_GPU_SKINNING)
X(USE_INSTANCING)
X(USE_NORMALS)
X(USE_OBJECTCOLOR)
X(USE_REAL_DEPTH)
X(USE_REFLECTION)
X(USE_REFRACTION)
X(USE_SHADOW)
X(USE_SHADOW_PCF)
X(USE_SHADOW_SAMPLER)
X(USE_FOG)
X(WATERTYPE_CLAP)
X(WATERTYPE_LAKE)
X2(_emptystring, "")
X(a_apexPosition)
X(a_otherPosition)
X(a_retreatPosition)
X(a_skinJoints)
X(a_skinWeights)
X(a_splashPosition)
X(a_tangent)
X(a_waterInfo)
X(ambient)
X(baseTex)
X(blendTex)
X(bloom)
X(blurTex2)
X(blurTex4)
X(blurTex8)
X(brightness)
X(cameraForward)
X(cameraPos)
X(canvas2d)
X(color)
X(colorAdd)
X(colorMul)
X(debug_line)
X(debug_overlay)
X(delta)
X(depthTex)
X(foamTex)
X(fogColor)
X(fogParams)
X(foreground_overlay)
X(grayscaleFactor)
X(hdr)
X(height)
X(instancingTransform)
X(losTex)
X(losTex1)
X(losTex2)
X(losTransform)
X(los_interp)
X(mapSize)
X(maskTex)
X(maskTextureTransform)
X(minimap)
X(modelViewMatrix)
X(murkiness)
X(normalMap)
X(normalMap2)
X(objectColor)
X(overlay_solid)
X(particle)
X(particle_solid)
X(playerColor)
X(pointSize)
X(projInvTransform)
X(qualityLevel)
X(reflectionMap)
X(reflectionMatrix)
X(refractionMap)
X(refractionMatrix)
X(renderedTex)
X(repeatScale)
X2(sans_10, "sans-10");
X(saturation)
X(screenSize)
X(shadingColor)
X(shadowDistance)
X(shadowDistances)
X2(shadowDistances_0, "shadowDistances[0]")
X(shadowScale)
X(shadowTex)
X(shadowTransform)
X(shadowTransforms)
X2(shadowTransforms_0, "shadowTransforms[0]")
X(sharpness)
X(skinBlendMatrices)
X2(skinBlendMatrices_0, "skinBlendMatrices[0]")
X(skyBoxRot)
X(skyCube)
X(sky_simple)
X(solid)
X(sunColor)
X(sunDir)
X(tex)
X(texSize)
X(textureTransform)
X(time)
X(tint)
X(transform)
X(translation)
X(viewInvTransform)
X(water_simple)
X(waterEffectsTex)
X(waterTex)
X(waveTex)
X(waviness)
X(waveParams1)
X(waveParams2)
X(width)
X(windAngle)
X(zFar)
X(zNear)
#undef X
#undef X2
Index: ps/trunk/source/renderer/RenderingOptions.cpp
===================================================================
--- ps/trunk/source/renderer/RenderingOptions.cpp (revision 25995)
+++ ps/trunk/source/renderer/RenderingOptions.cpp (revision 25996)
@@ -1,282 +1,290 @@
/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#include "precompiled.h"
#include "RenderingOptions.h"
#include "ps/CLogger.h"
#include "ps/ConfigDB.h"
#include "ps/CStr.h"
#include "ps/CStrInternStatic.h"
#include "renderer/Renderer.h"
#include "renderer/PostprocManager.h"
#include "renderer/ShadowMap.h"
CRenderingOptions g_RenderingOptions;
class CRenderingOptions::ConfigHooks
{
public:
std::vector::iterator begin() { return hooks.begin(); }
std::vector::iterator end() { return hooks.end(); }
template
void Setup(CStr8 name, T& variable)
{
hooks.emplace_back(g_ConfigDB.RegisterHookAndCall(name, [name, &variable]() { CFG_GET_VAL(name, variable); }));
}
void Setup(CStr8 name, std::function hook)
{
hooks.emplace_back(g_ConfigDB.RegisterHookAndCall(name, hook));
}
void clear() { hooks.clear(); }
private:
std::vector hooks;
};
RenderPath RenderPathEnum::FromString(const CStr8& name)
{
if (name == "default")
return DEFAULT;
if (name == "fixed")
return FIXED;
if (name == "shader")
return SHADER;
LOGWARNING("Unknown render path %s", name.c_str());
return DEFAULT;
}
CStr8 RenderPathEnum::ToString(RenderPath path)
{
switch (path)
{
case RenderPath::DEFAULT:
return "default";
case RenderPath::FIXED:
return "fixed";
case RenderPath::SHADER:
return "shader";
}
return "default"; // Silence warning about reaching end of non-void function.
}
RenderDebugMode RenderDebugModeEnum::FromString(const CStr8& name)
{
if (name == str_RENDER_DEBUG_MODE_NONE.c_str())
return RenderDebugMode::NONE;
if (name == str_RENDER_DEBUG_MODE_AO.c_str())
return RenderDebugMode::AO;
+ if (name == str_RENDER_DEBUG_MODE_ALPHA.c_str())
+ return RenderDebugMode::ALPHA;
+ if (name == str_RENDER_DEBUG_MODE_CUSTOM.c_str())
+ return RenderDebugMode::CUSTOM;
LOGWARNING("Unknown render debug mode %s", name.c_str());
return RenderDebugMode::NONE;
}
CStrIntern RenderDebugModeEnum::ToString(RenderDebugMode mode)
{
switch (mode)
{
case RenderDebugMode::AO:
return str_RENDER_DEBUG_MODE_AO;
+ case RenderDebugMode::ALPHA:
+ return str_RENDER_DEBUG_MODE_ALPHA;
+ case RenderDebugMode::CUSTOM:
+ return str_RENDER_DEBUG_MODE_CUSTOM;
default:
break;
}
return str_RENDER_DEBUG_MODE_NONE;
}
CRenderingOptions::CRenderingOptions() : m_ConfigHooks(new ConfigHooks())
{
m_RenderPath = RenderPath::DEFAULT;
m_Shadows = false;
m_WaterEffects = false;
m_WaterFancyEffects = false;
m_WaterRealDepth = false;
m_WaterRefraction = false;
m_WaterReflection = false;
m_ShadowAlphaFix = false;
m_ARBProgramShadow = true;
m_ShadowPCF = false;
m_Particles = false;
m_Silhouettes = false;
m_PreferGLSL = false;
m_Fog = false;
m_ForceAlphaTest = false;
m_GPUSkinning = false;
m_SmoothLOS = false;
m_PostProc = false;
m_DisplayFrustum = false;
m_DisplayShadowsFrustum = false;
m_RenderActors = true;
}
CRenderingOptions::~CRenderingOptions()
{
ClearHooks();
}
void CRenderingOptions::ReadConfigAndSetupHooks()
{
m_ConfigHooks->Setup("renderpath", [this]() {
CStr renderPath;
CFG_GET_VAL("renderpath", renderPath);
SetRenderPath(RenderPathEnum::FromString(renderPath));
});
m_ConfigHooks->Setup("preferglsl", [this]() {
bool enabled;
CFG_GET_VAL("preferglsl", enabled);
SetPreferGLSL(enabled);
if (CRenderer::IsInitialised())
g_Renderer.GetShadowMap().RecreateTexture();
});
m_ConfigHooks->Setup("shadowquality", []() {
if (CRenderer::IsInitialised())
g_Renderer.GetShadowMap().RecreateTexture();
});
m_ConfigHooks->Setup("shadowscascadecount", []() {
if (CRenderer::IsInitialised())
{
g_Renderer.GetShadowMap().RecreateTexture();
g_Renderer.MakeShadersDirty();
}
});
m_ConfigHooks->Setup("shadowscovermap", []() {
if (CRenderer::IsInitialised())
{
g_Renderer.GetShadowMap().RecreateTexture();
g_Renderer.MakeShadersDirty();
}
});
m_ConfigHooks->Setup("shadowscutoffdistance", []() {
if (CRenderer::IsInitialised())
g_Renderer.GetShadowMap().RecreateTexture();
});
m_ConfigHooks->Setup("shadows", [this]() {
bool enabled;
CFG_GET_VAL("shadows", enabled);
SetShadows(enabled);
});
m_ConfigHooks->Setup("shadowpcf", [this]() {
bool enabled;
CFG_GET_VAL("shadowpcf", enabled);
SetShadowPCF(enabled);
});
m_ConfigHooks->Setup("postproc", m_PostProc);
m_ConfigHooks->Setup("antialiasing", []() {
if (CRenderer::IsInitialised())
g_Renderer.GetPostprocManager().UpdateAntiAliasingTechnique();
});
m_ConfigHooks->Setup("sharpness", []() {
if (CRenderer::IsInitialised())
g_Renderer.GetPostprocManager().UpdateSharpnessFactor();
});
m_ConfigHooks->Setup("sharpening", []() {
if (CRenderer::IsInitialised())
g_Renderer.GetPostprocManager().UpdateSharpeningTechnique();
});
m_ConfigHooks->Setup("smoothlos", m_SmoothLOS);
m_ConfigHooks->Setup("watereffects", m_WaterEffects);
m_ConfigHooks->Setup("waterfancyeffects", m_WaterFancyEffects);
m_ConfigHooks->Setup("waterrealdepth", m_WaterRealDepth);
m_ConfigHooks->Setup("waterrefraction", m_WaterRefraction);
m_ConfigHooks->Setup("waterreflection", m_WaterReflection);
m_ConfigHooks->Setup("particles", m_Particles);
m_ConfigHooks->Setup("fog", [this]() {
bool enabled;
CFG_GET_VAL("fog", enabled);
SetFog(enabled);
});
m_ConfigHooks->Setup("silhouettes", m_Silhouettes);
m_ConfigHooks->Setup("forcealphatest", m_ForceAlphaTest);
m_ConfigHooks->Setup("gpuskinning", [this]() {
bool enabled;
CFG_GET_VAL("gpuskinning", enabled);
if (enabled && !m_PreferGLSL)
LOGWARNING("GPUSkinning has been disabled, because it is not supported with PreferGLSL disabled.");
else if (enabled)
m_GPUSkinning = true;
});
m_ConfigHooks->Setup("renderactors", m_RenderActors);
}
void CRenderingOptions::ClearHooks()
{
m_ConfigHooks->clear();
}
void CRenderingOptions::SetShadows(bool value)
{
m_Shadows = value;
if (CRenderer::IsInitialised())
g_Renderer.MakeShadersDirty();
}
void CRenderingOptions::SetShadowPCF(bool value)
{
m_ShadowPCF = value;
if (CRenderer::IsInitialised())
g_Renderer.MakeShadersDirty();
}
void CRenderingOptions::SetFog(bool value)
{
m_Fog = value;
if (CRenderer::IsInitialised())
g_Renderer.MakeShadersDirty();
}
void CRenderingOptions::SetPreferGLSL(bool value)
{
if (m_GPUSkinning && !value)
{
LOGWARNING("GPUSkinning have been disabled, because it is not supported with PreferGLSL disabled.");
m_GPUSkinning = false;
}
else if (!m_GPUSkinning && value)
CFG_GET_VAL("gpuskinning", m_GPUSkinning);
m_PreferGLSL = value;
if (!CRenderer::IsInitialised())
return;
g_Renderer.MakeShadersDirty();
g_Renderer.RecomputeSystemShaderDefines();
}
void CRenderingOptions::SetRenderPath(RenderPath value)
{
m_RenderPath = value;
if (CRenderer::IsInitialised())
g_Renderer.SetRenderPath(m_RenderPath);
}
void CRenderingOptions::SetRenderDebugMode(RenderDebugMode value)
{
m_RenderDebugMode = value;
if (CRenderer::IsInitialised())
g_Renderer.MakeShadersDirty();
}
Index: ps/trunk/source/renderer/RenderingOptions.h
===================================================================
--- ps/trunk/source/renderer/RenderingOptions.h (revision 25995)
+++ ps/trunk/source/renderer/RenderingOptions.h (revision 25996)
@@ -1,139 +1,141 @@
/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
/**
* Keeps track of the settings used for rendering.
* Ideally this header file should remain very quick to parse,
* so avoid including other headers here unless absolutely necessary.
*
* Lifetime concerns: g_RenderingOptions always exists, but hooks are tied to the configDB's lifetime
* an the renderer may or may not actually exist.
*/
#ifndef INCLUDED_RENDERINGOPTIONS
#define INCLUDED_RENDERINGOPTIONS
#include "ps/CStr.h"
#include "ps/CStrIntern.h"
class CRenderer;
enum RenderPath
{
// If no rendering path is configured explicitly, the renderer
// will choose the path when Open() is called.
DEFAULT,
// Classic fixed function.
FIXED,
// Use new ARB/GLSL system
SHADER
};
struct RenderPathEnum
{
static RenderPath FromString(const CStr8& name);
static CStr8 ToString(RenderPath);
};
enum class RenderDebugMode
{
NONE,
- AO
+ AO,
+ ALPHA,
+ CUSTOM
};
struct RenderDebugModeEnum
{
static RenderDebugMode FromString(const CStr8& name);
static CStrIntern ToString(RenderDebugMode mode);
};
class CRenderingOptions
{
// The renderer needs access to our private variables directly because capabilities have not yet been extracted
// and thus sometimes it needs to change the rendering options without the side-effects.
friend class CRenderer;
public:
CRenderingOptions();
~CRenderingOptions();
void ReadConfigAndSetupHooks();
void ClearHooks();
#define OPTION_DEFAULT_SETTER(NAME, TYPE) \
public: void Set##NAME(TYPE value) { m_##NAME = value; }\
#define OPTION_CUSTOM_SETTER(NAME, TYPE) \
public: void Set##NAME(TYPE value);\
#define OPTION_GETTER(NAME, TYPE)\
public: TYPE Get##NAME() const { return m_##NAME; }\
#define OPTION_DEF(NAME, TYPE)\
private: TYPE m_##NAME;
#define OPTION(NAME, TYPE)\
OPTION_DEFAULT_SETTER(NAME, TYPE); OPTION_GETTER(NAME, TYPE); OPTION_DEF(NAME, TYPE);
#define OPTION_WITH_SIDE_EFFECT(NAME, TYPE)\
OPTION_CUSTOM_SETTER(NAME, TYPE); OPTION_GETTER(NAME, TYPE); OPTION_DEF(NAME, TYPE);
OPTION_WITH_SIDE_EFFECT(Shadows, bool);
OPTION_WITH_SIDE_EFFECT(ShadowPCF, bool);
OPTION_WITH_SIDE_EFFECT(PreferGLSL, bool);
OPTION_WITH_SIDE_EFFECT(Fog, bool);
OPTION_WITH_SIDE_EFFECT(RenderPath, RenderPath);
OPTION_WITH_SIDE_EFFECT(RenderDebugMode, RenderDebugMode);
OPTION(WaterEffects, bool);
OPTION(WaterFancyEffects, bool);
OPTION(WaterRealDepth, bool);
OPTION(WaterRefraction, bool);
OPTION(WaterReflection, bool);
OPTION(ShadowAlphaFix, bool);
OPTION(ARBProgramShadow, bool);
OPTION(Particles, bool);
OPTION(ForceAlphaTest, bool);
OPTION(GPUSkinning, bool);
OPTION(Silhouettes, bool);
OPTION(SmoothLOS, bool);
OPTION(PostProc, bool);
OPTION(DisplayFrustum, bool);
OPTION(DisplayShadowsFrustum, bool);
OPTION(RenderActors, bool);
#undef OPTION_DEFAULT_SETTER
#undef OPTION_CUSTOM_SETTER
#undef OPTION_GETTER
#undef OPTION_DEF
#undef OPTION
#undef OPTION_WITH_SIDE_EFFECT
private:
class ConfigHooks;
std::unique_ptr m_ConfigHooks; // Hide this via PImpl to avoid including ConfigDB.h here.
};
extern CRenderingOptions g_RenderingOptions;
#endif // INCLUDED_RENDERINGOPTIONS