Skip to content

Commit

Permalink
#5936: First draft, porting the TDM ambient shader code to the main i…
Browse files Browse the repository at this point in the history
…nteraction shader
  • Loading branch information
codereader committed Apr 10, 2022
1 parent a7da6bc commit d2cef94
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 59 deletions.
152 changes: 95 additions & 57 deletions install/gl/interaction_fp.glsl
Expand Up @@ -7,7 +7,8 @@ uniform sampler2D u_attenuationmap_xy;
uniform sampler2D u_attenuationmap_z;
uniform sampler2D u_ShadowMap;

uniform vec3 u_view_origin;
uniform vec3 u_LocalViewOrigin;
uniform vec3 u_WorldUpLocal; // world 0,0,1 direction in local space
uniform vec3 u_light_origin;
uniform vec3 u_light_color;
uniform float u_light_scale;
Expand All @@ -20,7 +21,7 @@ uniform vec4 u_ShadowMapRect; // x,y,w,h
uniform bool u_UseShadowMap;

// Activate ambient light mode (brightness unaffected by direction)
uniform bool uAmbientLight;
uniform bool u_IsAmbientLight;

// Texture coords as calculated by the vertex program
varying vec2 var_TexDiffuse;
Expand All @@ -32,6 +33,7 @@ varying vec4 var_tex_atten_xy_z;
varying mat3 var_mat_os2ts;
varying vec4 var_Colour; // colour to be multiplied on the final fragment
varying vec3 var_WorldLightDirection; // direction the light is coming from in world space
varying vec3 var_LocalViewerDirection; // viewer direction in local space

