forked from 0ad/0ad
Postproc manager
This was SVN commit r12755.
This commit is contained in:
parent
538286054a
commit
1fb7889539
@ -79,6 +79,9 @@ gentangents = false
|
||||
; Use smooth LOS interpolation; REQUIRES preferglsl=true.
|
||||
smoothlos = false
|
||||
|
||||
; Use screen-space postprocessing filters (HDR, bloom, DOF, etc). Incompatible with fixed renderpath.
|
||||
postproc = false
|
||||
|
||||
; Quality level of shader effects (set to 10 to display effects)
|
||||
materialmgr.quality = 0.0
|
||||
|
||||
|
BIN
binaries/data/mods/public/maps/scenarios/Campaign Test Map.xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/Campaign Test Map.xml
(Stored with Git LFS)
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/Zagros Mountains 01.xml
(Stored with Git LFS)
BIN
binaries/data/mods/public/maps/scenarios/Zagros Mountains 01.xml
(Stored with Git LFS)
Binary file not shown.
9
binaries/data/mods/public/shaders/effects/bloom.xml
Normal file
9
binaries/data/mods/public/shaders/effects/bloom.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<effect>
|
||||
|
||||
<technique>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/bloom"/>
|
||||
</technique>
|
||||
|
||||
</effect>
|
@ -89,7 +89,7 @@
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/model_common">
|
||||
<define name="USE_TRANSPARENT" value="1"/>
|
||||
<define name="REQUIRE_ALPHA_GEQUAL" value="0.9375"/>
|
||||
<define name="REQUIRE_ALPHA_GEQUAL" value="0.6375"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
@ -98,7 +98,7 @@
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/model_common">
|
||||
<define name="USE_TRANSPARENT" value="1"/>
|
||||
<define name="REQUIRE_ALPHA_GEQUAL" value="0.9375"/>
|
||||
<define name="REQUIRE_ALPHA_GEQUAL" value="0.6375"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
@ -106,7 +106,7 @@
|
||||
<require context="ALPHABLEND_PASS_OPAQUE"/>
|
||||
<require shaders="fixed"/>
|
||||
<pass shader="fixed:model">
|
||||
<alpha func="gequal" ref="0.9375"/>
|
||||
<alpha func="gequal" ref="0.6375"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
|
12
binaries/data/mods/public/shaders/effects/postproc/DOF.xml
Normal file
12
binaries/data/mods/public/shaders/effects/postproc/DOF.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<effect>
|
||||
|
||||
<technique>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/dof">
|
||||
<define name="BLUR_FOV" value="3"/>
|
||||
</pass>
|
||||
<pass shader="glsl/hdr"/>
|
||||
</technique>
|
||||
|
||||
</effect>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<effect>
|
||||
|
||||
<technique>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/hdr"/>
|
||||
</technique>
|
||||
|
||||
</effect>
|
107
binaries/data/mods/public/shaders/glsl/bloom.fs
Normal file
107
binaries/data/mods/public/shaders/glsl/bloom.fs
Normal file
@ -0,0 +1,107 @@
|
||||
#version 110
|
||||
|
||||
varying vec2 v_tex;
|
||||
|
||||
uniform sampler2D renderedTex;
|
||||
|
||||
uniform vec2 texSize;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
#if BLOOM_NOP
|
||||
gl_FragColor = texture2D(renderedTex, v_tex);
|
||||
#endif
|
||||
|
||||
#if BLOOM_PASS_H
|
||||
vec4 colour;
|
||||
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2(-2.5, 0.0)) / texSize) * 0.05;
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2(-1.5, 0.0)) / texSize) * 0.1;
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2(-0.5, 0.0)) / texSize) * 0.2;
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2( 0.0, 0.0)) / texSize) * 0.3;
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2( 0.5, 0.0)) / texSize) * 0.2;
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2( 1.5, 0.0)) / texSize) * 0.1;
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2( 2.5, 0.0)) / texSize) * 0.05;
|
||||
|
||||
gl_FragColor.rgb = colour.rgb;
|
||||
gl_FragColor.a = 1.0;
|
||||
#endif
|
||||
|
||||
#if BLOOM_PASS_V
|
||||
vec4 colour;
|
||||
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2(0.0, -2.5)) / texSize) * 0.05;
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2(0.0, -1.5)) / texSize) * 0.1;
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2(0.0, -0.5)) / texSize) * 0.2;
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2(0.0, 0.0)) / texSize) * 0.3;
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2(0.0, 0.5)) / texSize) * 0.2;
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2(0.0, 1.5)) / texSize) * 0.1;
|
||||
colour += texture2D(renderedTex, (gl_FragCoord.xy + vec2(0.0, 2.5)) / texSize) * 0.05;
|
||||
|
||||
gl_FragColor.rgb = colour.rgb;
|
||||
gl_FragColor.a = 1.0;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*varying vec2 v_tex;
|
||||
|
||||
uniform sampler2D bgl_RenderedTexture;
|
||||
uniform sampler2D bgl_DepthTexture;
|
||||
uniform sampler2D bgl_LuminanceTexture;
|
||||
uniform float bgl_RenderedTextureWidth;
|
||||
uniform float bgl_RenderedTextureHeight;
|
||||
|
||||
#define PI 3.14159265
|
||||
|
||||
float width = bgl_RenderedTextureWidth; //texture width
|
||||
float height = bgl_RenderedTextureHeight; //texture height
|
||||
|
||||
vec2 texCoord = v_tex;
|
||||
vec2 texcoord = v_tex;
|
||||
|
||||
|
||||
float BRIGHT_PASS_THRESHOLD = 0.6;
|
||||
float BRIGHT_PASS_OFFSET = 0.6;
|
||||
|
||||
#define blurclamp 0.0015
|
||||
#define bias 0.01
|
||||
|
||||
#define KERNEL_SIZE 3.0
|
||||
|
||||
|
||||
|
||||
vec4 bright(vec2 coo)
|
||||
{
|
||||
vec4 color = texture2D(bgl_RenderedTexture, coo);
|
||||
|
||||
color = max(color - BRIGHT_PASS_THRESHOLD, 0.0);
|
||||
|
||||
return color / (color + BRIGHT_PASS_OFFSET);
|
||||
}
|
||||
|
||||
|
||||
void main0(void)
|
||||
{
|
||||
vec2 blur = vec2(clamp( bias, -blurclamp, blurclamp ));
|
||||
|
||||
vec4 col = vec4( 0, 0, 0, 0 );
|
||||
for ( float x = -KERNEL_SIZE + 1.0; x < KERNEL_SIZE; x += 1.0 )
|
||||
{
|
||||
for ( float y = -KERNEL_SIZE + 1.0; y < KERNEL_SIZE; y += 1.0 )
|
||||
{
|
||||
col += bright( texcoord + vec2( blur.x * x, blur.y * y ) );
|
||||
}
|
||||
}
|
||||
col /= ((KERNEL_SIZE+KERNEL_SIZE)-1.0)*((KERNEL_SIZE+KERNEL_SIZE)-1.0);
|
||||
|
||||
//gl_FragColor = col + texture2D(bgl_RenderedTexture, texcoord);
|
||||
|
||||
//col *= 0.9;
|
||||
gl_FragColor = 1.0 - (1.0 - col) * (1.0 - texture2D(bgl_RenderedTexture, texcoord));
|
||||
|
||||
}*/
|
||||
|
11
binaries/data/mods/public/shaders/glsl/bloom.xml
Normal file
11
binaries/data/mods/public/shaders/glsl/bloom.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<program type="glsl">
|
||||
|
||||
<vertex file="glsl/hdr.vs">
|
||||
<stream name="pos"/>
|
||||
<stream name="uv0"/>
|
||||
</vertex>
|
||||
|
||||
<fragment file="glsl/bloom.fs"/>
|
||||
|
||||
</program>
|
63
binaries/data/mods/public/shaders/glsl/dof.fs
Normal file
63
binaries/data/mods/public/shaders/glsl/dof.fs
Normal file
@ -0,0 +1,63 @@
|
||||
#version 120
|
||||
|
||||
uniform sampler2D renderedTex;
|
||||
uniform sampler2D depthTex;
|
||||
uniform sampler2D blurTex2;
|
||||
uniform sampler2D blurTex4;
|
||||
uniform sampler2D blurTex8;
|
||||
|
||||
uniform float width;
|
||||
uniform float height;
|
||||
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
|
||||
uniform float brightness;
|
||||
uniform float hdr;
|
||||
uniform float saturation;
|
||||
uniform float bloom;
|
||||
|
||||
varying vec2 v_tex;
|
||||
|
||||
|
||||
float linearizeDepth(float depth)
|
||||
{
|
||||
return -zFar * zNear / (depth * (zFar - zNear) - zFar);
|
||||
}
|
||||
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec3 colour = texture2D(renderedTex, v_tex).rgb;
|
||||
|
||||
vec3 blur2 = texture2D(blurTex2, v_tex).rgb;
|
||||
vec3 blur4 = texture2D(blurTex4, v_tex).rgb;
|
||||
vec3 blur8 = texture2D(blurTex8, v_tex).rgb;
|
||||
|
||||
float depth = texture2D(depthTex, v_tex).r;
|
||||
|
||||
float midDepth = texture2D(depthTex, vec2(0.5, 0.5)).r;
|
||||
midDepth += texture2D(depthTex, vec2(0.4, 0.4)).r;
|
||||
midDepth += texture2D(depthTex, vec2(0.4, 0.6)).r;
|
||||
midDepth += texture2D(depthTex, vec2(0.6, 0.4)).r;
|
||||
midDepth += texture2D(depthTex, vec2(0.6, 0.6)).r;
|
||||
|
||||
midDepth /= 5.0;
|
||||
|
||||
|
||||
float lDepth = linearizeDepth(depth);
|
||||
float lMidDepth = linearizeDepth(midDepth);
|
||||
float amount = abs(lDepth - lMidDepth);
|
||||
|
||||
amount = clamp(amount / (lMidDepth * BLUR_FOV), 0.0, 1.0);
|
||||
|
||||
colour = (amount >= 0.0 && amount < 0.25) ? mix(colour, blur2, (amount - 0.0) / (0.25)) : colour;
|
||||
colour = (amount >= 0.25 && amount < 0.50) ? mix(blur2, blur4, (amount - 0.25) / (0.25)) : colour;
|
||||
colour = (amount >= 0.50 && amount < 0.75) ? mix(blur4, blur8, (amount - 0.50) / (0.25)) : colour;
|
||||
colour = (amount >= 0.75 && amount <= 1.00) ? blur8 : colour;
|
||||
|
||||
gl_FragColor.rgb = colour;
|
||||
gl_FragColor.a = 1.0;
|
||||
}
|
||||
|
||||
|
13
binaries/data/mods/public/shaders/glsl/dof.xml
Normal file
13
binaries/data/mods/public/shaders/glsl/dof.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<program type="glsl">
|
||||
|
||||
<vertex file="glsl/hdr.vs">
|
||||
<stream name="pos"/>
|
||||
<stream name="uv0"/>
|
||||
<attrib name="a_vertex" semantics="gl_Vertex"/>
|
||||
<attrib name="a_uv0" semantics="gl_MultiTexCoord0"/>
|
||||
</vertex>
|
||||
|
||||
<fragment file="glsl/dof.fs"/>
|
||||
|
||||
</program>
|
50
binaries/data/mods/public/shaders/glsl/hdr.fs
Normal file
50
binaries/data/mods/public/shaders/glsl/hdr.fs
Normal file
@ -0,0 +1,50 @@
|
||||
#version 120
|
||||
|
||||
uniform sampler2D renderedTex;
|
||||
uniform sampler2D depthTex;
|
||||
uniform sampler2D blurTex2;
|
||||
uniform sampler2D blurTex4;
|
||||
uniform sampler2D blurTex8;
|
||||
|
||||
uniform float width;
|
||||
uniform float height;
|
||||
|
||||
uniform float brightness;
|
||||
uniform float hdr;
|
||||
uniform float saturation;
|
||||
uniform float bloom;
|
||||
|
||||
varying vec2 v_tex;
|
||||
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
||||
|
||||
vec3 colour = texture2D(renderedTex, v_tex).rgb;
|
||||
vec3 bloomv2 = texture2D(blurTex2, v_tex).rgb;
|
||||
vec3 bloomv4 = texture2D(blurTex4, v_tex).rgb;
|
||||
vec3 bloomv8 = texture2D(blurTex8, v_tex).rgb;
|
||||
|
||||
bloomv2 = max(bloomv2 - bloom, vec3(0.0));
|
||||
bloomv4 = max(bloomv4 - bloom, vec3(0.0));
|
||||
bloomv8 = max(bloomv8 - bloom, vec3(0.0));
|
||||
|
||||
vec3 bloomv = (bloomv2 + bloomv4 + bloomv8) / 3.0;
|
||||
|
||||
colour = max(bloomv, colour);
|
||||
|
||||
colour += vec3(brightness);
|
||||
|
||||
colour -= vec3(0.5);
|
||||
colour *= vec3(hdr);
|
||||
colour += vec3(0.5);
|
||||
|
||||
colour = mix(vec3(dot(colour, vec3(0.299, 0.587, 0.114))), colour, saturation);
|
||||
|
||||
|
||||
gl_FragColor.rgb = colour;
|
||||
gl_FragColor.a = 1.0;
|
||||
}
|
||||
|
||||
|
10
binaries/data/mods/public/shaders/glsl/hdr.vs
Normal file
10
binaries/data/mods/public/shaders/glsl/hdr.vs
Normal file
@ -0,0 +1,10 @@
|
||||
#version 110
|
||||
|
||||
varying vec2 v_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_Vertex;
|
||||
|
||||
v_tex = vec2(gl_MultiTexCoord0);
|
||||
}
|
13
binaries/data/mods/public/shaders/glsl/hdr.xml
Normal file
13
binaries/data/mods/public/shaders/glsl/hdr.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<program type="glsl">
|
||||
|
||||
<vertex file="glsl/hdr.vs">
|
||||
<stream name="pos"/>
|
||||
<stream name="uv0"/>
|
||||
<attrib name="a_vertex" semantics="gl_Vertex"/>
|
||||
<attrib name="a_uv0" semantics="gl_MultiTexCoord0"/>
|
||||
</vertex>
|
||||
|
||||
<fragment file="glsl/hdr.fs"/>
|
||||
|
||||
</program>
|
@ -31,6 +31,9 @@ uniform vec3 ambient;
|
||||
uniform vec3 sunColor;
|
||||
uniform vec3 sunDir;
|
||||
|
||||
uniform vec3 fogColor;
|
||||
uniform vec2 fogParams;
|
||||
|
||||
varying vec4 v_lighting;
|
||||
varying vec2 v_tex;
|
||||
varying vec2 v_los;
|
||||
@ -89,6 +92,22 @@ float get_shadow()
|
||||
#endif
|
||||
}
|
||||
|
||||
vec3 get_fog(vec3 color)
|
||||
{
|
||||
float density = fogParams.x;
|
||||
float maxFog = fogParams.y;
|
||||
|
||||
const float LOG2 = 1.442695;
|
||||
float z = gl_FragCoord.z / gl_FragCoord.w;
|
||||
float fogFactor = exp2(-density * density * z * z * LOG2);
|
||||
|
||||
fogFactor = fogFactor * (1.0 - maxFog) + maxFog;
|
||||
|
||||
fogFactor = clamp(fogFactor, 0.0, 1.0);
|
||||
|
||||
return mix(fogColor, color, fogFactor);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 coord = v_tex;
|
||||
@ -244,6 +263,8 @@ void main()
|
||||
color = mix(texdiffuse, color, specular.a);
|
||||
#endif
|
||||
|
||||
color = get_fog(color);
|
||||
|
||||
#if !IGNORE_LOS
|
||||
float los = texture2D(losTex, v_los).a;
|
||||
los = los < 0.03 ? 0.0 : los;
|
||||
|
@ -22,6 +22,9 @@ uniform vec3 ambient;
|
||||
uniform vec3 sunColor;
|
||||
uniform vec3 sunDir;
|
||||
|
||||
uniform vec3 fogColor;
|
||||
uniform vec2 fogParams;
|
||||
|
||||
uniform vec2 textureTransform;
|
||||
|
||||
varying vec3 v_lighting;
|
||||
@ -140,6 +143,21 @@ vec4 triplanarNormals(sampler2D sampler, vec3 wpos)
|
||||
}
|
||||
#endif
|
||||
|
||||
vec3 get_fog(vec3 color)
|
||||
{
|
||||
float density = fogParams.x;
|
||||
float maxFog = fogParams.y;
|
||||
|
||||
const float LOG2 = 1.442695;
|
||||
float z = gl_FragCoord.z / gl_FragCoord.w;
|
||||
float fogFactor = exp2(-density * density * z * z * LOG2);
|
||||
|
||||
fogFactor = fogFactor * (1.0 - maxFog) + maxFog;
|
||||
|
||||
fogFactor = clamp(fogFactor, 0.0, 1.0);
|
||||
|
||||
return mix(fogColor, color, fogFactor);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
@ -218,6 +236,8 @@ void main()
|
||||
color = mix(texdiffuse, color, specular.a);
|
||||
#endif
|
||||
|
||||
color = get_fog(color);
|
||||
|
||||
float los = texture2D(losTex, v_los).a;
|
||||
los = los < 0.03 ? 0.0 : los;
|
||||
color *= los;
|
||||
|
@ -17,9 +17,28 @@ uniform float fullDepth; // Depth at which to use full murkiness (shallower wat
|
||||
uniform vec3 reflectionTint; // Tint for reflection (used for really muddy water)
|
||||
uniform float reflectionTintStrength; // Strength of reflection tint (how much of it to mix in)
|
||||
|
||||
uniform vec3 fogColor;
|
||||
uniform vec2 fogParams;
|
||||
|
||||
varying vec3 worldPos;
|
||||
varying float waterDepth;
|
||||
|
||||
vec3 get_fog(vec3 color)
|
||||
{
|
||||
float density = fogParams.x;
|
||||
float maxFog = fogParams.y;
|
||||
|
||||
const float LOG2 = 1.442695;
|
||||
float z = gl_FragCoord.z / gl_FragCoord.w;
|
||||
float fogFactor = exp2(-density * density * z * z * LOG2);
|
||||
|
||||
fogFactor = fogFactor * (1.0 - maxFog) + maxFog;
|
||||
|
||||
fogFactor = clamp(fogFactor, 0.0, 1.0);
|
||||
|
||||
return mix(fogColor, color, fogFactor);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 n, l, h, v; // Normal, light vector, half-vector and view vector (vector to eye)
|
||||
@ -55,7 +74,11 @@ void main()
|
||||
losMod = texture2D(losMap, gl_TexCoord[3].st).a;
|
||||
losMod = losMod < 0.03 ? 0.0 : losMod;
|
||||
|
||||
gl_FragColor.rgb = mix(refrColor + 0.3*specular, reflColor + specular, fresnel) * losMod;
|
||||
gl_FragColor.rgb = mix(refrColor + 0.3*specular, reflColor + specular, fresnel);
|
||||
|
||||
gl_FragColor.rgb = get_fog(gl_FragColor.rgb);
|
||||
|
||||
gl_FragColor.rgb *= losMod;
|
||||
|
||||
// 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)
|
||||
|
@ -32,7 +32,11 @@ CLightEnv::CLightEnv()
|
||||
m_LightingModel("standard"),
|
||||
m_SunColor(1.5, 1.5, 1.5),
|
||||
m_TerrainAmbientColor(0x50/255.f, 0x60/255.f, 0x85/255.f),
|
||||
m_UnitsAmbientColor(0x80/255.f, 0x80/255.f, 0x80/255.f)
|
||||
m_UnitsAmbientColor(0x80/255.f, 0x80/255.f, 0x80/255.f),
|
||||
m_FogColor(0xCC/255.f, 0xCC/255.f, 0xE5/255.f),
|
||||
m_FogFactor(0.000),
|
||||
m_FogMax(0.5),
|
||||
m_Brightness(0.0), m_Contrast(1.0), m_Saturation(0.99), m_Bloom(0.1999)
|
||||
{
|
||||
CalculateSunDirection();
|
||||
}
|
||||
|
@ -69,6 +69,12 @@ public:
|
||||
RGBColor m_SunColor;
|
||||
RGBColor m_TerrainAmbientColor;
|
||||
RGBColor m_UnitsAmbientColor;
|
||||
RGBColor m_FogColor;
|
||||
|
||||
float m_FogFactor;
|
||||
float m_FogMax;
|
||||
|
||||
float m_Brightness, m_Contrast, m_Saturation, m_Bloom;
|
||||
|
||||
public:
|
||||
CLightEnv();
|
||||
@ -134,7 +140,14 @@ public:
|
||||
m_LightingModel == o.m_LightingModel &&
|
||||
m_SunColor == o.m_SunColor &&
|
||||
m_TerrainAmbientColor == o.m_TerrainAmbientColor &&
|
||||
m_UnitsAmbientColor == o.m_UnitsAmbientColor;
|
||||
m_UnitsAmbientColor == o.m_UnitsAmbientColor &&
|
||||
m_FogColor == o.m_FogColor &&
|
||||
m_FogFactor == o.m_FogFactor &&
|
||||
m_FogMax == o.m_FogMax &&
|
||||
m_Brightness == o.m_Brightness &&
|
||||
m_Contrast == o.m_Contrast &&
|
||||
m_Saturation == o.m_Saturation &&
|
||||
m_Bloom == o.m_Bloom;
|
||||
}
|
||||
|
||||
bool operator!=(const CLightEnv& o) const
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "ps/LoaderThunks.h"
|
||||
#include "ps/World.h"
|
||||
#include "ps/XML/Xeromyces.h"
|
||||
#include "renderer/PostprocManager.h"
|
||||
#include "renderer/SkyManager.h"
|
||||
#include "renderer/WaterManager.h"
|
||||
#include "simulation2/Simulation2.h"
|
||||
@ -56,13 +57,15 @@ CMapReader::CMapReader()
|
||||
cur_terrain_tex = 0; // important - resets generator state
|
||||
|
||||
// Maps that don't override the default probably want the old lighting model
|
||||
m_LightEnv.SetLightingModel("old");
|
||||
//m_LightEnv.SetLightingModel("old");
|
||||
//pPostproc->SetPostEffect(L"default");
|
||||
|
||||
}
|
||||
|
||||
// LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
|
||||
void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
|
||||
WaterManager* pWaterMan_, SkyManager* pSkyMan_,
|
||||
CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_,
|
||||
CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_, CPostprocManager* pPostproc_,
|
||||
CSimulation2 *pSimulation2_, const CSimContext* pSimContext_, int playerID_, bool skipEntities)
|
||||
{
|
||||
// latch parameters (held until DelayedLoadFinished)
|
||||
@ -73,6 +76,7 @@ void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
|
||||
pSkyMan = pSkyMan_;
|
||||
pCinema = pCinema_;
|
||||
pTrigMan = pTrigMan_;
|
||||
pPostproc = pPostproc_;
|
||||
pSimulation2 = pSimulation2_;
|
||||
pSimContext = pSimContext_;
|
||||
m_PlayerID = playerID_;
|
||||
@ -106,6 +110,10 @@ void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
|
||||
// delete all existing entities
|
||||
if (pSimulation2)
|
||||
pSimulation2->ResetState();
|
||||
|
||||
// reset post effects
|
||||
if (pPostproc)
|
||||
pPostproc->SetPostEffect(L"default");
|
||||
|
||||
// load map settings script
|
||||
RegMemFun(this, &CMapReader::LoadScriptSettings, L"CMapReader::LoadScriptSettings", 50);
|
||||
@ -133,7 +141,7 @@ void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
|
||||
// LoadRandomMap: try to load the map data; reinitialise the scene to new data if successful
|
||||
void CMapReader::LoadRandomMap(const CStrW& scriptFile, const CScriptValRooted& settings, CTerrain *pTerrain_,
|
||||
WaterManager* pWaterMan_, SkyManager* pSkyMan_,
|
||||
CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_,
|
||||
CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_, CPostprocManager* pPostproc_,
|
||||
CSimulation2 *pSimulation2_, int playerID_)
|
||||
{
|
||||
// latch parameters (held until DelayedLoadFinished)
|
||||
@ -146,6 +154,7 @@ void CMapReader::LoadRandomMap(const CStrW& scriptFile, const CScriptValRooted&
|
||||
pSkyMan = pSkyMan_;
|
||||
pCinema = pCinema_;
|
||||
pTrigMan = pTrigMan_;
|
||||
pPostproc = pPostproc_;
|
||||
pSimulation2 = pSimulation2_;
|
||||
pSimContext = pSimulation2 ? &pSimulation2->GetSimContext() : NULL;
|
||||
m_PlayerID = playerID_;
|
||||
@ -558,6 +567,7 @@ void CXMLReader::ReadEnvironment(XMBElement parent)
|
||||
#define EL(x) int el_##x = xmb_file.GetElementID(#x)
|
||||
#define AT(x) int at_##x = xmb_file.GetAttributeID(#x)
|
||||
EL(lightingmodel);
|
||||
EL(posteffect);
|
||||
EL(skyset);
|
||||
EL(suncolour);
|
||||
EL(sunelevation);
|
||||
@ -575,6 +585,15 @@ void CXMLReader::ReadEnvironment(XMBElement parent)
|
||||
EL(tint);
|
||||
EL(reflectiontint);
|
||||
EL(reflectiontintstrength);
|
||||
EL(fog);
|
||||
EL(fogcolour);
|
||||
EL(fogfactor);
|
||||
EL(fogthickness);
|
||||
EL(postproc);
|
||||
EL(brightness);
|
||||
EL(contrast);
|
||||
EL(saturation);
|
||||
EL(bloom);
|
||||
AT(r); AT(g); AT(b);
|
||||
#undef AT
|
||||
#undef EL
|
||||
@ -587,7 +606,7 @@ void CXMLReader::ReadEnvironment(XMBElement parent)
|
||||
|
||||
if (element_name == el_lightingmodel)
|
||||
{
|
||||
m_MapReader.m_LightEnv.SetLightingModel(element.GetText());
|
||||
// NOP - obsolete.
|
||||
}
|
||||
else if (element_name == el_skyset)
|
||||
{
|
||||
@ -623,6 +642,56 @@ void CXMLReader::ReadEnvironment(XMBElement parent)
|
||||
attrs.GetNamedItem(at_g).ToFloat(),
|
||||
attrs.GetNamedItem(at_b).ToFloat());
|
||||
}
|
||||
else if (element_name == el_fog)
|
||||
{
|
||||
XERO_ITER_EL(element, fog)
|
||||
{
|
||||
int element_name = fog.GetNodeName();
|
||||
if (element_name == el_fogcolour)
|
||||
{
|
||||
XMBAttributeList attrs = fog.GetAttributes();
|
||||
m_MapReader.m_LightEnv.m_FogColor = RGBColor(
|
||||
attrs.GetNamedItem(at_r).ToFloat(),
|
||||
attrs.GetNamedItem(at_g).ToFloat(),
|
||||
attrs.GetNamedItem(at_b).ToFloat());
|
||||
}
|
||||
else if (element_name == el_fogfactor)
|
||||
{
|
||||
m_MapReader.m_LightEnv.m_FogFactor = fog.GetText().ToFloat();
|
||||
}
|
||||
else if (element_name == el_fogthickness)
|
||||
{
|
||||
m_MapReader.m_LightEnv.m_FogMax = fog.GetText().ToFloat();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (element_name == el_postproc)
|
||||
{
|
||||
XERO_ITER_EL(element, postproc)
|
||||
{
|
||||
int element_name = postproc.GetNodeName();
|
||||
if (element_name == el_brightness)
|
||||
{
|
||||
m_MapReader.m_LightEnv.m_Brightness = postproc.GetText().ToFloat();
|
||||
}
|
||||
else if (element_name == el_contrast)
|
||||
{
|
||||
m_MapReader.m_LightEnv.m_Contrast = postproc.GetText().ToFloat();
|
||||
}
|
||||
else if (element_name == el_saturation)
|
||||
{
|
||||
m_MapReader.m_LightEnv.m_Saturation = postproc.GetText().ToFloat();
|
||||
}
|
||||
else if (element_name == el_bloom)
|
||||
{
|
||||
m_MapReader.m_LightEnv.m_Bloom = postproc.GetText().ToFloat();
|
||||
}
|
||||
else if (element_name == el_posteffect)
|
||||
{
|
||||
m_MapReader.pPostproc->SetPostEffect(postproc.GetText().FromUTF8());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (element_name == el_water)
|
||||
{
|
||||
XERO_ITER_EL(element, waterbody)
|
||||
@ -1321,7 +1390,9 @@ int CMapReader::ParseEnvironment()
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_LightEnv.SetLightingModel("standard");
|
||||
//m_LightEnv.SetLightingModel("standard");
|
||||
if (pPostproc)
|
||||
pPostproc->SetPostEffect(L"default");
|
||||
|
||||
std::wstring skySet;
|
||||
GET_ENVIRONMENT_PROPERTY(envObj.get(), SkySet, skySet)
|
||||
|
@ -32,6 +32,7 @@ class WaterManager;
|
||||
class SkyManager;
|
||||
class CLightEnv;
|
||||
class CCinemaManager;
|
||||
class CPostprocManager;
|
||||
class CTriggerManager;
|
||||
class CSimulation2;
|
||||
class CSimContext;
|
||||
@ -53,10 +54,10 @@ public:
|
||||
|
||||
// LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
|
||||
void LoadMap(const VfsPath& pathname, CTerrain*, WaterManager*, SkyManager*, CLightEnv*, CGameView*,
|
||||
CCinemaManager*, CTriggerManager*, CSimulation2*, const CSimContext*, int playerID, bool skipEntities);
|
||||
CCinemaManager*, CTriggerManager*, CPostprocManager* pPostproc, CSimulation2*, const CSimContext*,
|
||||
int playerID, bool skipEntities);
|
||||
|
||||
void LoadRandomMap(const CStrW& scriptFile, const CScriptValRooted& settings, CTerrain*, WaterManager*, SkyManager*, CLightEnv*, CGameView*,
|
||||
CCinemaManager*, CTriggerManager*, CSimulation2*, int playerID);
|
||||
void LoadRandomMap(const CStrW& scriptFile, const CScriptValRooted& settings, CTerrain*, WaterManager*, SkyManager*, CLightEnv*, CGameView*, CCinemaManager*, CTriggerManager*, CPostprocManager* pPostproc_, CSimulation2*, int playerID);
|
||||
|
||||
private:
|
||||
// Load script settings for use by scripts
|
||||
@ -129,6 +130,7 @@ private:
|
||||
CTerrain* pTerrain;
|
||||
WaterManager* pWaterMan;
|
||||
SkyManager* pSkyMan;
|
||||
CPostprocManager* pPostproc;
|
||||
CLightEnv* pLightEnv;
|
||||
CGameView* pGameView;
|
||||
CCinemaManager* pCinema;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "ps/Loader.h"
|
||||
#include "ps/Filesystem.h"
|
||||
#include "ps/XML/XMLWriter.h"
|
||||
#include "renderer/PostprocManager.h"
|
||||
#include "renderer/SkyManager.h"
|
||||
#include "renderer/WaterManager.h"
|
||||
#include "simulation2/Simulation2.h"
|
||||
@ -53,6 +54,7 @@ CMapWriter::CMapWriter()
|
||||
void CMapWriter::SaveMap(const VfsPath& pathname, CTerrain* pTerrain,
|
||||
WaterManager* pWaterMan, SkyManager* pSkyMan,
|
||||
CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* pCinema,
|
||||
CPostprocManager* pPostproc,
|
||||
CSimulation2* pSimulation2)
|
||||
{
|
||||
CFilePacker packer(FILE_VERSION, "PSMP");
|
||||
@ -64,7 +66,7 @@ void CMapWriter::SaveMap(const VfsPath& pathname, CTerrain* pTerrain,
|
||||
packer.Write(pathname);
|
||||
|
||||
VfsPath pathnameXML = pathname.ChangeExtension(L".xml");
|
||||
WriteXML(pathnameXML, pWaterMan, pSkyMan, pLightEnv, pCamera, pCinema, pSimulation2);
|
||||
WriteXML(pathnameXML, pWaterMan, pSkyMan, pLightEnv, pCamera, pCinema, pPostproc, pSimulation2);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -173,6 +175,7 @@ void CMapWriter::PackTerrain(CFilePacker& packer, CTerrain* pTerrain)
|
||||
void CMapWriter::WriteXML(const VfsPath& filename,
|
||||
WaterManager* pWaterMan, SkyManager* pSkyMan,
|
||||
CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* pCinema,
|
||||
CPostprocManager* pPostproc,
|
||||
CSimulation2* pSimulation2)
|
||||
{
|
||||
XML_Start();
|
||||
@ -190,7 +193,6 @@ void CMapWriter::WriteXML(const VfsPath& filename,
|
||||
{
|
||||
XML_Element("Environment");
|
||||
|
||||
XML_Setting("LightingModel", pLightEnv->GetLightingModel());
|
||||
XML_Setting("SkySet", pSkyMan->GetSkySet());
|
||||
{
|
||||
XML_Element("SunColour");
|
||||
@ -218,6 +220,17 @@ void CMapWriter::WriteXML(const VfsPath& filename,
|
||||
XML_Attribute("g", pLightEnv->m_UnitsAmbientColor.Y);
|
||||
XML_Attribute("b", pLightEnv->m_UnitsAmbientColor.Z);
|
||||
}
|
||||
{
|
||||
XML_Element("Fog");
|
||||
XML_Setting("FogFactor", pLightEnv->m_FogFactor);
|
||||
XML_Setting("FogThickness", pLightEnv->m_FogMax);
|
||||
{
|
||||
XML_Element("FogColour");
|
||||
XML_Attribute("r", pLightEnv->m_FogColor.X);
|
||||
XML_Attribute("g", pLightEnv->m_FogColor.Y);
|
||||
XML_Attribute("b", pLightEnv->m_FogColor.Z);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
XML_Element("Water");
|
||||
@ -251,6 +264,17 @@ void CMapWriter::WriteXML(const VfsPath& filename,
|
||||
XML_Setting("ReflectionTintStrength", pWaterMan->m_ReflectionTintStrength);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
XML_Element("Postproc");
|
||||
{
|
||||
XML_Setting("Brightness", pLightEnv->m_Brightness);
|
||||
XML_Setting("Contrast", pLightEnv->m_Contrast);
|
||||
XML_Setting("Saturation", pLightEnv->m_Saturation);
|
||||
XML_Setting("Bloom", pLightEnv->m_Bloom);
|
||||
XML_Setting("PostEffect", pPostproc->GetPostEffect());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -29,6 +29,7 @@ class CLightEnv;
|
||||
class CTerrain;
|
||||
class CCamera;
|
||||
class CCinemaManager;
|
||||
class CPostprocManager;
|
||||
class CTriggerManager;
|
||||
class WaterManager;
|
||||
class SkyManager;
|
||||
@ -46,7 +47,8 @@ public:
|
||||
void SaveMap(const VfsPath& pathname, CTerrain* pTerr,
|
||||
WaterManager* pWaterMan, SkyManager* pSkyMan,
|
||||
CLightEnv* pLightEnv, CCamera* pCamera,
|
||||
CCinemaManager* pCinema, CSimulation2* pSimulation2);
|
||||
CCinemaManager* pCinema, CPostprocManager* pPostproc,
|
||||
CSimulation2* pSimulation2);
|
||||
|
||||
private:
|
||||
// PackMap: pack the current world into a raw data stream
|
||||
@ -62,7 +64,8 @@ private:
|
||||
// WriteXML: output some other data (entities, etc) in XML format
|
||||
void WriteXML(const VfsPath& pathname, WaterManager* pWaterMan,
|
||||
SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera,
|
||||
CCinemaManager* pCinema, CSimulation2* pSimulation2);
|
||||
CCinemaManager* pCinema, CPostprocManager* pPostproc,
|
||||
CSimulation2* pSimulation2);
|
||||
// void WriteTriggerGroup(XMLWriter_File& xml_file_, const MapTriggerGroup& group,
|
||||
// const std::list<MapTriggerGroup>& groupList);
|
||||
// void WriteTrigger(XMLWriter_File& xml_file_, const MapTrigger& trigger);
|
||||
|
@ -181,6 +181,8 @@ FUNC(void, glFramebufferTexture3DEXT, (GLenum target, GLenum attachment, GLenum
|
||||
FUNC(void, glFramebufferRenderbufferEXT, (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer))
|
||||
FUNC(void, glGetFramebufferAttachmentParameterivEXT, (GLenum target, GLenum attachment, GLenum pname, GLint *params))
|
||||
FUNC(void, glGenerateMipmapEXT, (GLenum target))
|
||||
FUNC(void, glBlitFramebufferEXT, (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter))
|
||||
FUNC(void, glDrawBuffers, (GLsizei n, const GLenum *bufs))
|
||||
|
||||
// GL_ARB_vertex_program, GL_ARB_fragment_program
|
||||
FUNC(void, glProgramStringARB, (GLenum target, GLenum format, GLsizei len, const GLvoid *string))
|
||||
|
@ -82,7 +82,8 @@ void CWorld::RegisterInit(const CStrW& mapFile, int playerID)
|
||||
CRenderer::IsInitialised() ? g_Renderer.GetSkyManager() : NULL,
|
||||
&g_LightEnv, m_pGame->GetView(),
|
||||
m_pGame->GetView() ? m_pGame->GetView()->GetCinema() : NULL,
|
||||
pTriggerManager, m_pGame->GetSimulation2(), &m_pGame->GetSimulation2()->GetSimContext(), playerID, false);
|
||||
pTriggerManager, CRenderer::IsInitialised() ? &g_Renderer.GetPostprocManager() : NULL,
|
||||
m_pGame->GetSimulation2(), &m_pGame->GetSimulation2()->GetSimContext(), playerID, false);
|
||||
// fails immediately, or registers for delay loading
|
||||
}
|
||||
catch (PSERROR_File& err)
|
||||
@ -106,7 +107,8 @@ void CWorld::RegisterInitRMS(const CStrW& scriptFile, const CScriptValRooted& se
|
||||
CRenderer::IsInitialised() ? g_Renderer.GetSkyManager() : NULL,
|
||||
&g_LightEnv, m_pGame->GetView(),
|
||||
m_pGame->GetView() ? m_pGame->GetView()->GetCinema() : NULL,
|
||||
pTriggerManager, m_pGame->GetSimulation2(), playerID);
|
||||
pTriggerManager, CRenderer::IsInitialised() ? &g_Renderer.GetPostprocManager() : NULL,
|
||||
m_pGame->GetSimulation2(), playerID);
|
||||
// registers for delay loading
|
||||
}
|
||||
|
||||
|
488
source/renderer/PostprocManager.cpp
Normal file
488
source/renderer/PostprocManager.cpp
Normal file
@ -0,0 +1,488 @@
|
||||
/* Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "lib/ogl.h"
|
||||
#include "maths/MathUtil.h"
|
||||
|
||||
#include "gui/GUIutil.h"
|
||||
#include "lib/bits.h"
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/Filesystem.h"
|
||||
#include "ps/Game.h"
|
||||
#include "ps/World.h"
|
||||
|
||||
#include "graphics/GameView.h"
|
||||
#include "graphics/LightEnv.h"
|
||||
#include "graphics/ShaderManager.h"
|
||||
|
||||
#include "renderer/PostprocManager.h"
|
||||
#include "renderer/Renderer.h"
|
||||
|
||||
|
||||
CPostprocManager::CPostprocManager()
|
||||
: m_IsInitialised(false), m_PingFbo(0), m_PongFbo(0), m_PostProcEffect(L"default"), m_ColourTex1(0), m_ColourTex2(0),
|
||||
m_DepthTex(0), m_BloomFbo(0), m_BlurTex2a(0), m_BlurTex2b(0), m_BlurTex4a(0), m_BlurTex4b(0),
|
||||
m_BlurTex8a(0), m_BlurTex8b(0), m_WhichBuffer(true)
|
||||
{
|
||||
}
|
||||
|
||||
CPostprocManager::~CPostprocManager()
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
|
||||
void CPostprocManager::Initialize()
|
||||
{
|
||||
RecreateBuffers();
|
||||
m_IsInitialised = true;
|
||||
SetPostEffect(L"default");
|
||||
}
|
||||
|
||||
void CPostprocManager::Cleanup()
|
||||
{
|
||||
if (m_IsInitialised)
|
||||
{
|
||||
if (m_PingFbo) pglDeleteFramebuffersEXT(1, &m_PingFbo);
|
||||
if (m_PongFbo) pglDeleteFramebuffersEXT(1, &m_PongFbo);
|
||||
if (m_BloomFbo) pglDeleteFramebuffersEXT(1, &m_BloomFbo);
|
||||
m_PingFbo = m_PongFbo = m_BloomFbo = 0;
|
||||
|
||||
if (m_ColourTex1) glDeleteTextures(1, &m_ColourTex1);
|
||||
if (m_ColourTex2) glDeleteTextures(1, &m_ColourTex2);
|
||||
if (m_DepthTex) glDeleteTextures(1, &m_DepthTex);
|
||||
m_ColourTex1 = m_ColourTex2 = m_DepthTex = 0;
|
||||
|
||||
if (m_BlurTex2a) glDeleteTextures(1, &m_BlurTex2a);
|
||||
if (m_BlurTex2b) glDeleteTextures(1, &m_BlurTex2b);
|
||||
if (m_BlurTex4a) glDeleteTextures(1, &m_BlurTex4a);
|
||||
if (m_BlurTex4b) glDeleteTextures(1, &m_BlurTex4b);
|
||||
if (m_BlurTex8a) glDeleteTextures(1, &m_BlurTex8a);
|
||||
if (m_BlurTex8b) glDeleteTextures(1, &m_BlurTex8b);
|
||||
m_BlurTex2a = m_BlurTex2b = m_BlurTex4a = m_BlurTex4b = m_BlurTex8a = m_BlurTex8b = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CPostprocManager::RecreateBuffers()
|
||||
{
|
||||
Cleanup();
|
||||
|
||||
m_Width = g_Renderer.GetWidth();
|
||||
m_Height = g_Renderer.GetHeight();
|
||||
|
||||
#define GEN_BUFFER_RGBA(name, w, h) \
|
||||
glGenTextures(1, (GLuint*)&name); \
|
||||
glBindTexture(GL_TEXTURE_2D, name); \
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, \
|
||||
GL_UNSIGNED_BYTE, 0); \
|
||||
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);
|
||||
|
||||
// Two fullscreen ping-pong textures.
|
||||
GEN_BUFFER_RGBA(m_ColourTex1, m_Width, m_Height);
|
||||
GEN_BUFFER_RGBA(m_ColourTex2, m_Width, m_Height);
|
||||
|
||||
// Textures for several blur sizes. It would be possible to reuse
|
||||
// m_BlurTex2b, thus avoiding the need for m_BlurTex4b and m_BlurTex8b, though given
|
||||
// that these are fairly small it's probably not worth complicating the coordinates passed
|
||||
// to the blur helper functions.
|
||||
GEN_BUFFER_RGBA(m_BlurTex2a, m_Width / 2, m_Height / 2);
|
||||
GEN_BUFFER_RGBA(m_BlurTex2b, m_Width / 2, m_Height / 2);
|
||||
|
||||
GEN_BUFFER_RGBA(m_BlurTex4a, m_Width / 4, m_Height / 4);
|
||||
GEN_BUFFER_RGBA(m_BlurTex4b, m_Width / 4, m_Height / 4);
|
||||
|
||||
GEN_BUFFER_RGBA(m_BlurTex8a, m_Width / 8, m_Height / 8);
|
||||
GEN_BUFFER_RGBA(m_BlurTex8b, m_Width / 8, m_Height / 8);
|
||||
|
||||
#undef GEN_BUFFER_RGBA
|
||||
|
||||
// Allocate the Depth/Stencil texture.
|
||||
glGenTextures(1, (GLuint*)&m_DepthTex);
|
||||
glBindTexture(GL_TEXTURE_2D, m_DepthTex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_Width, m_Height,
|
||||
0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
|
||||
GL_NONE);
|
||||
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);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
// Set up the framebuffers with some initial textures.
|
||||
|
||||
pglGenFramebuffersEXT(1, &m_PingFbo);
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_ColourTex1, 0);
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0);
|
||||
|
||||
GLenum status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
{
|
||||
LOGWARNING(L"Framebuffer object incomplete (A): 0x%04X", status);
|
||||
}
|
||||
|
||||
pglGenFramebuffersEXT(1, &m_PongFbo);
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_ColourTex2, 0);
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0);
|
||||
|
||||
status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
{
|
||||
LOGWARNING(L"Framebuffer object incomplete (B): 0x%04X", status);
|
||||
}
|
||||
|
||||
pglGenFramebuffersEXT(1, &m_BloomFbo);
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_BloomFbo);
|
||||
/*pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_BloomTex1, 0);
|
||||
|
||||
status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
{
|
||||
LOGWARNING(L"Framebuffer object incomplete (B): 0x%04X", status);
|
||||
}*/
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
|
||||
void CPostprocManager::ApplyBlurDownscale2x(GLuint inTex, GLuint outTex, int inWidth, int inHeight)
|
||||
{
|
||||
// Bind inTex to framebuffer for rendering.
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_BloomFbo);
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, outTex, 0);
|
||||
|
||||
// Get bloom shader with instructions to simply copy texels.
|
||||
CShaderDefines defines;
|
||||
defines.Add("BLOOM_NOP", "1");
|
||||
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("bloom"),
|
||||
g_Renderer.GetSystemShaderDefines(), defines);
|
||||
|
||||
tech->BeginPass();
|
||||
CShaderProgramPtr shader = tech->GetShader();
|
||||
|
||||
GLuint renderedTex = inTex;
|
||||
|
||||
// Cheat by creating high quality mipmaps for inTex, so the copying operation actually
|
||||
// produces good scaling due to hardware filtering.
|
||||
glBindTexture(GL_TEXTURE_2D, renderedTex);
|
||||
pglGenerateMipmapEXT(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
shader->BindTexture("renderedTex", renderedTex);
|
||||
|
||||
glPushAttrib(GL_VIEWPORT_BIT);
|
||||
glViewport(0, 0, inWidth / 2, inHeight / 2);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor4f(1.f, 1.f, 1.f, 1.f);
|
||||
glTexCoord2f(1.0, 1.0); glVertex2f(1,1);
|
||||
glTexCoord2f(0.0, 1.0); glVertex2f(-1,1);
|
||||
glTexCoord2f(0.0, 0.0); glVertex2f(-1,-1);
|
||||
glTexCoord2f(1.0, 0.0); glVertex2f(1,-1);
|
||||
glEnd();
|
||||
|
||||
glPopAttrib();
|
||||
tech->EndPass();
|
||||
}
|
||||
|
||||
void CPostprocManager::ApplyBlurGauss(GLuint inOutTex, GLuint tempTex, int inWidth, int inHeight)
|
||||
{
|
||||
// Set tempTex as our rendering target.
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_BloomFbo);
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tempTex, 0);
|
||||
|
||||
// Get bloom shader, for a horizontal Gaussian blur pass.
|
||||
CShaderDefines defines2;
|
||||
defines2.Add("BLOOM_PASS_H", "1");
|
||||
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("bloom"),
|
||||
g_Renderer.GetSystemShaderDefines(), defines2);
|
||||
|
||||
tech->BeginPass();
|
||||
CShaderProgramPtr shader = tech->GetShader();
|
||||
shader->BindTexture("renderedTex", inOutTex);
|
||||
shader->Uniform("texSize", inWidth, inHeight, 0.0f, 0.0f);
|
||||
|
||||
glPushAttrib(GL_VIEWPORT_BIT);
|
||||
glViewport(0, 0, inWidth, inHeight);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor4f(1.f, 1.f, 1.f, 1.f);
|
||||
glTexCoord2f(1.0, 1.0); glVertex2f(1,1);
|
||||
glTexCoord2f(0.0, 1.0); glVertex2f(-1,1);
|
||||
glTexCoord2f(0.0, 0.0); glVertex2f(-1,-1);
|
||||
glTexCoord2f(1.0, 0.0); glVertex2f(1,-1);
|
||||
glEnd();
|
||||
|
||||
glPopAttrib();
|
||||
tech->EndPass();
|
||||
|
||||
// Set result texture as our render target.
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_BloomFbo);
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, inOutTex, 0);
|
||||
|
||||
// Get bloom shader, for a vertical Gaussian blur pass.
|
||||
CShaderDefines defines3;
|
||||
defines3.Add("BLOOM_PASS_V", "1");
|
||||
tech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("bloom"),
|
||||
g_Renderer.GetSystemShaderDefines(), defines3);
|
||||
|
||||
tech->BeginPass();
|
||||
shader = tech->GetShader();
|
||||
|
||||
// Our input texture to the shader is the output of the horizontal pass.
|
||||
shader->BindTexture("renderedTex", tempTex);
|
||||
shader->Uniform("texSize", inWidth, inHeight, 0.0f, 0.0f);
|
||||
|
||||
glPushAttrib(GL_VIEWPORT_BIT);
|
||||
glViewport(0, 0, inWidth, inHeight);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor4f(1.f, 1.f, 1.f, 1.f);
|
||||
glTexCoord2f(1.0, 1.0); glVertex2f(1,1);
|
||||
glTexCoord2f(0.0, 1.0); glVertex2f(-1,1);
|
||||
glTexCoord2f(0.0, 0.0); glVertex2f(-1,-1);
|
||||
glTexCoord2f(1.0, 0.0); glVertex2f(1,-1);
|
||||
glEnd();
|
||||
|
||||
glPopAttrib();
|
||||
tech->EndPass();
|
||||
}
|
||||
|
||||
void CPostprocManager::ApplyBlur()
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
GLint originalFBO;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &originalFBO);
|
||||
|
||||
int width = m_Width, height = m_Height;
|
||||
|
||||
#define SCALE_AND_BLUR(tex1, tex2, temptex) \
|
||||
ApplyBlurDownscale2x(tex1, tex2, width, height); \
|
||||
width /= 2; \
|
||||
height /= 2; \
|
||||
ApplyBlurGauss(tex2, temptex, width, height);
|
||||
|
||||
// We do the same thing for each scale, incrementally adding more and more blur.
|
||||
SCALE_AND_BLUR(m_WhichBuffer ? m_ColourTex1 : m_ColourTex2, m_BlurTex2a, m_BlurTex2b);
|
||||
SCALE_AND_BLUR(m_BlurTex2a, m_BlurTex4a, m_BlurTex4b);
|
||||
SCALE_AND_BLUR(m_BlurTex4a, m_BlurTex8a, m_BlurTex8b);
|
||||
|
||||
#undef SCALE_AND_BLUR
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, originalFBO);
|
||||
}
|
||||
|
||||
|
||||
void CPostprocManager::CaptureRenderOutput()
|
||||
{
|
||||
// clear both FBOs and leave m_PingFbo selected for rendering;
|
||||
// m_WhichBuffer stays true at this point
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
|
||||
pglDrawBuffers(1, buffers);
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
pglDrawBuffers(1, buffers);
|
||||
|
||||
m_WhichBuffer = true;
|
||||
}
|
||||
|
||||
|
||||
void CPostprocManager::ReleaseRenderOutput()
|
||||
{
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
// we blit to screen from the previous active buffer
|
||||
if (m_WhichBuffer)
|
||||
pglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_PingFbo);
|
||||
else
|
||||
pglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_PongFbo);
|
||||
|
||||
pglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
|
||||
pglBlitFramebufferEXT(0, 0, m_Width, m_Height, 0, 0, m_Width, m_Height,
|
||||
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
|
||||
pglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
|
||||
void CPostprocManager::LoadEffect(CStrW &name)
|
||||
{
|
||||
if (!m_IsInitialised)
|
||||
return;
|
||||
|
||||
if (name != L"default")
|
||||
{
|
||||
CStrW n = L"postproc/" + name;
|
||||
m_PostProcTech = g_Renderer.GetShaderManager().LoadEffect(n.ToUTF8().c_str());
|
||||
}
|
||||
|
||||
m_PostProcEffect = name;
|
||||
}
|
||||
|
||||
|
||||
void CPostprocManager::ApplyEffect(CShaderTechniquePtr &shaderTech1, int pass)
|
||||
{
|
||||
// select the other FBO for rendering
|
||||
if (!m_WhichBuffer)
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
|
||||
else
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
shaderTech1->BeginPass(pass);
|
||||
CShaderProgramPtr shader = shaderTech1->GetShader(pass);
|
||||
|
||||
shader->Bind();
|
||||
|
||||
// Use the textures from the current FBO as input to the shader.
|
||||
// We also bind a bunch of other textures and parameters, but since
|
||||
// this only happens once per frame the overhead is negligible.
|
||||
if (m_WhichBuffer)
|
||||
shader->BindTexture("renderedTex", m_ColourTex1);
|
||||
else
|
||||
shader->BindTexture("renderedTex", m_ColourTex2);
|
||||
|
||||
shader->BindTexture("depthTex", m_DepthTex);
|
||||
|
||||
shader->BindTexture("blurTex2", m_BlurTex2a);
|
||||
shader->BindTexture("blurTex4", m_BlurTex4a);
|
||||
shader->BindTexture("blurTex8", m_BlurTex8a);
|
||||
|
||||
shader->Uniform("width", m_Width);
|
||||
shader->Uniform("height", m_Height);
|
||||
shader->Uniform("zNear", g_Game->GetView()->GetNear());
|
||||
shader->Uniform("zFar", g_Game->GetView()->GetFar());
|
||||
|
||||
shader->Uniform("brightness", g_LightEnv.m_Brightness);
|
||||
shader->Uniform("hdr", g_LightEnv.m_Contrast);
|
||||
shader->Uniform("saturation", g_LightEnv.m_Saturation);
|
||||
shader->Uniform("bloom", g_LightEnv.m_Bloom);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor4f(1.f, 1.f, 1.f, 1.f);
|
||||
glTexCoord2f(1.0, 1.0); glVertex2f(1,1);
|
||||
glTexCoord2f(0.0, 1.0); glVertex2f(-1,1);
|
||||
glTexCoord2f(0.0, 0.0); glVertex2f(-1,-1);
|
||||
glTexCoord2f(1.0, 0.0); glVertex2f(1,-1);
|
||||
glEnd();
|
||||
|
||||
shader->Unbind();
|
||||
|
||||
shaderTech1->EndPass(pass);
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
m_WhichBuffer = !m_WhichBuffer;
|
||||
}
|
||||
|
||||
void CPostprocManager::ApplyPostproc()
|
||||
{
|
||||
if (!m_IsInitialised)
|
||||
return;
|
||||
|
||||
// Don't do anything if we are using the default effect.
|
||||
if (m_PostProcEffect == L"default")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, 0);
|
||||
|
||||
GLenum buffers[] = { GL_COLOR_ATTACHMENT0 };
|
||||
pglDrawBuffers(1, buffers);
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, 0);
|
||||
pglDrawBuffers(1, buffers);
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
||||
|
||||
// First render blur textures. Note that this only happens ONLY ONCE, before any effects are applied!
|
||||
// (This may need to change depending on future usage, however that will have a fps hit)
|
||||
ApplyBlur();
|
||||
|
||||
for (int pass = 0; pass < m_PostProcTech->GetNumPasses(); ++pass)
|
||||
{
|
||||
ApplyEffect(m_PostProcTech, pass);
|
||||
}
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0);
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0);
|
||||
}
|
||||
|
||||
|
||||
// Generate list of available effect-sets
|
||||
std::vector<CStrW> CPostprocManager::GetPostEffects() const
|
||||
{
|
||||
std::vector<CStrW> effects;
|
||||
|
||||
const VfsPath path(L"shaders/effects/postproc/");
|
||||
|
||||
VfsPaths pathnames;
|
||||
if(vfs::GetPathnames(g_VFS, path, 0, pathnames) < 0)
|
||||
{
|
||||
LOGERROR(L"Error finding Post effects in '%ls'", path.string().c_str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < pathnames.size(); i++)
|
||||
{
|
||||
if (pathnames[i].Extension() != L".xml")
|
||||
continue;
|
||||
|
||||
effects.push_back(pathnames[i].Basename().string());
|
||||
}
|
||||
|
||||
// Add the default "null" effect to the list.
|
||||
effects.push_back(L"default");
|
||||
|
||||
sort(effects.begin(), effects.end());
|
||||
|
||||
return effects;
|
||||
}
|
||||
|
||||
void CPostprocManager::SetPostEffect(CStrW name)
|
||||
{
|
||||
LoadEffect(name);
|
||||
}
|
115
source/renderer/PostprocManager.h
Normal file
115
source/renderer/PostprocManager.h
Normal file
@ -0,0 +1,115 @@
|
||||
/* Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_POSTPROCMANAGER
|
||||
#define INCLUDED_POSTPROCMANAGER
|
||||
|
||||
|
||||
#include "graphics/ShaderTechnique.h"
|
||||
|
||||
class CPostprocManager
|
||||
{
|
||||
private:
|
||||
|
||||
// Two framebuffers, that we flip between at each shader pass.
|
||||
GLuint m_PingFbo, m_PongFbo;
|
||||
|
||||
// Unique colour textures for the framebuffers.
|
||||
GLuint m_ColourTex1, m_ColourTex2;
|
||||
|
||||
// The framebuffers share a depth/stencil texture.
|
||||
GLuint m_DepthTex;
|
||||
|
||||
// A framebuffer and textures x2 for each blur level we render.
|
||||
GLuint m_BloomFbo, m_BlurTex2a, m_BlurTex2b, m_BlurTex4a, m_BlurTex4b, m_BlurTex8a, m_BlurTex8b;
|
||||
|
||||
// Indicates which of the ping-pong buffers is used for reading and which for drawing.
|
||||
bool m_WhichBuffer;
|
||||
|
||||
// The name and shader technique we are using. "default" name means no technique is used
|
||||
// (i.e. while we do allocate the buffers, no effects are rendered).
|
||||
CStrW m_PostProcEffect;
|
||||
CShaderTechniquePtr m_PostProcTech;
|
||||
|
||||
// The current screen dimensions in pixels.
|
||||
int m_Width, m_Height;
|
||||
|
||||
// Is the postproc manager initialised? Buffers created? Default effect loaded?
|
||||
bool m_IsInitialised;
|
||||
|
||||
// Creates blur textures at various scales, for bloom, DOF, etc.
|
||||
void ApplyBlur();
|
||||
|
||||
// High quality GPU image scaling to half size. outTex must have exactly half the size
|
||||
// of inTex. inWidth and inHeight are the dimensions of inTex in texels.
|
||||
void ApplyBlurDownscale2x(GLuint inTex, GLuint outTex, int inWidth, int inHeight);
|
||||
|
||||
// GPU-based Gaussian blur in two passes. inOutTex contains the input image and will be filled
|
||||
// with the blurred image. tempTex must have the same size as inOutTex.
|
||||
// inWidth and inHeight are the dimensions of the images in texels.
|
||||
void ApplyBlurGauss(GLuint inOutTex, GLuint tempTex, int inWidth, int inHeight);
|
||||
|
||||
// Applies a pass of a given effect to the entire current framebuffer. The shader is
|
||||
// provided with a number of general-purpose variables, including the rendered screen so far,
|
||||
// the depth buffer, a number of blur textures, the screen size, the zNear/zFar planes and
|
||||
// some other parameters used by the optional bloom/HDR pass.
|
||||
void ApplyEffect(CShaderTechniquePtr &shaderTech1, int pass);
|
||||
|
||||
public:
|
||||
CPostprocManager();
|
||||
~CPostprocManager();
|
||||
|
||||
// Create all buffers/textures in GPU memory and set default effect.
|
||||
void Initialize();
|
||||
|
||||
// Delete all allocated buffers/textures from GPU memory.
|
||||
void Cleanup();
|
||||
|
||||
// Delete existing buffers/textures and create them again, using a new screen size if needed.
|
||||
// (the textures are also attached to the framebuffers)
|
||||
void RecreateBuffers();
|
||||
|
||||
// Loads a new postproc effect. "default" effect does NOT load anything.
|
||||
void LoadEffect(CStrW &name);
|
||||
|
||||
// Returns a list of xml files found in shaders/effects/postproc.
|
||||
std::vector<CStrW> GetPostEffects() const;
|
||||
|
||||
// Returns the name of the current effect.
|
||||
inline const CStrW& GetPostEffect() const
|
||||
{
|
||||
return m_PostProcEffect;
|
||||
}
|
||||
|
||||
// Matching setter that calls LoadEffect.
|
||||
void SetPostEffect(CStrW name);
|
||||
|
||||
// Clears the two colour buffers and depth buffer, and redirects all rendering
|
||||
// to our textures instead of directly to the system framebuffer.
|
||||
void CaptureRenderOutput();
|
||||
|
||||
// First renders blur textures, then calls ApplyEffect for each effect pass,
|
||||
// ping-ponging the buffers at each step.
|
||||
void ApplyPostproc();
|
||||
|
||||
// Blits the final postprocessed texture to the system framebuffer. The system framebuffer
|
||||
// is selected as the output buffer. Should be called before silhouette rendering.
|
||||
void ReleaseRenderOutput();
|
||||
};
|
||||
|
||||
|
||||
#endif //INCLUDED_POSTPROCMANAGER
|
@ -90,6 +90,9 @@ void ShaderRenderModifier::BeginPass(const CShaderProgramPtr& shader)
|
||||
shader->Uniform("ambient", GetLightEnv()->m_UnitsAmbientColor);
|
||||
shader->Uniform("sunDir", GetLightEnv()->GetSunDir());
|
||||
shader->Uniform("sunColor", GetLightEnv()->m_SunColor);
|
||||
|
||||
shader->Uniform("fogColor", GetLightEnv()->m_FogColor);
|
||||
shader->Uniform("fogParams", GetLightEnv()->m_FogFactor, GetLightEnv()->m_FogMax, 0.f, 0.f);
|
||||
}
|
||||
|
||||
if (shader->GetTextureBinding("losTex").Active())
|
||||
|
@ -276,6 +276,9 @@ public:
|
||||
|
||||
/// Shadow map
|
||||
ShadowMap shadow;
|
||||
|
||||
/// Postprocessing effect manager
|
||||
CPostprocManager postprocManager;
|
||||
|
||||
/// Various model renderers
|
||||
struct Models
|
||||
@ -437,6 +440,7 @@ CRenderer::CRenderer()
|
||||
m_Options.m_GPUSkinning = false;
|
||||
m_Options.m_GenTangents = false;
|
||||
m_Options.m_SmoothLOS = false;
|
||||
m_Options.m_Postproc = false;
|
||||
m_Options.m_ShowSky = false;
|
||||
|
||||
// TODO: be more consistent in use of the config system
|
||||
@ -445,6 +449,7 @@ CRenderer::CRenderer()
|
||||
CFG_GET_USER_VAL("gpuskinning", Bool, m_Options.m_GPUSkinning);
|
||||
CFG_GET_USER_VAL("gentangents", Bool, m_Options.m_GenTangents);
|
||||
CFG_GET_USER_VAL("smoothlos", Bool, m_Options.m_SmoothLOS);
|
||||
CFG_GET_USER_VAL("postproc", Bool, m_Options.m_Postproc);
|
||||
|
||||
#if CONFIG2_GLES
|
||||
// Override config option since GLES only supports GLSL
|
||||
@ -642,6 +647,9 @@ bool CRenderer::Open(int width, int height)
|
||||
// Let component renderers perform one-time initialization after graphics capabilities and
|
||||
// the shader path have been determined.
|
||||
m->overlayRenderer.Initialize();
|
||||
|
||||
if (m_Options.m_Postproc)
|
||||
m->postprocManager.Initialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -654,6 +662,9 @@ void CRenderer::Resize(int width,int height)
|
||||
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
|
||||
if (m_Options.m_Postproc)
|
||||
m->postprocManager.RecreateBuffers();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -1376,6 +1387,9 @@ void CRenderer::RenderSubmissions()
|
||||
PROFILE3("render submissions");
|
||||
|
||||
GetScene().GetLOSTexture().InterpolateLOS();
|
||||
|
||||
if (m_Options.m_Postproc)
|
||||
m->postprocManager.CaptureRenderOutput();
|
||||
|
||||
CShaderDefines context = m->globalContext;
|
||||
|
||||
@ -1495,6 +1509,12 @@ void CRenderer::RenderSubmissions()
|
||||
RenderParticles();
|
||||
ogl_WarnIfError();
|
||||
}
|
||||
|
||||
if (m_Options.m_Postproc)
|
||||
{
|
||||
m->postprocManager.ApplyPostproc();
|
||||
m->postprocManager.ReleaseRenderOutput();
|
||||
}
|
||||
|
||||
if (m_Options.m_Silhouettes)
|
||||
{
|
||||
@ -1519,6 +1539,7 @@ void CRenderer::RenderSubmissions()
|
||||
// render overlays that should appear on top of all other objects
|
||||
m->overlayRenderer.RenderForegroundOverlays(m_ViewCamera);
|
||||
ogl_WarnIfError();
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -2035,3 +2056,8 @@ CMaterialManager& CRenderer::GetMaterialManager()
|
||||
{
|
||||
return m->materialManager;
|
||||
}
|
||||
|
||||
CPostprocManager& CRenderer::GetPostprocManager()
|
||||
{
|
||||
return m->postprocManager;
|
||||
}
|
@ -30,6 +30,7 @@
|
||||
#include "ps/Singleton.h"
|
||||
#include "scripting/ScriptableObject.h"
|
||||
|
||||
#include "renderer/PostprocManager.h"
|
||||
#include "renderer/Scene.h"
|
||||
#include "renderer/TimeManager.h"
|
||||
|
||||
@ -135,6 +136,7 @@ public:
|
||||
bool m_GenTangents;
|
||||
bool m_SmoothLOS;
|
||||
bool m_ShowSky;
|
||||
bool m_Postproc;
|
||||
} m_Options;
|
||||
|
||||
struct Caps {
|
||||
@ -291,6 +293,8 @@ public:
|
||||
CShaderDefines GetSystemShaderDefines();
|
||||
|
||||
CTimeManager& GetTimeManager();
|
||||
|
||||
CPostprocManager& GetPostprocManager();
|
||||
|
||||
/**
|
||||
* GetCapabilities: Return which OpenGL capabilities are available and enabled.
|
||||
|
@ -83,6 +83,9 @@ struct ShadowMapInternals
|
||||
// Copy of renderer's standard view camera, saved between
|
||||
// BeginRender and EndRender while we replace it with the shadow camera
|
||||
CCamera SavedViewCamera;
|
||||
|
||||
// Save the caller's FBO so it can be restored
|
||||
GLint SavedViewFBO;
|
||||
|
||||
// Helper functions
|
||||
void CalcShadowMatrices();
|
||||
@ -318,6 +321,9 @@ void ShadowMapInternals::CreateTexture()
|
||||
pglDeleteFramebuffersEXT(1, &Framebuffer);
|
||||
Framebuffer = 0;
|
||||
}
|
||||
|
||||
// save the caller's FBO
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &SavedViewFBO);
|
||||
|
||||
pglGenFramebuffersEXT(1, &Framebuffer);
|
||||
|
||||
@ -433,7 +439,7 @@ void ShadowMapInternals::CreateTexture()
|
||||
|
||||
GLenum status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, SavedViewFBO);
|
||||
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
{
|
||||
@ -450,6 +456,9 @@ void ShadowMapInternals::CreateTexture()
|
||||
void ShadowMap::BeginRender()
|
||||
{
|
||||
// HACK HACK: this depends in non-obvious ways on the behaviour of the caller
|
||||
|
||||
// save caller's FBO
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m->SavedViewFBO);
|
||||
|
||||
// Calc remaining shadow matrices
|
||||
m->CalcShadowMatrices();
|
||||
@ -502,7 +511,7 @@ void ShadowMap::EndRender()
|
||||
|
||||
{
|
||||
PROFILE("unbind framebuffer");
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m->SavedViewFBO);
|
||||
}
|
||||
|
||||
glViewport(0, 0, g_Renderer.GetWidth(), g_Renderer.GetHeight());
|
||||
|
@ -487,6 +487,9 @@ void TerrainRenderer::PrepareShader(const CShaderProgramPtr& shader, ShadowMap*
|
||||
|
||||
shader->Uniform("ambient", lightEnv.m_TerrainAmbientColor);
|
||||
shader->Uniform("sunColor", lightEnv.m_SunColor);
|
||||
|
||||
shader->Uniform("fogColor", lightEnv.m_FogColor);
|
||||
shader->Uniform("fogParams", lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
|
||||
}
|
||||
|
||||
void TerrainRenderer::RenderTerrainShader(const CShaderDefines& context, ShadowMap* shadow, bool filtered)
|
||||
@ -702,6 +705,8 @@ bool TerrainRenderer::RenderFancyWater()
|
||||
m->fancyWaterShader->Uniform("refractionMatrix", WaterMgr->m_RefractionMatrix);
|
||||
m->fancyWaterShader->Uniform("losMatrix", losTexture.GetTextureMatrix());
|
||||
m->fancyWaterShader->Uniform("cameraPos", camPos);
|
||||
m->fancyWaterShader->Uniform("fogColor", lightEnv.m_FogColor);
|
||||
m->fancyWaterShader->Uniform("fogParams", lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
|
||||
|
||||
for (size_t i = 0; i < m->visiblePatches.size(); ++i)
|
||||
{
|
||||
|
@ -385,7 +385,7 @@ void CSimulation2Impl::Update(int turnLength, const std::vector<SimulationComman
|
||||
|
||||
VfsPath mapfilename(VfsPath("maps/scenarios") / (mapFile + L".pmp"));
|
||||
mapReader->LoadMap(mapfilename, &secondaryTerrain, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, &secondaryContext, INVALID_PLAYER, true); // throws exception on failure
|
||||
NULL, NULL, &secondaryContext, INVALID_PLAYER, true); // throws exception on failure
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -68,7 +68,7 @@ public:
|
||||
CMapReader* mapReader = new CMapReader(); // it'll call "delete this" itself
|
||||
|
||||
LDR_BeginRegistering();
|
||||
mapReader->LoadMap(L"maps/scenarios/Median Oasis.pmp", &terrain, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
mapReader->LoadMap(L"maps/scenarios/Median Oasis.pmp", &terrain, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
&sim2, &sim2.GetSimContext(), -1, false);
|
||||
LDR_EndRegistering();
|
||||
TS_ASSERT_OK(LDR_NonprogressiveLoad());
|
||||
|
@ -506,7 +506,7 @@ public:
|
||||
CMapReader* mapReader = new CMapReader(); // it'll call "delete this" itself
|
||||
|
||||
LDR_BeginRegistering();
|
||||
mapReader->LoadMap(L"maps/scenarios/Latium.pmp", &terrain, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
mapReader->LoadMap(L"maps/scenarios/Latium.pmp", &terrain, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
&sim2, &sim2.GetSimContext(), -1, false);
|
||||
LDR_EndRegistering();
|
||||
TS_ASSERT_OK(LDR_NonprogressiveLoad());
|
||||
|
@ -227,13 +227,29 @@ EnvironmentSidebar::EnvironmentSidebar(ScenarioEditor& scenarioEditor, wxWindow*
|
||||
sunSizer->Add(new VariableSliderBox(this, _("Sun elevation"), g_EnvironmentSettings.sunelevation, -M_PIf/2, M_PIf/2), wxSizerFlags().Expand());
|
||||
sunSizer->Add(new VariableSliderBox(this, _("Sun overbrightness"), g_EnvironmentSettings.sunoverbrightness, 1.0f, 3.0f), wxSizerFlags().Expand());
|
||||
|
||||
sunSizer->Add(m_LightingModelList = new VariableListBox(this, _("Light model"), g_EnvironmentSettings.lightingmodel), wxSizerFlags().Expand());
|
||||
sunSizer->Add(m_PostEffectList = new VariableListBox(this, _("Post Effect"), g_EnvironmentSettings.posteffect), wxSizerFlags().Expand());
|
||||
|
||||
wxSizer* fogSizer = new wxGridSizer(2);
|
||||
m_MainSizer->Add(fogSizer, wxSizerFlags().Expand().Border(wxTOP, 8));
|
||||
|
||||
fogSizer->Add(new VariableSliderBox(this, _("Fog Factor"), g_EnvironmentSettings.fogfactor, 0.0, 0.01), wxSizerFlags().Expand());
|
||||
fogSizer->Add(new VariableSliderBox(this, _("Fog Thickness"), g_EnvironmentSettings.fogmax, 0.5, 0.0), wxSizerFlags().Expand());
|
||||
|
||||
m_MainSizer->Add(new LightControl(this, wxSize(150, 150), g_EnvironmentSettings));
|
||||
m_MainSizer->Add(m_SkyList = new VariableListBox(this, _("Sky set"), g_EnvironmentSettings.skyset), wxSizerFlags().Expand());
|
||||
|
||||
wxSizer* SSSizer = new wxGridSizer(2);
|
||||
m_MainSizer->Add(SSSizer, wxSizerFlags().Expand().Border(wxTOP, 8));
|
||||
|
||||
SSSizer->Add(new VariableSliderBox(this, _("Brightness"), g_EnvironmentSettings.brightness, -0.5, 0.5), wxSizerFlags().Expand());
|
||||
SSSizer->Add(new VariableSliderBox(this, _("Contrast (HDR)"), g_EnvironmentSettings.contrast, 0.5, 1.5), wxSizerFlags().Expand());
|
||||
SSSizer->Add(new VariableSliderBox(this, _("Saturation"), g_EnvironmentSettings.saturation, 0.0, 1.0), wxSizerFlags().Expand());
|
||||
SSSizer->Add(new VariableSliderBox(this, _("Bloom"), g_EnvironmentSettings.bloom, 0.2, 0.0), wxSizerFlags().Expand());
|
||||
|
||||
m_MainSizer->Add(new VariableColourBox(this, _("Sun colour"), g_EnvironmentSettings.suncolour), wxSizerFlags().Expand());
|
||||
m_MainSizer->Add(new VariableColourBox(this, _("Terrain ambient colour"), g_EnvironmentSettings.terraincolour), wxSizerFlags().Expand());
|
||||
m_MainSizer->Add(new VariableColourBox(this, _("Object ambient colour"), g_EnvironmentSettings.unitcolour), wxSizerFlags().Expand());
|
||||
m_MainSizer->Add(new VariableColourBox(this, _("Fog colour"), g_EnvironmentSettings.fogcolour), wxSizerFlags().Expand());
|
||||
|
||||
m_Conn = g_EnvironmentSettings.RegisterObserver(0, &SendToGame);
|
||||
}
|
||||
@ -245,17 +261,15 @@ void EnvironmentSidebar::OnFirstDisplay()
|
||||
AtlasMessage::qGetSkySets qry_skysets;
|
||||
qry_skysets.Post();
|
||||
m_SkyList->SetChoices(*qry_skysets.skysets);
|
||||
|
||||
AtlasMessage::qGetPostEffects qry_effects;
|
||||
qry_effects.Post();
|
||||
m_PostEffectList->SetChoices(*qry_effects.posteffects);
|
||||
|
||||
AtlasMessage::qGetEnvironmentSettings qry_env;
|
||||
qry_env.Post();
|
||||
g_EnvironmentSettings = qry_env.settings;
|
||||
|
||||
|
||||
std::vector<std::wstring> lightingModels;
|
||||
lightingModels.push_back(L"standard");
|
||||
m_LightingModelList->SetChoices(lightingModels);
|
||||
|
||||
|
||||
g_EnvironmentSettings.NotifyObservers();
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ protected:
|
||||
virtual void OnFirstDisplay();
|
||||
|
||||
private:
|
||||
VariableListBox* m_LightingModelList;
|
||||
VariableListBox* m_PostEffectList;
|
||||
VariableListBox* m_SkyList;
|
||||
ObservableScopedConnection m_Conn;
|
||||
};
|
||||
|
@ -61,10 +61,18 @@ sEnvironmentSettings GetSettings()
|
||||
sunrotation -= (float)M_PI*2;
|
||||
s.sunrotation = sunrotation;
|
||||
s.sunelevation = g_LightEnv.GetElevation();
|
||||
|
||||
s.lightingmodel = CStr(g_LightEnv.GetLightingModel()).FromUTF8();
|
||||
|
||||
s.posteffect = g_Renderer.GetPostprocManager().GetPostEffect();
|
||||
|
||||
s.skyset = g_Renderer.GetSkyManager()->GetSkySet();
|
||||
|
||||
s.fogfactor = g_LightEnv.m_FogFactor;
|
||||
s.fogmax = g_LightEnv.m_FogMax;
|
||||
|
||||
s.brightness = g_LightEnv.m_Brightness;
|
||||
s.contrast = g_LightEnv.m_Contrast;
|
||||
s.saturation = g_LightEnv.m_Saturation;
|
||||
s.bloom = g_LightEnv.m_Bloom;
|
||||
|
||||
// RGBColor (CVector3D) colours
|
||||
#define COLOUR(A, B) A = Colour((int)(B.X*255), (int)(B.Y*255), (int)(B.Z*255))
|
||||
@ -78,6 +86,7 @@ sEnvironmentSettings GetSettings()
|
||||
COLOUR(s.suncolour, g_LightEnv.m_SunColor);
|
||||
COLOUR(s.terraincolour, g_LightEnv.m_TerrainAmbientColor);
|
||||
COLOUR(s.unitcolour, g_LightEnv.m_UnitsAmbientColor);
|
||||
COLOUR(s.fogcolour, g_LightEnv.m_FogColor);
|
||||
#undef COLOUR
|
||||
|
||||
return s;
|
||||
@ -104,19 +113,31 @@ void SetSettings(const sEnvironmentSettings& s)
|
||||
|
||||
g_LightEnv.SetRotation(s.sunrotation);
|
||||
g_LightEnv.SetElevation(s.sunelevation);
|
||||
|
||||
g_LightEnv.SetLightingModel(CStrW(*s.lightingmodel).ToUTF8());
|
||||
|
||||
CStrW posteffect = *s.posteffect;
|
||||
if (posteffect.length() == 0)
|
||||
posteffect = L"default";
|
||||
g_Renderer.GetPostprocManager().SetPostEffect(posteffect);
|
||||
|
||||
CStrW skySet = *s.skyset;
|
||||
if (skySet.length() == 0)
|
||||
skySet = L"default";
|
||||
g_Renderer.GetSkyManager()->SetSkySet(skySet);
|
||||
|
||||
g_LightEnv.m_FogFactor = s.fogfactor;
|
||||
g_LightEnv.m_FogMax = s.fogmax;
|
||||
|
||||
g_LightEnv.m_Brightness = s.brightness;
|
||||
g_LightEnv.m_Contrast = s.contrast;
|
||||
g_LightEnv.m_Saturation = s.saturation;
|
||||
g_LightEnv.m_Bloom = s.bloom;
|
||||
|
||||
#define COLOUR(A, B) B = RGBColor(A->r/255.f, A->g/255.f, A->b/255.f)
|
||||
COLOUR(s.suncolour, g_LightEnv.m_SunColor);
|
||||
g_LightEnv.m_SunColor *= s.sunoverbrightness;
|
||||
COLOUR(s.terraincolour, g_LightEnv.m_TerrainAmbientColor);
|
||||
COLOUR(s.unitcolour, g_LightEnv.m_UnitsAmbientColor);
|
||||
COLOUR(s.fogcolour, g_LightEnv.m_FogColor);
|
||||
#undef COLOUR
|
||||
}
|
||||
|
||||
@ -159,4 +180,11 @@ QUERYHANDLER(GetSkySets)
|
||||
msg->skysets = std::vector<std::wstring>(skies.begin(), skies.end());
|
||||
}
|
||||
|
||||
|
||||
QUERYHANDLER(GetPostEffects)
|
||||
{
|
||||
std::vector<CStrW> effects = g_Renderer.GetPostprocManager().GetPostEffects();
|
||||
msg->posteffects = std::vector<std::wstring>(effects.begin(), effects.end());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -231,6 +231,7 @@ MESSAGEHANDLER(SaveMap)
|
||||
g_Game->GetWorld()->GetTerrain(),
|
||||
g_Renderer.GetWaterManager(), g_Renderer.GetSkyManager(),
|
||||
&g_LightEnv, g_Game->GetView()->GetCamera(), g_Game->GetView()->GetCinema(),
|
||||
&g_Renderer.GetPostprocManager(),
|
||||
g_Game->GetSimulation2());
|
||||
}
|
||||
|
||||
|
@ -432,13 +432,22 @@ struct sEnvironmentSettings
|
||||
|
||||
// support different lighting models ("old" for the version compatible with old scenarios,
|
||||
// "standard" for the new normal model that supports much brighter lighting)
|
||||
Shareable<std::wstring> lightingmodel;
|
||||
Shareable<std::wstring> posteffect;
|
||||
|
||||
Shareable<std::wstring> skyset;
|
||||
|
||||
Shareable<Colour> suncolour;
|
||||
Shareable<Colour> terraincolour;
|
||||
Shareable<Colour> unitcolour;
|
||||
Shareable<Colour> fogcolour;
|
||||
|
||||
Shareable<float> fogfactor;
|
||||
Shareable<float> fogmax;
|
||||
|
||||
Shareable<float> brightness;
|
||||
Shareable<float> contrast;
|
||||
Shareable<float> saturation;
|
||||
Shareable<float> bloom;
|
||||
};
|
||||
SHAREABLE_STRUCT(sEnvironmentSettings);
|
||||
#endif
|
||||
@ -459,6 +468,12 @@ QUERY(GetSkySets,
|
||||
((std::vector<std::wstring>, skysets))
|
||||
);
|
||||
|
||||
QUERY(GetPostEffects,
|
||||
// no inputs
|
||||
,
|
||||
((std::vector<std::wstring>, posteffects))
|
||||
);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
Reference in New Issue
Block a user