Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bindings and shaders for bent normals used in ambient occlusion #6301

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions code/def_files/data/effects/deferred-clear-f.sdr
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ out vec4 fragOut2;
out vec4 fragOut3;
out vec4 fragOut4;
out vec4 fragOut5;
out vec4 fragOut6;
void main()
{
fragOut0 = vec4(0.0, 0.0, 0.0, 1.0); // color
fragOut1 = vec4(0.0, 0.0, -1000000.0, 1.0); // position
fragOut2 = vec4(0.0, 0.0, 0.0, 1.0); // normal
fragOut3 = vec4(0.0, 0.0, 0.0, 0.0); // specular
fragOut4 = vec4(0.0, 0.0, 0.0, 1.0); // emissive
fragOut5 = vec4(0.0, 0.0, 0.0, 1.0); // composite
fragOut4 = vec4(0.0, 0.0, 0.0, 1.0); // bent
fragOut5 = vec4(0.0, 0.0, 0.0, 1.0); // emissive
fragOut6 = vec4(0.0, 0.0, 0.0, 1.0); // composite
}
17 changes: 14 additions & 3 deletions code/def_files/data/effects/deferred-f.sdr
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ uniform sampler2D ColorBuffer;
uniform sampler2D NormalBuffer;
uniform sampler2D PositionBuffer;
uniform sampler2D SpecBuffer;
uniform sampler2D BentBuffer;
uniform sampler2DArray shadow_map;

layout (std140) uniform globalDeferredData {
Expand Down Expand Up @@ -168,7 +169,8 @@ void GetLightInfo(vec3 position, in float alpha, in vec3 reflectDir, out vec3 li
void main()
{
vec2 screenPos = gl_FragCoord.xy * vec2(invScreenWidth, invScreenHeight);
vec3 position = texture(PositionBuffer, screenPos).xyz;
vec4 positionBufferData = texture(PositionBuffer, screenPos);
vec3 position = positionBufferData.xyz;

if(abs(dot(position, position)) < nearPlane * nearPlane)
discard;
Expand All @@ -178,11 +180,15 @@ void main()
vec4 specColor = texture(SpecBuffer, screenPos);
// The vector in the normal buffer could be longer than the unit vector since decal rendering only adds to the normal buffer
vec3 normal = normalize(normalData.xyz);

vec4 bentNormalBufferData = texture(BentBuffer, screenPos);
vec3 bentNormal = normalize(bentNormalBufferData.xyz);
float gloss = normalData.a;
float roughness = clamp(1.0f - gloss, 0.0f, 1.0f);
float alpha = roughness * roughness;
float fresnel = specColor.a;
vec3 eyeDir = normalize(-position);
float ambientOcclusion = bentNormalBufferData.a;

vec3 lightDir;
float attenuation;
Expand All @@ -204,7 +210,12 @@ void main()

vec3 halfVec = normalize(lightDir + eyeDir);
float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0);

float NdotV = clamp(dot(normal, eyeDir), 0.0, 1.0);
float BdotL = clamp(dot(bentNormal, lightDir), 0.0, 1.0);
float occlusionShadow = GetVisibilityFromMaterialOcclusion(ambientOcclusion, gloss, NdotV, BdotL);

vec4 fragmentColor = vec4(1.0);
fragmentColor.rgb = computeLighting(specColor.rgb, diffColor, lightDir, normal.xyz, halfVec, eyeDir, roughness, fresnel, NdotL).rgb * diffuseLightColor * attenuation * area_normalisation;
fragmentColor.rgb = computeLighting(specColor.rgb, diffColor, lightDir, normal.xyz, halfVec, eyeDir, roughness, fresnel, NdotL ).rgb * diffuseLightColor * attenuation * area_normalisation * occlusionShadow ;
fragOut0 = max(fragmentColor, vec4(0.0));
}
}
31 changes: 29 additions & 2 deletions code/def_files/data/effects/lighting.sdr
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,33 @@ const float GLOW_MAP_INTENSITY = 1.5;
const float GLOW_MAP_SRGB_MULTIPLIER = 3.0;
const float PI = 3.14159f;