// Function ported from TDM tdm_shadowmaps.glsl, determining the cube map face for the given direction
vec3 CubeMapDirectionToUv(vec3 v, out int faceIdx)
Expand Down Expand Up @@ -92,77 +94,113 @@ float getDepthValueForVector(in sampler2D shadowMapTexture, vec4 shadowRect, vec

void main()
{
// Ported from TDM interaction.common.fs.glsl

vec4 fresnelParms = vec4(1.0, .23, .5, 1.0);
vec4 fresnelParms2 = vec4(.2, .023, 120.0, 4.0);
vec4 lightParms = vec4(.7, 1.8, 10.0, 30.0);
vec3 totalColor;

// Perform the texture lookups
vec4 diffuse = texture2D(u_Diffusemap, var_TexDiffuse);
vec3 specular = texture2D(u_Specularmap, var_TexSpecular).rgb;

// compute view direction in tangent space
vec3 localV = normalize(var_mat_os2ts * (u_view_origin - var_vertex));

// compute light direction in tangent space
vec3 localL = normalize(var_mat_os2ts * (u_light_origin - var_vertex));

vec4 bumpTexel = texture2D(u_Bumpmap, var_TexBump) * 2. - 1.;
vec3 RawN = normalize( bumpTexel.xyz );
vec3 N = var_mat_os2ts * RawN;

//must be done in tangent space, otherwise smoothing will suffer (see #4958)
float NdotL = clamp(dot(RawN, localL), 0.0, 1.0);
float NdotV = clamp(dot(RawN, localV), 0.0, 1.0);
float NdotH = clamp(dot(RawN, normalize(localV + localL)), 0.0, 1.0);

// fresnel part
float fresnelTerm = pow(1.0 - NdotV, fresnelParms2.w);
float rimLight = fresnelTerm * clamp(NdotL - 0.3, 0.0, fresnelParms.z) * lightParms.y;
float specularPower = mix(lightParms.z, lightParms.w, specular.z);
float specularCoeff = pow(NdotH, specularPower) * fresnelParms2.z;
float fresnelCoeff = fresnelTerm * fresnelParms.y + fresnelParms2.y;
// Light texture lookups
vec3 attenuation_xy = vec3(0,0,0);

vec3 specularColor = specularCoeff * fresnelCoeff * specular * (diffuse.rgb * 0.25 + vec3(0.75));
float R2f = clamp(localL.z * 4.0, 0.0, 1.0);

float NdotL_adjusted = NdotL;
float light = rimLight * R2f + NdotL_adjusted;

// compute attenuation
vec3 attenuation_xy = vec3(0.0, 0.0, 0.0);
if (var_tex_atten_xy_z.w > 0.0)
attenuation_xy = texture2DProj(
u_attenuationmap_xy,
var_tex_atten_xy_z.xyw
).rgb;

vec3 attenuation_z = texture2D(
u_attenuationmap_z, vec2(var_tex_atten_xy_z.z, 0.5)
).rgb;
{
attenuation_xy = texture2DProj(u_attenuationmap_xy, var_tex_atten_xy_z.xyw).rgb;
}

vec3 totalColor = (specularColor * u_light_color * R2f + diffuse.rgb) * light * (u_light_color * u_light_scale) * attenuation_xy * attenuation_z * var_Colour.rgb;
vec3 attenuation_z = texture2D(u_attenuationmap_z, vec2(var_tex_atten_xy_z.z, 0.5)).rgb;

if (u_UseShadowMap)
if (!u_IsAmbientLight)
{
// Ported from TDM interaction.common.fs.glsl
vec4 fresnelParms = vec4(1.0, .23, .5, 1.0);
vec4 fresnelParms2 = vec4(.2, .023, 120.0, 4.0);
vec4 lightParms = vec4(.7, 1.8, 10.0, 30.0);

// compute view direction in tangent space
vec3 localV = normalize(var_mat_os2ts * (u_LocalViewOrigin - var_vertex));

// compute light direction in tangent space
vec3 localL = normalize(var_mat_os2ts * (u_light_origin - var_vertex));

vec3 RawN = normalize(bumpTexel.xyz);
vec3 N = var_mat_os2ts * RawN;

//must be done in tangent space, otherwise smoothing will suffer (see #4958)
float NdotL = clamp(dot(RawN, localL), 0.0, 1.0);
float NdotV = clamp(dot(RawN, localV), 0.0, 1.0);
float NdotH = clamp(dot(RawN, normalize(localV + localL)), 0.0, 1.0);

// fresnel part
float fresnelTerm = pow(1.0 - NdotV, fresnelParms2.w);
float rimLight = fresnelTerm * clamp(NdotL - 0.3, 0.0, fresnelParms.z) * lightParms.y;
float specularPower = mix(lightParms.z, lightParms.w, specular.z);
float specularCoeff = pow(NdotH, specularPower) * fresnelParms2.z;
float fresnelCoeff = fresnelTerm * fresnelParms.y + fresnelParms2.y;

vec3 specularColor = specularCoeff * fresnelCoeff * specular * (diffuse.rgb * 0.25 + vec3(0.75));
float R2f = clamp(localL.z * 4.0, 0.0, 1.0);

float NdotL_adjusted = NdotL;
float light = rimLight * R2f + NdotL_adjusted;

// Combine everything to get the colour (unshadowed)
totalColor = (specularColor * u_light_color * R2f + diffuse.rgb) * light * (u_light_color * u_light_scale) * attenuation_xy * attenuation_z * var_Colour.rgb;

if (u_UseShadowMap)
{
float shadowMapResolution = (textureSize(u_ShadowMap, 0).x * u_ShadowMapRect.w);

// The light direction is used to sample the shadow map texture
vec3 L = normalize(var_WorldLightDirection);

vec3 absL = abs(var_WorldLightDirection);
float maxAbsL = max(absL.x, max(absL.y, absL.z));
float centerFragZ = maxAbsL;

vec3 normal = mat3(u_ObjectTransform) * N;

float lightFallAngle = -dot(normal, L);
float errorMargin = 5.0 * maxAbsL / ( shadowMapResolution * max(lightFallAngle, 0.1) );

float centerBlockerZ = getDepthValueForVector(u_ShadowMap, u_ShadowMapRect, L);
float lit = float(centerBlockerZ >= centerFragZ - errorMargin);

totalColor *= lit;
}
}
else
{
float shadowMapResolution = (textureSize(u_ShadowMap, 0).x * u_ShadowMapRect.w);
// Ported from TDM's interaction.ambient.fs
vec3 localNormal = vec3(bumpTexel.x, bumpTexel.y, sqrt(max(1. - bumpTexel.x*bumpTexel.x - bumpTexel.y*bumpTexel.y, 0)));
vec3 N = normalize(var_mat_os2ts * localNormal);

vec3 nViewDir = normalize(var_LocalViewerDirection);
vec3 reflect = - (nViewDir - 2 * N * dot(N, nViewDir));

// compute lighting model
vec4 color = diffuse * var_Colour;

vec4 light = vec4(attenuation_xy * attenuation_z, 1);

// The light direction is used to sample the shadow map texture
vec3 L = normalize(var_WorldLightDirection);
vec3 light1 = vec3(.5); // directionless half
light1 += max(dot(N, u_WorldUpLocal) * (1. - specular) * .5, 0);

vec3 absL = abs(var_WorldLightDirection);
float maxAbsL = max(absL.x, max(absL.y, absL.z));
float centerFragZ = maxAbsL;
float spec = max(dot(reflect, u_WorldUpLocal), 0);
float specPow = clamp((spec * spec), 0.0, 1.1);
light1 += vec3(spec * specPow * specPow) * specular * 1.0;

vec3 normal = mat3(u_ObjectTransform) * N;
// not needed:
// light.a = diffuse.a;

float lightFallAngle = -dot(normal, L);
float errorMargin = 5.0 * maxAbsL / ( shadowMapResolution * max(lightFallAngle, 0.1) );
light1.rgb *= color.rgb;

float centerBlockerZ = getDepthValueForVector(u_ShadowMap, u_ShadowMapRect, L);
float lit = float(centerBlockerZ >= centerFragZ - errorMargin);
light.rgb *= diffuse.rgb * light1;

totalColor *= lit;
light = max(light, vec4(0)); // avoid negative values, which with floating point render buffers can lead to NaN artefacts

totalColor = light.rgb;
}

gl_FragColor.rgb = totalColor;
Expand Down
5 changes: 5 additions & 0 deletions install/gl/interaction_vp.glsl
Expand Up @@ -12,6 +12,7 @@ uniform vec4 u_ColourAddition; // constant additive vertex colour value
uniform mat4 u_ModelViewProjection; // combined modelview and projection matrix
uniform mat4 u_ObjectTransform; // object to world
uniform vec3 u_WorldLightOrigin; // light origin in world space
uniform vec3 u_LocalViewOrigin; // view origin in local space

// Texture Matrices (the two top rows of each)
uniform vec4 u_DiffuseTextureMatrix[2];
Expand All @@ -31,6 +32,7 @@ varying vec4 var_tex_atten_xy_z;
varying mat3 var_mat_os2ts;
varying vec4 var_Colour; // colour to be multiplied on the final fragment
varying vec3 var_WorldLightDirection; // direction the light is coming from in world space
varying vec3 var_LocalViewerDirection; // viewer direction in local space

void main()
{
Expand Down Expand Up @@ -65,6 +67,9 @@ void main()
attr_Tangent.z, attr_Bitangent.z, attr_Normal.z
);

// Calculate the viewer direction in local space (attr_Position is already in local space)
var_LocalViewerDirection = u_LocalViewOrigin - attr_Position.xyz;

// Vertex colour factor
var_Colour = (attr_Colour * u_ColourModulation + u_ColourAddition);
}
Expand Down
14 changes: 12 additions & 2 deletions radiantcore/rendersystem/backend/glprogram/InteractionProgram.cpp
Expand Up @@ -54,10 +54,11 @@ void InteractionProgram::create()
// Set the uniform locations to the correct bound values
_locLightOrigin = glGetUniformLocation(_programObj, "u_light_origin");
_locWorldLightOrigin = glGetUniformLocation(_programObj, "u_WorldLightOrigin");
_locWorldUpLocal = glGetUniformLocation(_programObj, "u_WorldUpLocal");
_locLightColour = glGetUniformLocation(_programObj, "u_light_color");
_locViewOrigin = glGetUniformLocation(_programObj, "u_view_origin");
_locViewOrigin = glGetUniformLocation(_programObj, "u_LocalViewOrigin");
_locLightScale = glGetUniformLocation(_programObj, "u_light_scale");
_locAmbientLight = glGetUniformLocation(_programObj, "uAmbientLight");
_locAmbientLight = glGetUniformLocation(_programObj, "u_IsAmbientLight");
_locColourModulation = glGetUniformLocation(_programObj, "u_ColourModulation");
_locColourAddition = glGetUniformLocation(_programObj, "u_ColourAddition");
_locModelViewProjection = glGetUniformLocation(_programObj, "u_ModelViewProjection");
Expand Down Expand Up @@ -239,6 +240,10 @@ void InteractionProgram::setUpObjectLighting(const Vector3& worldLightOrigin,
// Calculate the light origin in object space
auto localLight = worldToObject.transformPoint(worldLightOrigin);

// Calculate world up (0,0,1) in object space
// This is needed for ambient lights
auto worldUpLocal = worldToObject.zCol3();

// Calculate viewer location in object space
auto osViewer = inverseObjectTransform.transformPoint(viewer);

Expand All @@ -258,6 +263,11 @@ void InteractionProgram::setUpObjectLighting(const Vector3& worldLightOrigin,
static_cast<float>(worldLightOrigin.y()),
static_cast<float>(worldLightOrigin.z())
);
glUniform3f(_locWorldUpLocal,
static_cast<float>(worldUpLocal.x()),
static_cast<float>(worldUpLocal.y()),
static_cast<float>(worldUpLocal.z())
);

debug::assertNoGlErrors();
}
Expand Down
Expand Up @@ -18,6 +18,7 @@ class InteractionProgram :
// Uniform/program-local parameter IDs.
int _locLightOrigin;
int _locWorldLightOrigin;
int _locWorldUpLocal;
int _locLightColour;
int _locViewOrigin;
int _locLightScale;
Expand Down

0 comments on commit d2cef94

Please sign in to comment.