HDR: Implement GTAO (Ground Truth Ambient Occlusion)
This commit is contained in:
parent
65c8a95dd8
commit
96a6e6c9bf
13 changed files with 341 additions and 46 deletions
13
Compositor/HDR/ao-buffer.xml
Normal file
13
Compositor/HDR/ao-buffer.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<PropertyList>
|
||||
<type>2d</type>
|
||||
<width>screen</width>
|
||||
<height>screen</height>
|
||||
<format>r8</format>
|
||||
<min-filter>linear</min-filter>
|
||||
<mag-filter>linear</mag-filter>
|
||||
<condition>
|
||||
<property>/sim/rendering/hdr/ambient-occlusion/enabled</property>
|
||||
</condition>
|
||||
</PropertyList>
|
|
@ -194,15 +194,12 @@
|
|||
<mag-filter>nearest</mag-filter>
|
||||
</buffer>
|
||||
|
||||
<!-- SSAO -->
|
||||
<buffer>
|
||||
<name>ao0</name>
|
||||
<type>2d</type>
|
||||
<width>screen</width>
|
||||
<height>screen</height>
|
||||
<screen-width-scale>0.5</screen-width-scale>
|
||||
<screen-height-scale>0.5</screen-height-scale>
|
||||
<format>r8</format>
|
||||
<!-- Ambient Occlusion buffers -->
|
||||
<buffer include="ao-buffer.xml">
|
||||
<name>ao-noisy</name>
|
||||
</buffer>
|
||||
<buffer include="ao-buffer.xml">
|
||||
<name>ao-filtered</name>
|
||||
</buffer>
|
||||
|
||||
<!-- Bloom buffers -->
|
||||
|
@ -675,6 +672,46 @@
|
|||
</attachment>
|
||||
</pass>
|
||||
|
||||
<!-- GTAO (Ground Truth Ambient Occlusion) -->
|
||||
<pass>
|
||||
<name>gtao</name>
|
||||
<type>quad</type>
|
||||
<effect>Effects/HDR/gtao</effect>
|
||||
<clear-mask>color</clear-mask>
|
||||
<clear-color type="vec4d">1.0 1.0 1.0 1.0</clear-color>
|
||||
<condition>
|
||||
<property>/sim/rendering/hdr/ambient-occlusion/enabled</property>
|
||||
</condition>
|
||||
<binding>
|
||||
<unit>0</unit>
|
||||
<buffer>gbuffer0</buffer>
|
||||
</binding>
|
||||
<binding>
|
||||
<unit>1</unit>
|
||||
<buffer>depth-stencil</buffer>
|
||||
</binding>
|
||||
<attachment>
|
||||
<component>color0</component>
|
||||
<buffer>ao-noisy</buffer>
|
||||
</attachment>
|
||||
</pass>
|
||||
<pass>
|
||||
<name>gtao-denoiser</name>
|
||||
<type>quad</type>
|
||||
<effect>Effects/HDR/gtao-denoiser</effect>
|
||||
<condition>
|
||||
<property>/sim/rendering/hdr/ambient-occlusion/enabled</property>
|
||||
</condition>
|
||||
<binding>
|
||||
<unit>0</unit>
|
||||
<buffer>ao-noisy</buffer>
|
||||
</binding>
|
||||
<attachment>
|
||||
<component>color0</component>
|
||||
<buffer>ao-filtered</buffer>
|
||||
</attachment>
|
||||
</pass>
|
||||
|
||||
<!-- Shadow mapping pre-passes -->
|
||||
<pass include="csm-pass.xml">
|
||||
<name>csm0</name>
|
||||
|
@ -721,25 +758,6 @@
|
|||
</viewport>
|
||||
</pass>
|
||||
|
||||
<!-- SSAO (Screen Space Ambient Occlusion) -->
|
||||
<pass>
|
||||
<name>ao</name>
|
||||
<type>quad</type>
|
||||
<effect>Effects/HDR/ao</effect>
|
||||
<binding>
|
||||
<unit>0</unit>
|
||||
<buffer>gbuffer0</buffer>
|
||||
</binding>
|
||||
<binding>
|
||||
<unit>1</unit>
|
||||
<buffer>depth-stencil</buffer>
|
||||
</binding>
|
||||
<attachment>
|
||||
<component>color0</component>
|
||||
<buffer>ao0</buffer>
|
||||
</attachment>
|
||||
</pass>
|
||||
|
||||
<!--
|
||||
Main lighting pass
|
||||
Combine the G-Buffer and other buffers to compute the final shading value
|
||||
|
@ -771,7 +789,10 @@
|
|||
</binding>
|
||||
<binding>
|
||||
<unit>7</unit>
|
||||
<buffer>ao0</buffer>
|
||||
<buffer>ao-filtered</buffer>
|
||||
<condition>
|
||||
<property>/sim/rendering/hdr/ambient-occlusion/enabled</property>
|
||||
</condition>
|
||||
</binding>
|
||||
<binding>
|
||||
<unit>9</unit>
|
||||
|
|
17
Effects/HDR/gtao-denoiser.eff
Normal file
17
Effects/HDR/gtao-denoiser.eff
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PropertyList>
|
||||
<name>Effects/HDR/gtao-denoiser</name>
|
||||
<technique n="1">
|
||||
<pass>
|
||||
<program>
|
||||
<vertex-shader>Shaders/HDR/trivial-notexcoord.vert</vertex-shader>
|
||||
<fragment-shader>Shaders/HDR/gtao-denoiser.frag</fragment-shader>
|
||||
</program>
|
||||
<uniform>
|
||||
<name>ao_tex</name>
|
||||
<type>sampler-2d</type>
|
||||
<value type="int">0</value>
|
||||
</uniform>
|
||||
</pass>
|
||||
</technique>
|
||||
</PropertyList>
|
37
Effects/HDR/gtao.eff
Normal file
37
Effects/HDR/gtao.eff
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PropertyList>
|
||||
<name>Effects/HDR/gtao</name>
|
||||
<parameters>
|
||||
<world-radius>
|
||||
<use>/sim/rendering/hdr/ambient-occlusion/world-radius</use>
|
||||
</world-radius>
|
||||
</parameters>
|
||||
<technique n="1">
|
||||
<pass>
|
||||
<stencil>
|
||||
<function>less-or-equal</function>
|
||||
<value>8</value>
|
||||
</stencil>
|
||||
<program>
|
||||
<vertex-shader>Shaders/HDR/trivial.vert</vertex-shader>
|
||||
<fragment-shader>Shaders/HDR/gtao.frag</fragment-shader>
|
||||
<fragment-shader>Shaders/HDR/gbuffer-include.frag</fragment-shader>
|
||||
</program>
|
||||
<uniform>
|
||||
<name>gbuffer0_tex</name>
|
||||
<type>sampler-2d</type>
|
||||
<value type="int">0</value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>depth_tex</name>
|
||||
<type>sampler-2d</type>
|
||||
<value type="int">1</value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>world_radius</name>
|
||||
<type>float</type>
|
||||
<value><use>world-radius</use></value>
|
||||
</uniform>
|
||||
</pass>
|
||||
</technique>
|
||||
</PropertyList>
|
|
@ -11,6 +11,9 @@
|
|||
<wrap-t>clamp-to-edge</wrap-t>
|
||||
<internal-format>normalized</internal-format>
|
||||
</texture>
|
||||
<ambient-occlusion-enabled>
|
||||
<use>/sim/rendering/hdr/ambient-occlusion/enabled</use>
|
||||
</ambient-occlusion-enabled>
|
||||
<show-shadow-cascades>
|
||||
<use>/sim/rendering/hdr/debug/show-shadow-cascades</use>
|
||||
</show-shadow-cascades>
|
||||
|
@ -64,6 +67,11 @@
|
|||
<type>sampler-2d</type>
|
||||
<value type="int">7</value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>ambient_occlusion_enabled</name>
|
||||
<type>bool</type>
|
||||
<value><use>ambient-occlusion-enabled</use></value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>debug_shadow_cascades</name>
|
||||
<type>bool</type>
|
||||
|
|
|
@ -31,18 +31,23 @@ vec3 decodeNormal(vec2 f)
|
|||
|
||||
// Given a 2D coordinate in the range [0,1] and a depth value from a depth
|
||||
// buffer, also in the [0,1] range, return the view space position.
|
||||
vec3 positionFromDepth(vec2 pos, float depth)
|
||||
vec3 positionFromDepth(vec2 pos, float depth, mat4 projMatrixInverse)
|
||||
{
|
||||
// We are using a reversed depth buffer. 1.0 corresponds to the near plane
|
||||
// and 0.0 to the far plane. We convert this back to clip space by doing
|
||||
// 1.0 - depth to undo the depth reversal
|
||||
// 2.0 * depth - 1.0 to transform it to clip space [-1,1]
|
||||
vec4 clipSpacePos = vec4(pos * 2.0 - 1.0, 1.0 - depth * 2.0, 1.0);
|
||||
vec4 viewSpacePos = fg_ProjectionMatrixInverse * clipSpacePos;
|
||||
vec4 viewSpacePos = projMatrixInverse * clipSpacePos;
|
||||
viewSpacePos.xyz /= viewSpacePos.w;
|
||||
return viewSpacePos.xyz;
|
||||
}
|
||||
|
||||
vec3 positionFromDepth(vec2 pos, float depth)
|
||||
{
|
||||
return positionFromDepth(pos, depth, fg_ProjectionMatrixInverse);
|
||||
}
|
||||
|
||||
// http://www.geeks3d.com/20091216/geexlab-how-to-visualize-the-depth-buffer-in-glsl/
|
||||
float linearizeDepth(float depth)
|
||||
{
|
||||
|
|
|
@ -30,7 +30,7 @@ vec3 evaluateLight(
|
|||
float roughness,
|
||||
vec3 f0,
|
||||
vec3 intensity,
|
||||
float occlusion,
|
||||
float visibility,
|
||||
vec3 n,
|
||||
vec3 l,
|
||||
vec3 v,
|
||||
|
@ -41,7 +41,7 @@ vec3 evaluateIBL(
|
|||
float metallic,
|
||||
float roughness,
|
||||
vec3 f0,
|
||||
float occlusion,
|
||||
float visibility,
|
||||
vec3 nWorldSpace,
|
||||
float NdotV,
|
||||
vec3 reflected);
|
||||
|
|
|
@ -26,7 +26,7 @@ vec3 evaluateLight(
|
|||
float roughness,
|
||||
vec3 f0,
|
||||
vec3 intensity,
|
||||
float occlusion,
|
||||
float visibility,
|
||||
vec3 n,
|
||||
vec3 l,
|
||||
vec3 v,
|
||||
|
@ -37,7 +37,7 @@ vec3 evaluateIBL(
|
|||
float metallic,
|
||||
float roughness,
|
||||
vec3 f0,
|
||||
float occlusion,
|
||||
float visibility,
|
||||
vec3 nWorldSpace,
|
||||
float NdotV,
|
||||
vec3 reflected);
|
||||
|
|
35
Shaders/HDR/gtao-denoiser.frag
Normal file
35
Shaders/HDR/gtao-denoiser.frag
Normal file
|
@ -0,0 +1,35 @@
|
|||
#version 330 core
|
||||
|
||||
out float fragColor;
|
||||
|
||||
uniform sampler2D ao_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy) - ivec2(2);
|
||||
float ao = 0.0;
|
||||
|
||||
ao += texelFetch(ao_tex, coord, 0).r;
|
||||
ao += texelFetch(ao_tex, coord + ivec2(1, 0), 0).r;
|
||||
ao += texelFetch(ao_tex, coord + ivec2(0, 1), 0).r;
|
||||
ao += texelFetch(ao_tex, coord + ivec2(1, 1), 0).r;
|
||||
|
||||
ao += texelFetch(ao_tex, coord + ivec2(2, 0), 0).r;
|
||||
ao += texelFetch(ao_tex, coord + ivec2(3, 0), 0).r;
|
||||
ao += texelFetch(ao_tex, coord + ivec2(2, 1), 0).r;
|
||||
ao += texelFetch(ao_tex, coord + ivec2(3, 1), 0).r;
|
||||
|
||||
ao += texelFetch(ao_tex, coord + ivec2(0, 2), 0).r;
|
||||
ao += texelFetch(ao_tex, coord + ivec2(1, 2), 0).r;
|
||||
ao += texelFetch(ao_tex, coord + ivec2(0, 3), 0).r;
|
||||
ao += texelFetch(ao_tex, coord + ivec2(1, 3), 0).r;
|
||||
|
||||
ao += texelFetch(ao_tex, coord + ivec2(2, 2), 0).r;
|
||||
ao += texelFetch(ao_tex, coord + ivec2(3, 2), 0).r;
|
||||
ao += texelFetch(ao_tex, coord + ivec2(2, 3), 0).r;
|
||||
ao += texelFetch(ao_tex, coord + ivec2(3, 3), 0).r;
|
||||
|
||||
ao /= 16.0;
|
||||
|
||||
fragColor = ao;
|
||||
}
|
141
Shaders/HDR/gtao.frag
Normal file
141
Shaders/HDR/gtao.frag
Normal file
|
@ -0,0 +1,141 @@
|
|||
/**
|
||||
* An implementation of GTAO (Ground Truth Ambient Occlusion)
|
||||
* Based on 'Practical Real-Time Strategies for Accurate Indirect Occlusion' by
|
||||
* Jorge Jimenez et al.
|
||||
* https://www.activision.com/cdn/research/Practical_Real_Time_Strategies_for_Accurate_Indirect_Occlusion_NEW%20VERSION_COLOR.pdf
|
||||
* https://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf
|
||||
* Most of the shader is based on Algorithm 1 of the paper.
|
||||
*/
|
||||
|
||||
#version 330 core
|
||||
|
||||
out float fragColor;
|
||||
|
||||
in vec2 texCoord;
|
||||
|
||||
uniform sampler2D gbuffer0_tex;
|
||||
uniform sampler2D depth_tex;
|
||||
|
||||
uniform float world_radius;
|
||||
|
||||
uniform vec4 fg_Viewport;
|
||||
uniform vec2 fg_PixelSize;
|
||||
uniform mat4 fg_ProjectionMatrix;
|
||||
|
||||
const float PI = 3.141592653;
|
||||
const float PI_HALF = PI * 0.5;
|
||||
const float SLICE_COUNT = 3.0;
|
||||
const float DIRECTION_SAMPLE_COUNT = 4.0;
|
||||
|
||||
vec3 decodeNormal(vec2 f);
|
||||
vec3 positionFromDepth(vec2 pos, float depth);
|
||||
|
||||
void main()
|
||||
{
|
||||
float depth = textureLod(depth_tex, texCoord, 0.0).r;
|
||||
// Ignore the background
|
||||
if (depth == 0.0) {
|
||||
fragColor = 0.0;
|
||||
discard;
|
||||
}
|
||||
// Slightly push the depth towards the camera to avoid imprecision artifacts
|
||||
depth = clamp(depth * 1.00001, 0.0, 1.0);
|
||||
|
||||
// View space normal
|
||||
vec3 normal = decodeNormal(texture(gbuffer0_tex, texCoord).rg);
|
||||
// Fragment position in view space
|
||||
vec3 pos = positionFromDepth(texCoord, depth);
|
||||
// View vector in view space
|
||||
vec3 v = normalize(-pos);
|
||||
|
||||
float noiseDirection = 0.0625 * float(
|
||||
((int(gl_FragCoord.x) + int(gl_FragCoord.y) & 3) << 2) +
|
||||
(int(gl_FragCoord.x) & 3));
|
||||
|
||||
float noiseOffset = 0.25 * float(int(gl_FragCoord.x) + int(gl_FragCoord.y) & 3);
|
||||
|
||||
// Transform the world space hemisphere radius to screen space pixels with
|
||||
// the following formula:
|
||||
// radius * 1 / [ tan(fovy / 2) * z_distance ] * (screen_size.y / 2)
|
||||
// In our case, the (1,1) element of the projection matrix contains
|
||||
// 1 / tan(fovy / 2), so we can use that directly.
|
||||
// z_distance is the distance from the camera to the fragment, which is
|
||||
// just the positive z component of the view space fragment position.
|
||||
float radiusPixels = world_radius * (fg_ProjectionMatrix[1][1] / abs(pos.z))
|
||||
* fg_Viewport.w * 0.5;
|
||||
|
||||
float visibility = 0.0;
|
||||
|
||||
for (float i = 0.0; i < SLICE_COUNT; ++i) {
|
||||
float phi = ((i + noiseDirection) / SLICE_COUNT) * PI;
|
||||
float cosPhi = cos(phi);
|
||||
float sinPhi = sin(phi);
|
||||
vec2 omega = vec2(cosPhi, sinPhi);
|
||||
|
||||
vec3 dir = vec3(omega, 0.0);
|
||||
vec3 orthoDirection = dir - dot(dir, v) * v;
|
||||
vec3 axis = normalize(cross(dir, v));
|
||||
vec3 projNormal = normal - axis * dot(normal, axis);
|
||||
float projNormalLength = max(1e-5, length(projNormal));
|
||||
|
||||
float sgnN = sign(dot(orthoDirection, projNormal));
|
||||
float cosN = clamp(dot(projNormal, v) / projNormalLength, 0.0, 1.0);
|
||||
float n = sgnN * acos(cosN);
|
||||
|
||||
float hcos1 = -1.0, hcos2 = -1.0;
|
||||
|
||||
for (float j = 0.0; j < DIRECTION_SAMPLE_COUNT; ++j) {
|
||||
float s = (j + noiseOffset) / DIRECTION_SAMPLE_COUNT;
|
||||
s += 1.2 / radiusPixels;
|
||||
vec2 sOffset = s * radiusPixels * omega;
|
||||
sOffset = round(sOffset) * fg_PixelSize;
|
||||
|
||||
vec2 sTexCoord1 = texCoord - sOffset;
|
||||
float sDepth1 = textureLod(depth_tex, sTexCoord1, 0.0).r;
|
||||
if (sDepth1 == 0.0) {
|
||||
// Skip background
|
||||
continue;
|
||||
}
|
||||
vec3 sPos1 = positionFromDepth(sTexCoord1, sDepth1);
|
||||
|
||||
vec2 sTexCoord2 = texCoord + sOffset;
|
||||
float sDepth2 = textureLod(depth_tex, sTexCoord2, 0.0).r;
|
||||
if (sDepth2 == 0.0) {
|
||||
// Skip background
|
||||
continue;
|
||||
}
|
||||
vec3 sPos2 = positionFromDepth(sTexCoord2, sDepth2);
|
||||
|
||||
vec3 sHorizon1 = sPos1 - pos;
|
||||
vec3 sHorizon2 = sPos2 - pos;
|
||||
float sHorizonLength1 = length(sHorizon1);
|
||||
float sHorizonLength2 = length(sHorizon2);
|
||||
|
||||
float shcos1 = dot(sHorizon1 / sHorizonLength1, v);
|
||||
float shcos2 = dot(sHorizon2 / sHorizonLength2, v);
|
||||
|
||||
// Section 4.3: Bounding the sampling area
|
||||
// Attenuate samples that are further away
|
||||
float weight1 = clamp((1.0 - sHorizonLength1 / world_radius) * 2.0, 0.0, 1.0);
|
||||
float weight2 = clamp((1.0 - sHorizonLength2 / world_radius) * 2.0, 0.0, 1.0);
|
||||
shcos1 = mix(-1.0, shcos1, weight1);
|
||||
shcos2 = mix(-1.0, shcos2, weight2);
|
||||
|
||||
hcos1 = max(hcos1, shcos1);
|
||||
hcos2 = max(hcos2, shcos2);
|
||||
}
|
||||
|
||||
float h1 = n + max(-acos(hcos1) - n, -PI_HALF);
|
||||
float h2 = n + min( acos(hcos2) - n, PI_HALF);
|
||||
|
||||
float sinN = sin(n);
|
||||
float h1_2 = 2.0 * h1;
|
||||
float h2_2 = 2.0 * h2;
|
||||
float vd = 0.25 * ((cosN + h1_2 * sinN - cos(h1_2 - n)) +
|
||||
(cosN + h2_2 * sinN - cos(h2_2 - n)));
|
||||
visibility += projNormalLength * vd;
|
||||
}
|
||||
visibility /= float(SLICE_COUNT);
|
||||
|
||||
fragColor = clamp(visibility, 0.0, 1.0);
|
||||
}
|
|
@ -120,7 +120,7 @@ vec3 evaluateIBL(
|
|||
float metallic,
|
||||
float roughness,
|
||||
vec3 f0, // Use getF0Reflectance() to obtain this
|
||||
float occlusion,
|
||||
float visibility,
|
||||
vec3 nWorldSpace, // Normal in world space
|
||||
float NdotV, // Must be positive and non-zero
|
||||
vec3 reflected // Reflected vector in world space: reflect(-v, n)
|
||||
|
@ -132,7 +132,7 @@ vec3 evaluateIBL(
|
|||
vec3 diffuse = evaluateDiffuseIrradianceIBL(nWorldSpace) * baseColor
|
||||
* (vec3(1.0) - f) * (1.0 - metallic);
|
||||
|
||||
return (diffuse + specular) * occlusion;
|
||||
return (diffuse + specular) * visibility;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -144,7 +144,7 @@ vec3 evaluateLight(
|
|||
float roughness,
|
||||
vec3 f0, // Use getF0Reflectance() to obtain this
|
||||
vec3 intensity,
|
||||
float occlusion,
|
||||
float visibility,
|
||||
vec3 n,
|
||||
vec3 l,
|
||||
vec3 v,
|
||||
|
@ -153,7 +153,7 @@ vec3 evaluateLight(
|
|||
)
|
||||
{
|
||||
// Skip fragments that are completely occluded or that are not facing the light
|
||||
if (occlusion <= 0.0 || NdotL <= 0.0)
|
||||
if (visibility <= 0.0 || NdotL <= 0.0)
|
||||
return vec3(0.0);
|
||||
|
||||
NdotL = clamp(NdotL, 0.001, 1.0);
|
||||
|
@ -180,6 +180,6 @@ vec3 evaluateLight(
|
|||
|
||||
vec3 material = f_diffuse + f_specular;
|
||||
|
||||
vec3 color = material * intensity * occlusion;
|
||||
vec3 color = material * intensity * visibility;
|
||||
return color;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ uniform sampler2D gbuffer2_tex;
|
|||
uniform sampler2D depth_tex;
|
||||
uniform sampler2D ao_tex;
|
||||
|
||||
uniform bool ambient_occlusion_enabled;
|
||||
uniform bool debug_shadow_cascades;
|
||||
|
||||
uniform mat4 fg_ViewMatrixInverse;
|
||||
|
@ -27,7 +28,7 @@ vec3 evaluateLight(
|
|||
float roughness,
|
||||
vec3 f0,
|
||||
vec3 intensity,
|
||||
float occlusion,
|
||||
float visibility,
|
||||
vec3 n,
|
||||
vec3 l,
|
||||
vec3 v,
|
||||
|
@ -38,13 +39,24 @@ vec3 evaluateIBL(
|
|||
float metallic,
|
||||
float roughness,
|
||||
vec3 f0,
|
||||
float occlusion,
|
||||
float visibility,
|
||||
vec3 nWorldSpace,
|
||||
float NdotV,
|
||||
vec3 reflected);
|
||||
vec3 addAerialPerspective(vec3 color, vec2 coord, float depth);
|
||||
vec3 getSunIntensity();
|
||||
|
||||
float GTAOMultiBounce(float x, vec3 albedo)
|
||||
{
|
||||
// Use luminance instead of albedo because colored multibounce looks bad
|
||||
// Idea borrowed from Blender Eevee
|
||||
float lum = dot(albedo, vec3(0.333));
|
||||
float a = 2.0404 * lum - 0.3324;
|
||||
float b = -4.7951 * lum + 0.6417;
|
||||
float c = 2.7552 * lum + 0.6903;
|
||||
return max(x, ((x * a + b) * x + c) * x);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 gbuffer0 = texture(gbuffer0_tex, texCoord);
|
||||
|
@ -67,8 +79,6 @@ void main()
|
|||
float NdotL = dot(n, l);
|
||||
float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
|
||||
|
||||
float ao = texture(ao_tex, texCoord).r;
|
||||
|
||||
vec3 f0 = getF0Reflectance(baseColor, metallic);
|
||||
|
||||
vec3 sunIlluminance = getSunIntensity() * clamp(NdotL, 0.0, 1.0);
|
||||
|
@ -83,7 +93,11 @@ void main()
|
|||
n, l, v,
|
||||
NdotL, NdotV);
|
||||
|
||||
float ambientOcclusion = ao * occlusion;
|
||||
float ao = occlusion;
|
||||
if (ambient_occlusion_enabled) {
|
||||
ao *= GTAOMultiBounce(texture(ao_tex, texCoord).r, baseColor);
|
||||
}
|
||||
|
||||
vec3 worldNormal = (fg_ViewMatrixInverse * vec4(n, 0.0)).xyz;
|
||||
vec3 worldReflected = (fg_ViewMatrixInverse * vec4(reflect(-v, n), 0.0)).xyz;
|
||||
|
||||
|
@ -91,7 +105,7 @@ void main()
|
|||
metallic,
|
||||
roughness,
|
||||
f0,
|
||||
ambientOcclusion,
|
||||
ao,
|
||||
worldNormal,
|
||||
NdotV,
|
||||
worldNormal);
|
||||
|
|
|
@ -388,6 +388,10 @@ Started September 2000 by David Megginson, david@megginson.com
|
|||
<exposure-compensation type="float">0.0</exposure-compensation>
|
||||
<bloom-magnitude type="float">0.5</bloom-magnitude>
|
||||
<bloom-threshold type="float">8.0</bloom-threshold>
|
||||
<ambient-occlusion>
|
||||
<enabled type="bool" userarchive="y">true</enabled>
|
||||
<world-radius type="float">0.2</world-radius>
|
||||
</ambient-occlusion>
|
||||
<debug>
|
||||
<display-ev100 type="bool">false</display-ev100>
|
||||
<show-gbuffer type="bool">false</show-gbuffer>
|
||||
|
|
Loading…
Add table
Reference in a new issue