Skip to content

Commit

Permalink
Dev: Added local scattering to LUT based hair material
Browse files Browse the repository at this point in the history
  • Loading branch information
AEspinosaDev committed Nov 20, 2024
1 parent d6bb1a7 commit bc0c9e4
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 39 deletions.
6 changes: 3 additions & 3 deletions include/engine/core/materials/hair_strand.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,12 +247,12 @@ class HairStrandMaterial2 : public HairStrandMaterial
m_textures[GI] = new Texture(settings);
m_textures[MGI] = new Texture(settings);
Tools::Loaders::load_texture(
m_textures[N1], ENGINE_RESOURCES_PATH "textures/N_TT_R.png", TEXTURE_FORMAT_TYPE_COLOR, false);
m_textures[N1], ENGINE_RESOURCES_PATH "textures/N_TT_R.png", TEXTURE_FORMAT_TYPE_NORMAL, false);
Tools::Loaders::load_texture(
m_textures[N2], ENGINE_RESOURCES_PATH "textures/N_TRT.png", TEXTURE_FORMAT_TYPE_COLOR, false);
m_textures[N2], ENGINE_RESOURCES_PATH "textures/N_TRT.png", TEXTURE_FORMAT_TYPE_NORMAL, false);
Tools::Loaders::load_3D_texture(m_textures[GI], ENGINE_RESOURCES_PATH "textures/GI.png");
Tools::Loaders::load_texture(
m_textures[MGI], ENGINE_RESOURCES_PATH "textures/M_GI.png", TEXTURE_FORMAT_TYPE_COLOR, false);
m_textures[MGI], ENGINE_RESOURCES_PATH "textures/M_GI.png", TEXTURE_FORMAT_TYPE_NORMAL, false);
m_textures[N1]->set_format(RGBA_8U);
m_textures[N2]->set_format(RGBA_8U);
m_textures[GI]->set_format(RGBA_8U);
Expand Down
106 changes: 81 additions & 25 deletions resources/shaders/forward/hair_strand2.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -163,23 +163,78 @@ MarschnerLookupBSDF bsdf;
layout(location = 0) out vec4 fragColor;


float computeShadow(LightUniform light, int lightId) {

vec4 posLightSpace = light.viewProj * vec4(g_modelPos, 1.0);

vec3 projCoords = posLightSpace.xyz / posLightSpace.w; //For x,y and Z

projCoords.xy = projCoords.xy * 0.5 + 0.5;

if(projCoords.z > 1.0 || projCoords.z < 0.0)
return 1.0;

vec3 lightDir = normalize(light.position.xyz - g_pos);
float bias = max(light.shadowData.x * 5.0 * (1.0 - dot(g_dir, lightDir)), light.shadowData.x); //Modulate by angle of incidence

// return 1.0 - filterPCF(shadowMap,lightId,int(light.pcfKernel), light.kernelRadius,projCoords, bias);
return 1.0 - filterPCF(shadowMap, lightId,int(light.shadowData.w), light.shadowData.y, projCoords, light.shadowData.x);
}
// float computeShadow(LightUniform light, int lightId) {

// vec4 posLightSpace = light.viewProj * vec4(g_modelPos, 1.0);

// vec3 projCoords = posLightSpace.xyz / posLightSpace.w; //For x,y and Z

// projCoords.xy = projCoords.xy * 0.5 + 0.5;

// if(projCoords.z > 1.0 || projCoords.z < 0.0)
// return 1.0;

// vec3 lightDir = normalize(light.position.xyz - g_pos);
// float bias = max(light.shadowData.x * 5.0 * (1.0 - dot(g_dir, lightDir)), light.shadowData.x); //Modulate by angle of incidence

// // return 1.0 - filterPCF(shadowMap,lightId,int(light.pcfKernel), light.kernelRadius,projCoords, bias);
// return 1.0 - filterPCF(shadowMap, lightId,int(light.shadowData.w), light.shadowData.y, projCoords, light.shadowData.x);
// }

float bilinear( float v[4], vec2 f )
{
return mix( mix( v[0], v[1], f.x ), mix( v[2], v[3], f.x ), f.y );
}

vec3 bilinear( vec3 v[4], vec2 f )
{
return mix( mix( v[0], v[1], f.x ), mix( v[2], v[3], f.x ), f.y );
}
vec3 hairShadow( out vec3 spread, out float directF, vec3 pShad, int lightId )
{
float hairDensity = 1.0;
ivec2 size = textureSize( shadowMap, 0 ).xy;
vec2 t = pShad.xy * vec2(size) + 0.5;
vec2 f = t - floor(t);
vec2 s = 0.5 / vec2(size);

vec2 tcp[4];
tcp[0] = pShad.xy + vec2( -s.x, -s.y );
tcp[1] = pShad.xy + vec2( s.x, -s.y );
tcp[2] = pShad.xy + vec2( -s.x, s.y );
tcp[3] = pShad.xy + vec2( s.x, s.y );

const float coverage = 0.05;
const vec3 a_f = vec3( 0.507475266, 0.465571405, 0.394347166 );
const vec3 w_f = vec3( 0.028135575, 0.027669785, 0.027669785 );
float dir[4];
vec3 spr[4], t_d[4];
for ( int i=0; i<4; ++i ) {
float z = texture(shadowMap, vec3(tcp[i],lightId)).r;
//vis[i] = z < pShad.z ? 0.0 : 1.0;
float h = max( 0.0, pShad.z - z );
float n = h * hairDensity;
dir[i] = pow( 1.0 - coverage, n );
t_d[i] = pow( 1.0 - coverage*(1.0 - a_f), vec3(n,n,n) );
spr[i] = n * coverage * w_f;
}

directF = bilinear( dir, f );
spread = bilinear( spr, f );
return bilinear( t_d, f );
}
vec3 computeShadow(LightUniform light,int lightId, out vec3 spread, out float directF )
{
vec4 posLightSpace = light.viewProj * vec4(g_modelPos, 1.0);
vec3 projCoords = posLightSpace.xyz / posLightSpace.w; //For x,y and Z
projCoords.xy = projCoords.xy * 0.5 + 0.5;
// if(projCoords.z > 1.0 || projCoords.z < 0.0)
// return 1.0;
// projCoords.z -= light.shadowData.x;
vec3 trans_direct = hairShadow( spread, directF, projCoords,lightId );
directF *= 0.5;
return trans_direct * 0.5;
}