// https://www.activision.com/cdn/research/siggraph_2018_opt.pdf
float AdjustCosConeAngle ( float cosConeAngle , float gloss , float NdotV )
{
// The cone is an especially poor approximation to actual visibility for high gloss values .
// This is an ad hoc adjustment .
// Gloss above 0.67 is unaffected by the cone , i .e .\ we set to full cone angle .
//gloss = clamp( gloss * 1.5, 0.0, 1.0 ); // Optionally , omit this line .
float gloss2 = gloss * gloss ;
float gloss4 = gloss2 * gloss2 ;
float gloss8 = gloss4 * gloss4 ;
float oneMinusNdotV2 = ( 1 - NdotV ) * ( 1 - NdotV );
float oneMinusNdotV4 = oneMinusNdotV2 * oneMinusNdotV2 ;
// We lerp towards full cone angle based on gloss and NdotV .
cosConeAngle = mix( 0, cosConeAngle , ( 1 - gloss8 ) * ( 1 - oneMinusNdotV4 ) );
return cosConeAngle ;
}


float GetVisibilityFromMaterialOcclusion( float materialOcclusion, float gloss, float NdotV, float BdotL )
{
float vis = materialOcclusion;
float cosConeAngle = sqrt( 1 - vis ) ;
float adjustedCosConeAngle = AdjustCosConeAngle( cosConeAngle , gloss , NdotV ) ;
adjustedCosConeAngle = max( adjustedCosConeAngle , 0.001 );
vis = clamp( BdotL / adjustedCosConeAngle, 0.0, 1.0 );
return vis ; // * vis
}

vec3 FresnelSchlick(vec3 halfVec, vec3 view, vec3 specColor)
{
Expand Down Expand Up @@ -69,9 +96,9 @@ vec3 ComputeGGX(vec3 specColor, vec3 diffColor, vec3 light, vec3 normal, vec3 ha
vec3 computeLighting(vec3 specColor, vec3 diffColor, vec3 light, vec3 normal, vec3 halfVec, vec3 view, float roughness, float fresnelFactor, float dotNL)
{
#ifdef FLAG_LIGHT_MODEL_BLINN_PHONG
return SpecularBlinnPhong(specColor, light, normal, halfVec, 32, fresnelFactor, dotNL);
return SpecularBlinnPhong(specColor, light, normal, halfVec, 32, fresnelFactor, dotNL );
#else
return ComputeGGX(specColor, diffColor, light, normal, halfVec, view, roughness, fresnelFactor, dotNL);
return ComputeGGX(specColor, diffColor, light, normal, halfVec, view, roughness, fresnelFactor, dotNL );
#endif
}

Expand Down
68 changes: 47 additions & 21 deletions code/def_files/data/effects/main-f.sdr
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ layout (std140) uniform modelData {
int sMiscmapIndex;

float alphaMult;

int flags;
int sBentmapIndex;
};

in VertexOutput {
Expand Down Expand Up @@ -140,6 +140,9 @@ uniform sampler2D sFramebuffer;
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_MISC
uniform sampler2DArray sMiscmap;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_MISC
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_BENT
uniform sampler2DArray sBentmap;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_BENT
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
uniform sampler2DArray shadow_map;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
Expand All @@ -151,6 +154,7 @@ out vec4 fragOut1;
out vec4 fragOut2;
out vec4 fragOut3;
out vec4 fragOut4;
out vec4 fragOut5;
#endif

vec3 FresnelLazarovEnv(vec3 specColor, vec3 view, vec3 normal, float gloss)
Expand Down Expand Up @@ -184,10 +188,10 @@ void GetLightInfo(int i, out vec3 lightDir, out float attenuation)
attenuation = 1.0 / (1.0 + lights[i].attenuation * dist);
}
}
vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial, float gloss, float fresnel, float shadow, float aoFactor)
vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial, float gloss, float fresnel, float shadow, vec2 aoFactor, vec3 bentNormal)
{
vec3 eyeDir = vec3(normalize(-vertIn.position).xyz);
vec3 lightAmbient = (emissionFactor + ambientFactor * ambientFactor) * aoFactor; // ambientFactor^2 due to legacy OpenGL compatibility behavior
vec3 lightAmbient = (emissionFactor + ambientFactor * ambientFactor) * aoFactor.x; // ambientFactor^2 due to legacy OpenGL compatibility behavior
vec3 lightDiffuse = vec3(0.0, 0.0, 0.0);
vec3 lightSpecular = vec3(0.0, 0.0, 0.0);
#pragma optionNV unroll all
Expand All @@ -203,13 +207,34 @@ vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial,
GetLightInfo(i, lightDir, attenuation);
vec3 halfVec = normalize(lightDir + eyeDir);
float NdotL = clamp(dot(normal, lightDir), 0.0f, 1.0f);
float BdotL = clamp(dot(bentNormal, lightDir), 0.0f, 1.0f);
float NdotV = clamp(dot(normal, eyeDir), 0.0f, 1.0f);
float occlusionShadow = GetVisibilityFromMaterialOcclusion(aoFactor.y, gloss, NdotV, BdotL);
// Ambient, Diffuse, and Specular
lightDiffuse += (lights[i].diffuse_color.rgb * diffuseFactor * NdotL * attenuation) * shadow;
lightSpecular += lights[i].diffuse_color.rgb * computeLighting(specularMaterial, diffuseMaterial, lightDir, normal, halfVec, eyeDir, roughness, fresnel, NdotL) * attenuation * shadow;
lightSpecular += lights[i].diffuse_color.rgb * computeLighting(specularMaterial, diffuseMaterial, lightDir, normal, halfVec, eyeDir, roughness, fresnel, NdotL) * attenuation * shadow * occlusionShadow ;
}
return diffuseMaterial * lightAmbient + lightSpecular;
}