vec3 computeAmbient(vec3 n) {
Expand Down Expand Up @@ -229,6 +284,13 @@ void main() {
//If inside liught area influence
if(isInAreaOfInfluence(scene.lights[i], g_pos)) {

vec3 shadow = vec3(1.0);
if(int(object.otherParams.y) == 1 && scene.lights[i].shadowCast == 1) {
if(scene.lights[i].shadowType == 0) //Classic
shadow = computeShadow(scene.lights[i], i,bsdf.spread, bsdf.directFraction);
if(scene.lights[i].shadowType == 1) //VSM
shadow.x = computeVarianceShadow(shadowMap,scene.lights[i],i,g_modelPos);
}
vec3 lighting = evalMarschnerLookupBSDF(
normalize(scene.lights[i].position.xyz - g_pos),
normalize(-g_pos),
Expand All @@ -241,14 +303,8 @@ void main() {
material.tt,
material.trt);

if(int(object.otherParams.y) == 1 && scene.lights[i].shadowCast == 1) {
if(scene.lights[i].shadowType == 0) //Classic
lighting *= computeShadow(scene.lights[i], i);
if(scene.lights[i].shadowType == 1) //VSM
lighting *= computeVarianceShadow(shadowMap,scene.lights[i],i,g_modelPos);
}

color += lighting;
color += lighting * shadow;
}
}

Expand All @@ -268,6 +324,6 @@ void main() {
}


fragColor = vec4(reindhartTonemap(color), 1.0);
fragColor = vec4(color, 1.0);

}
25 changes: 14 additions & 11 deletions resources/shaders/scripts/BRDFs/marschner_LUT_BSDF.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ struct MarschnerLookupBSDF{
float Rpower;
float TTpower;
float TRTpower;
vec3 spread;
float directFraction;
};

//Longitudinal TERM (Gaussian Distribution)
Expand Down Expand Up @@ -73,8 +75,10 @@ vec3 evalMarschnerLookupBSDF(
//Phi
vec3 wiPerp = normalize(wi - sin_thI * u);
vec3 vPerp = normalize(v - sin_thR * u);
float cos_phiH = dot(vPerp,wiPerp)*inversesqrt(dot(vPerp,vPerp)*dot(wiPerp,wiPerp));
float phiH = cos((asin(sin_thI)-asin(sin_thR))*0.5);
// float cos_phiH = dot(vPerp,wiPerp)*inversesqrt(dot(vPerp,vPerp)*dot(wiPerp,wiPerp));
// float phiH = cos((asin(sin_thI)-asin(sin_thR))*0.5);
float cos_phiH = dot( wiPerp, vPerp );
float phiH = acos( cos_phiH );

float randVal = rand( 2, 3 );
float phi_shift = ECCEN_SHIFT*(randVal-0.5f);
Expand All @@ -87,8 +91,8 @@ vec3 evalMarschnerLookupBSDF(
//////////////////////////////////////////////////////////////////////////

// N
vec2 index1 = vec2( phiH * ONE_OVER_PI, 1-ix_th );
vec2 index2 = vec2( phiH * ONE_OVER_PI, 1-ix_th );
vec2 index1 = vec2( phiH * ONE_OVER_PI, ix_th );
vec2 index2 = vec2( phiH * ONE_OVER_PI, ix_th );

vec4 N = texture(texN, index1);
float NR = SCALE_N_R * N.a;
Expand All @@ -111,16 +115,15 @@ vec3 evalMarschnerLookupBSDF(
// Local Scattering
//////////////////////////////////////////////////////////////////////////
float ix_thH = thH * ONE_OVER_PI * 0.5 + 0.5;
vec3 ix_spread = sqrt(vec3(0.5)) * ONE_OVER_PI*0.5;
vec3 ix_spread = sqrt(bsdf.spread) * ONE_OVER_PI*0.5;

vec3 gi;
gi.r = DENSITY * texture( texGI, vec3( ix_spread.r, ix_thH, 1-ix_th ) ).r;
gi.g = DENSITY * texture( texGI, vec3( ix_spread.g, ix_thH, 1-ix_th ) ).g;
gi.b = DENSITY * texture( texGI, vec3( ix_spread.b, ix_thH, 1-ix_th ) ).b;
gi.r = DENSITY * texture( texGI, vec3( ix_spread.r, ix_thH, ix_th ) ).r;
gi.g = DENSITY * texture( texGI, vec3( ix_spread.g, ix_thH, ix_th ) ).g;
gi.b = DENSITY * texture( texGI, vec3( ix_spread.b, ix_thH, ix_th ) ).b;

//specular += gi;

// specular *= directFraction;
specular += gi;
specular *= bsdf.directFraction;


return (specular) * irradiance * GLOBAL_SCALE;
Expand Down

0 comments on commit bc0c9e4

Please sign in to comment.