// Normal map - convert from DXT5nm
vec3 unpackNormalMap(vec3 unitNormal, sampler2DArray sampler, int index, vec2 texCoord)
{
vec2 normalSample;
vec3 result = vec3(1.0);

result.rg = normalSample = (texture(sampler, vec3(texCoord, float(index))).ag * 2.0) - 1.0;
result.b = clamp(sqrt(1.0 - dot(result.rg, result.rg)), 0.0001, 1.0);
result = vertIn.tangentMatrix * result;
float normLen = length(result);
// prevent breaking of normal maps
if (normLen > 0.0)
result /= normLen;
else
result = unitNormal;

return result;
}

void main()
{
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
Expand All @@ -231,6 +256,7 @@ void main()
vec2 aoFactors = vec2(1.0, 1.0);
vec3 unitNormal = normalize(vertIn.normal);
vec3 normal = unitNormal;
vec3 bentNormal = unitNormal;

#prereplace IF_FLAG MODEL_SDR_FLAG_AMBIENT
// red channel is ambient occlusion factor which only affects ambient lighting.
Expand All @@ -240,16 +266,7 @@ void main()

#prereplace IF_FLAG MODEL_SDR_FLAG_NORMAL
// Normal map - convert from DXT5nm
vec2 normalSample;
normal.rg = normalSample = (texture(sNormalmap, vec3(texCoord, float(sNormalmapIndex))).ag * 2.0) - 1.0;
normal.b = clamp(sqrt(1.0 - dot(normal.rg, normal.rg)), 0.0001, 1.0);
normal = vertIn.tangentMatrix * normal;
float norm = length(normal);
// prevent breaking of normal maps
if (norm > 0.0)
normal /= norm;
else
normal = unitNormal;
normal = unpackNormalMap(unitNormal, sNormalmap, sNormalmapIndex, texCoord);
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_NORMAL

vec2 distort = vec2(0.0, 0.0);
Expand Down Expand Up @@ -307,9 +324,6 @@ void main()
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_HDR
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SPEC

baseColor.rgb *= aoFactors.y;
specColor.rgb *= aoFactors.y;

vec4 teamMask = vec4(0.0);
vec3 team_color_glow = vec3(0.0);

Expand Down Expand Up @@ -341,6 +355,11 @@ void main()
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_TEAMCOLOR
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_MISC

#prereplace IF_FLAG MODEL_SDR_FLAG_BENT
// Bent Normal map
bentNormal = unpackNormalMap(unitNormal, sBentmap, sBentmapIndex, texCoord);
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_BENT

// Lights aren't applied when we are rendering to the G-buffers since that gets handled later
#prereplace IF_FLAG MODEL_SDR_FLAG_DEFERRED
#prereplace IF_FLAG MODEL_SDR_FLAG_LIGHT
Expand All @@ -360,7 +379,7 @@ void main()
#prereplace IF_FLAG MODEL_SDR_FLAG_SHADOWS
shadow = getShadowValue(shadow_map, -vertIn.position.z, vertIn.shadowPos.z, vertIn.shadowUV, fardist, middist, neardist, veryneardist);
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SHADOWS
baseColor.rgb = CalculateLighting(normal, baseColor.rgb, specColor.rgb, glossData, fresnelFactor, shadow, aoFactors.x);
baseColor.rgb = CalculateLighting(normal, baseColor.rgb, specColor.rgb, glossData, fresnelFactor, shadow, aoFactors, bentNormal);
#prereplace ELSE_FLAG //MODEL_SDR_FLAG_LIGHT
#prereplace IF_FLAG MODEL_SDR_FLAG_SPEC
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
Expand Down Expand Up @@ -408,9 +427,15 @@ void main()
float g1vNL = GeometrySchlickGGX(NdotL, k);
vec3 specEnvLighting = specEnvColour.rgb * fresnel * g1vNL;

vec3 irr_normal_dir = vec3(envMatrix * vec4(normal,0.0));
#prereplace IF_FLAG MODEL_SDR_FLAG_BENT
specEnvLighting *= mix(max(dot(light_dir, bentNormal), 0), 1.0, aoFactors.x);
irr_normal_dir = vec3(envMatrix * vec4(bentNormal, 0.0));
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_BENT

vec3 kD = vec3(1.0)-fresnel;
kD *= (vec3(1.0) - specColor.rgb);
vec3 diffEnvColor = srgb_to_linear(texture(sIrrmap, vec3(envMatrix * vec4(normal, 0.0))).rgb);
vec3 diffEnvColor = srgb_to_linear(texture(sIrrmap, irr_normal_dir).rgb);
vec3 diffEnvLighting = kD * baseColor.rgb * diffEnvColor * aoFactors.x;
emissiveColor.rgb += (specEnvLighting + diffEnvLighting) * baseColor.a;
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_LIGHT
Expand Down Expand Up @@ -489,7 +514,8 @@ void main()
fragOut1 = vec4(vertIn.position.xyz, 1.0);
fragOut2 = vec4(normal, glossData);
fragOut3 = vec4(specColor.rgb, fresnelFactor);
fragOut4 = emissiveColor;
fragOut4 = vec4(bentNormal, aoFactors.y);
fragOut5 = emissiveColor;
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DEFERRED

#endif
Expand Down
1 change: 1 addition & 0 deletions code/def_files/data/effects/main-g.sdr
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ layout (std140) uniform modelData {
float alphaMult;

int flags;
int sBentmapIndex;
};

in VertexOutput {
Expand Down
1 change: 1 addition & 0 deletions code/def_files/data/effects/main-v.sdr
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ layout (std140) uniform modelData {
float alphaMult;

int flags;
int sBentmapIndex;
};

#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_TRANSFORM
Expand Down
5 changes: 3 additions & 2 deletions code/def_files/data/effects/model_shader_flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
#elif defined MODEL_SDR_FLAG_MODE_GLSL
#define SDR_FLAG(name, value, geoshader) const int name = value;
#else
#error Make sure to properly define the usage mode for this file!

Check failure on line 8 in code/def_files/data/effects/model_shader_flags.h

View workflow job for this annotation

GitHub Actions / Linux (Release, clang-16)

clang-tidy: Make sure to properly define the usage mode for this file! (clang-diagnostic-error)
#endif

SDR_FLAG(MODEL_SDR_FLAG_LIGHT , (1 << 0) , false)

Check failure on line 11 in code/def_files/data/effects/model_shader_flags.h

View workflow job for this annotation

GitHub Actions / Linux (Release, clang-16)

clang-tidy: a type specifier is required for all declarations (clang-diagnostic-error)

Check failure on line 11 in code/def_files/data/effects/model_shader_flags.h

View workflow job for this annotation

GitHub Actions / Linux (Release, clang-16)

clang-tidy: use of undeclared identifier 'MODEL_SDR_FLAG_LIGHT' (clang-diagnostic-error)

Check failure on line 11 in code/def_files/data/effects/model_shader_flags.h

View workflow job for this annotation

GitHub Actions / Linux (Release, clang-16)

clang-tidy: expected ';' after top level declarator (clang-diagnostic-error)
SDR_FLAG(MODEL_SDR_FLAG_DEFERRED , (1 << 1) , false)
SDR_FLAG(MODEL_SDR_FLAG_HDR , (1 << 2) , false)
SDR_FLAG(MODEL_SDR_FLAG_DIFFUSE , (1 << 3) , false)
Expand All @@ -24,12 +24,13 @@
SDR_FLAG(MODEL_SDR_FLAG_SHADOWS , (1 << 13), false)
SDR_FLAG(MODEL_SDR_FLAG_THRUSTER , (1 << 14), false)
SDR_FLAG(MODEL_SDR_FLAG_ALPHA_MULT , (1 << 15), false)
SDR_FLAG(MODEL_SDR_FLAG_BENT , (1 << 16), false)

#ifndef MODEL_SDR_FLAG_MODE_GLSL
//The following ones are used ONLY as compile-time flags, but they still need to be defined here to ensure no conflict occurs
//But since these are checked with ifdefs even for the large shader, they must never be available in GLSL mode

SDR_FLAG(MODEL_SDR_FLAG_SHADOW_MAP , (1 << 16), true)
SDR_FLAG(MODEL_SDR_FLAG_THICK_OUTLINES, (1 << 17), true)
SDR_FLAG(MODEL_SDR_FLAG_SHADOW_MAP , (1 << 17), true)
SDR_FLAG(MODEL_SDR_FLAG_THICK_OUTLINES, (1 << 18), true)

#endif
7 changes: 6 additions & 1 deletion code/def_files/data/effects/msaa-f.sdr
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ out vec4 fragOut2;
out vec4 fragOut3;
out vec4 fragOut4;
out vec4 fragOut5;
out vec4 fragOut6;

uniform sampler2DMS texColor;
uniform sampler2DMS texPos;
uniform sampler2DMS texNormal;
uniform sampler2DMS texSpecular;
uniform sampler2DMS texBent;
uniform sampler2DMS texEmissive;
uniform sampler2DMS texDepth;

Expand Down Expand Up @@ -167,6 +169,7 @@ void main()
vec4 color = vec4(0);
vec4 pos = vec4(0);
vec4 normal = vec4(0);
vec4 bent = vec4(0);
vec4 specular = vec4(0);
vec4 emissive = vec4(0);
float depth = 0;
Expand All @@ -183,6 +186,7 @@ void main()
pos += localPos * localWeight;
color += texelFetch(texColor, texel, i) * localWeight;
normal += texelFetch(texNormal, texel, i) * localWeight;
bent += texelFetch(texBent, texel, i) * localWeight;
specular += texelFetch(texSpecular, texel, i) * localWeight;
emissive += texelFetch(texEmissive, texel, i) * localWeight;
depth += texelFetch(texDepth, texel, i).x * localWeight;
Expand All @@ -193,6 +197,7 @@ void main()
fragOut1 = pos / weight;
fragOut2 = vec4(normalize(normal.xyz), normal.a / weight);
fragOut3 = specular / weight;
fragOut4 = emissive / weight;
fragOut4 = vec4(normalize(bent.xyz), bent.a / weight);
fragOut5 = emissive / weight;
gl_FragDepth = depth / weight;
}
6 changes: 5 additions & 1 deletion code/graphics/material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ Depth_bias(0)
Texture_maps[TM_MISC_TYPE] = -1;
Texture_maps[TM_SPEC_GLOSS_TYPE] = -1;
Texture_maps[TM_AMBIENT_TYPE] = -1;
Texture_maps[TM_BENT_NORMAL_TYPE] = -1;

Clip_params.enabled = false;

Expand Down Expand Up @@ -298,7 +299,8 @@ bool material::is_textured() const
Texture_maps[TM_NORMAL_TYPE] > -1 ||
Texture_maps[TM_HEIGHT_TYPE] > -1 ||
Texture_maps[TM_AMBIENT_TYPE] > -1 ||
Texture_maps[TM_MISC_TYPE] > -1;
Texture_maps[TM_MISC_TYPE] > -1 ||
Texture_maps[TM_BENT_NORMAL_TYPE] > -1;
}

void material::set_texture_type(texture_type t_type)
Expand Down Expand Up @@ -784,6 +786,8 @@ int model_material::get_shader_runtime_flags() const {
flags |= MODEL_SDR_FLAG_MISC;
if (get_texture_map(TM_MISC_TYPE) > 0 && is_team_color_set())
flags |= MODEL_SDR_FLAG_TEAMCOLOR;
if (get_texture_map(TM_BENT_NORMAL_TYPE) > 0)
flags |= MODEL_SDR_FLAG_BENT;
if (is_fogged())
flags |= MODEL_SDR_FLAG_FOG;
if (is_shadow_receiving())
Expand Down
Loading
Loading