Created SurfaceData structure to centralize computation of frequently used shader temporary values

This commit is contained in:
Olivier Prat 2017-12-21 17:41:36 +01:00
parent 5c476dc967
commit 053bd2ba98
14 changed files with 180 additions and 161 deletions

View file

@ -46,11 +46,14 @@ struct DeferredFragment {
float depthVal;
};
<@if not GETFRESNEL0@>
<@def GETFRESNEL0@>
vec3 getFresnelF0(float metallic, vec3 metalF0) {
// Enable continuous metallness value by lerping between dielectric
// and metal fresnel F0 value based on the "metallic" parameter
return mix(vec3(0.03), metalF0, metallic);
}
<@endif@>
DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {
vec4 normalVal;

View file

@ -65,10 +65,12 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness
<$prepareGlobalLight($supportScattering$)$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@> );
@ -79,7 +81,7 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@> );
@ -110,10 +112,12 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
) {
<$prepareGlobalLight($supportScattering$)$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@>
@ -123,7 +127,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@>
@ -174,19 +178,21 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur
vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) {
<$prepareGlobalLight()$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
color += emissive * isEmissiveEnabled();
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance);
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);
color += ambientDiffuse;
color += ambientSpecular / opacity;
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation);
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse;
color += directionalSpecular / opacity;
@ -199,19 +205,21 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze(
{
<$prepareGlobalLight()$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
color += emissive * isEmissiveEnabled();
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance);
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);
color += ambientDiffuse;
color += ambientSpecular / opacity;
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation);
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse;
color += directionalSpecular / opacity;

View file

@ -65,10 +65,12 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness
<$prepareGlobalLight($supportScattering$)$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@> );
@ -79,7 +81,7 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@> );
@ -109,10 +111,12 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
) {
<$prepareGlobalLight($supportScattering$)$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@>
@ -124,7 +128,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@>
@ -173,19 +177,21 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur
vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) {
<$prepareGlobalLight()$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
color += emissive * isEmissiveEnabled();
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance);
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);
color += ambientDiffuse;
color += ambientSpecular / opacity;
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation);
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse;
color += directionalSpecular / opacity;

View file

@ -22,8 +22,9 @@ vec4 evalSkyboxLight(vec3 direction, float lod) {
<@func declareEvalAmbientSpecularIrradiance(supportAmbientSphere, supportAmbientMap, supportIfAmbientMapElseAmbientSphere)@>
vec3 fresnelSchlickAmbient(vec3 fresnelColor, vec3 lightDir, vec3 halfDir, float gloss) {
float f = pow(1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0), 5.0);
vec3 fresnelSchlickAmbient(vec3 fresnelColor, SurfaceData surface) {
float gloss = 1.0 - surface.roughness;
float f = pow(1.0 - surface.ldoth, 5.0);
return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f;
// return mix(fresnelColor, vec3(1.0), f);
}
@ -32,8 +33,8 @@ vec3 fresnelSchlickAmbient(vec3 fresnelColor, vec3 lightDir, vec3 halfDir, floa
<$declareSkyboxMap()$>
<@endif@>
vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, vec3 fragEyeDir, vec3 fragNormal, float roughness) {
vec3 lightDir = -reflect(fragEyeDir, fragNormal);
vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface) {
vec3 lightDir = -reflect(surface.eyeDir, surface.normal);
vec3 specularLight;
<@if supportIfAmbientMapElseAmbientSphere@>
if (getLightHasAmbientMap(ambient))
@ -41,8 +42,8 @@ vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, vec3 fragEyeDir, vec3 f
<@if supportAmbientMap@>
{
float levels = getLightAmbientMapNumMips(ambient);
float lod = min(((roughness)* levels), levels);
specularLight = evalSkyboxLight(lightDir, lod).xyz;
float lod = min(((surface.roughness)* levels), levels);
specularLight = evalSkyboxLight(surface.lightDir, lod).xyz;
// We multiply specular by Pi to match specular / diffuse normalization in
// LightingModel.slh where diffuse and specular arent divided by Pi (when they should, rigourously
// speaking, based on physical equations). The spherical harmonics evaluation, on
@ -56,7 +57,7 @@ vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, vec3 fragEyeDir, vec3 f
<@endif@>
<@if supportAmbientSphere@>
{
specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz;
specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), surface.lightDir).xyz;
}
<@endif@>
@ -74,21 +75,21 @@ float curvatureAO(in float k) {
}
<@endif@>
void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, vec3 eyeDir, vec3 normal,
float roughness, float metallic, vec3 fresnelF0, vec3 albedo, float obscurance
void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface,
float metallic, vec3 fresnelF0, vec3 albedo, float obscurance
<@if supportScattering@>
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
<@endif@>
) {
// Fresnel
vec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, eyeDir, normal, 1.0 - roughness);
vec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface);
// Diffuse from ambient
diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), normal).xyz;
diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), surface.normal).xyz;
// Specular highlight from ambient
specular = evalAmbientSpecularIrradiance(ambient, eyeDir, normal, roughness) * ambientFresnel;
specular = evalAmbientSpecularIrradiance(ambient, surface) * ambientFresnel;
<@if supportScattering@>
if (scattering * isScatteringEnabled() > 0.0) {

View file

@ -12,7 +12,7 @@
<@func declareLightingDirectional(supportScattering)@>
void evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance,
vec3 eyeDir, vec3 normal, float roughness,
SurfaceData surface,
float metallic, vec3 fresnel, vec3 albedo, float shadow
<@if supportScattering@>
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
@ -22,14 +22,17 @@ void evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir,
// Attenuation
vec3 lightEnergy = shadow * lightIrradiance;
evalFragShading(diffuse, specular, normal, -lightDir, eyeDir, metallic, fresnel, roughness, albedo
updateSurfaceDataWithLight(surface, -lightDir);
evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@>
);
diffuse *= lightEnergy * isDiffuseEnabled() * isDirectionalEnabled();
specular *= lightEnergy * isSpecularEnabled() * isDirectionalEnabled();
lightEnergy *= isDirectionalEnabled();
diffuse *= lightEnergy * isDiffuseEnabled();
specular *= lightEnergy * isSpecularEnabled();
}
<@endfunc@>

View file

@ -12,7 +12,7 @@
<@func declareLightingPoint(supportScattering)@>
void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,
vec4 fragLightDirLen, vec3 fragEyeDir, vec3 normal, float roughness,
vec4 fragLightDirLen, SurfaceData surface,
float metallic, vec3 fresnel, vec3 albedo, float shadow
<@if supportScattering@>
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
@ -23,19 +23,22 @@ void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,
float fragLightDistance = fragLightDirLen.w;
vec3 fragLightDir = fragLightDirLen.xyz;
updateSurfaceDataWithLight(surface, fragLightDir);
// Eval attenuation
float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);
vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light);
// Eval shading
evalFragShading(diffuse, specular, normal, fragLightDir, fragEyeDir, metallic, fresnel, roughness, albedo
evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@>
);
diffuse *= lightEnergy * isDiffuseEnabled() * isPointEnabled();
specular *= lightEnergy * isSpecularEnabled() * isPointEnabled();
lightEnergy *= isPointEnabled();
diffuse *= lightEnergy * isDiffuseEnabled();
specular *= lightEnergy * isSpecularEnabled();
if (isShowLightContour() > 0.0) {
// Show edge

View file

@ -12,7 +12,7 @@
<@func declareLightingSpot(supportScattering)@>
void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,
vec4 fragLightDirLen, float cosSpotAngle, vec3 fragEyeDir, vec3 normal, float roughness,
vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface,
float metallic, vec3 fresnel, vec3 albedo, float shadow
<@if supportScattering@>
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
@ -23,6 +23,7 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,
float fragLightDistance = fragLightDirLen.w;
vec3 fragLightDir = fragLightDirLen.xyz;
updateSurfaceDataWithLight(surface, fragLightDir);
// Eval attenuation
float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);
@ -30,14 +31,15 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light,
vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light);
// Eval shading
evalFragShading(diffuse, specular, normal, fragLightDir, fragEyeDir, metallic, fresnel, roughness, albedo
evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@>
);
diffuse *= lightEnergy * isDiffuseEnabled() * isSpotEnabled();
specular *= lightEnergy * isSpecularEnabled() * isSpotEnabled();
lightEnergy *= isSpotEnabled();
diffuse *= lightEnergy * isDiffuseEnabled();
specular *= lightEnergy * isSpecularEnabled();
if (isShowLightContour() > 0.0) {
// Show edges

View file

@ -77,6 +77,30 @@ float isWireframeEnabled() {
<@endfunc@>
<$declareLightingModel()$>
struct SurfaceData {
vec3 normal;
vec3 eyeDir;
vec3 lightDir;
vec3 halfDir;
float roughness;
float roughness2;
float roughness4;
float ndotv;
float ndotl;
float ndoth;
float ldoth;
float smithInvG1NdotV;
};
<@if not GETFRESNEL0@>
<@def GETFRESNEL0@>
vec3 getFresnelF0(float metallic, vec3 metalF0) {
// Enable continuous metallness value by lerping between dielectric
// and metal fresnel F0 value based on the "metallic" parameter
return mix(vec3(0.03), metalF0, metallic);
}
<@endif@>
<@func declareBeckmannSpecular()@>
uniform sampler2D scatteringSpecularBeckmann;
@ -85,17 +109,13 @@ float fetchSpecularBeckmann(float ndoth, float roughness) {
return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);
}
vec2 skinSpecular(vec3 N, vec3 L, vec3 V, float roughness, float intensity) {
vec2 skinSpecular(SurfaceData surface, float intensity) {
vec2 result = vec2(0.0, 1.0);
float ndotl = dot(N, L);
if (ndotl > 0.0) {
vec3 h = L + V;
vec3 H = normalize(h);
float ndoth = dot(N, H);
float PH = fetchSpecularBeckmann(ndoth, roughness);
float F = fresnelSchlickScalar(0.028, H, V);
float frSpec = max(PH * F / dot(h, h), 0.0);
result.x = ndotl * intensity * frSpec;
if (surface.ndotl > 0.0) {
float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness);
float F = fresnelSchlickScalar(0.028, surface);
float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0);
result.x = surface.ndotl * intensity * frSpec;
result.y -= F;
}
@ -105,83 +125,105 @@ vec2 skinSpecular(vec3 N, vec3 L, vec3 V, float roughness, float intensity) {
<@func declareEvalPBRShading()@>
vec3 fresnelSchlickColor(vec3 fresnelColor, vec3 lightDir, vec3 halfDir) {
float base = 1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0);
float evalSmithInvG1(float roughness4, float ndotd) {
return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4));
}
SurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) {
SurfaceData surface;
surface.eyeDir = eyeDir;
surface.normal = normal;
surface.lightDir = vec3(0,0,0);
surface.halfDir = vec3(0,0,0);
surface.roughness = mix(0.001, 1.0, roughness);
surface.roughness2 = surface.roughness * surface.roughness;
surface.roughness4 = surface.roughness2 * surface.roughness2;
surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0);
surface.ndoth = 0.0;
surface.ndotl = 0.0;
surface.ldoth = 0.0;
surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv);
return surface;
}
void updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) {
surface.lightDir = lightDir;
surface.halfDir = normalize(surface.eyeDir + lightDir);
vec3 dots;
dots.x = dot(surface.normal, surface.halfDir);
dots.y = dot(surface.normal, surface.lightDir);
dots.z = dot(surface.halfDir, surface.lightDir);
dots = clamp(dots, vec3(0), vec3(1));
surface.ndoth = dots.x;
surface.ndotl = dots.y;
surface.ldoth = dots.z;
}
vec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) {
float base = 1.0 - surface.ldoth;
//float exponential = pow(base, 5.0);
float base2 = base * base;
float exponential = base * base2 * base2;
return vec3(exponential) + fresnelColor * (1.0 - exponential);
}
float fresnelSchlickScalar(float fresnelScalar, vec3 lightDir, vec3 halfDir) {
float base = 1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0);
float fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) {
float base = 1.0 - surface.ldoth;
//float exponential = pow(base, 5.0);
float base2 = base * base;
float exponential = base * base2 * base2;
return (exponential) + fresnelScalar * (1.0 - exponential);
}
float specularDistribution(float roughness, vec3 normal, vec3 halfDir, vec3 eyeDir, float ndotl) {
float specularDistribution(SurfaceData surface) {
// See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf
// for details of equations, especially page 20
float ndoth = dot(halfDir, normal);
float ndotv = dot(eyeDir, normal);
vec3 nd = clamp(vec3(ndoth, ndotv, ndotl), vec3(0.0), vec3(1.0));
vec3 nd2 = nd * nd;
float roughness2 = mix(0.001, 1.0, roughness);
roughness2 *= roughness2; // pow 2
float roughness4 = roughness2;
roughness4 *= roughness4; // pow 4
float denom = (nd2.x * (roughness2 - 1.0) + 1.0);
float denom = (surface.ndoth*surface.ndoth * (surface.roughness2 - 1.0) + 1.0);
denom *= denom;
// Add geometric factors G1(n,l) and G1(n,v)
float oneMinusRoughness4 = 1.0-roughness4;
vec2 invG = nd.yz + sqrt(vec2(roughness4)+nd2.yz*oneMinusRoughness4);
denom *= invG.x * invG.y;
float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);
denom *= surface.smithInvG1NdotV * smithInvG1NdotL;
// Don't divide by PI as diffuse isn't either. The real PBR formula normalizes
// by PI on both but if we decide to not do it, it is just as if we
// multiplied all our lights by PI
//denom *= 3.1415926;
float power = roughness4 / denom;
float power = surface.roughness4 / denom;
return power;
}
// Frag Shading returns the diffuse amount as W and the specular rgb as xyz
vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float metallic, vec3 fresnel, float roughness) {
vec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {
// Incident angle attenuation
float angleAttenuation = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0);
float angleAttenuation = surface.ndotl;
// Specular Lighting
vec3 halfDir = normalize(fragEyeDir + fragLightDir);
vec3 fresnelColor = fresnelSchlickColor(fresnel, fragLightDir, halfDir);
float power = specularDistribution(roughness, fragNormal, halfDir, fragEyeDir, angleAttenuation);
vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);
float power = specularDistribution(surface);
vec3 specular = fresnelColor * power * angleAttenuation;
return vec4(specular, (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x));
}
// Frag Shading returns the diffuse amount as W and the specular rgb as xyz
vec4 evalPBRShadingDielectric(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float roughness, float fresnel) {
vec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {
// Incident angle attenuation
float angleAttenuation = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0);
float angleAttenuation = surface.ndotl;
// Specular Lighting
vec3 halfDir = normalize(fragEyeDir + fragLightDir);
float fresnelScalar = fresnelSchlickScalar(fresnel, fragLightDir, halfDir);
float power = specularDistribution(roughness, fragNormal, halfDir, fragEyeDir, angleAttenuation);
float fresnelScalar = fresnelSchlickScalar(fresnel, surface);
float power = specularDistribution(surface);
vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;
return vec4(specular, angleAttenuation * (1.0 - fresnelScalar));
}
vec4 evalPBRShadingMetallic(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float roughness, vec3 fresnel) {
vec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {
// Incident angle attenuation
float angleAttenuation = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0);
float angleAttenuation = surface.ndotl;
// Specular Lighting
vec3 halfDir = normalize(fragEyeDir + fragLightDir);
vec3 fresnelColor = fresnelSchlickColor(fresnel, fragLightDir, halfDir);
float power = specularDistribution(roughness, fragNormal, halfDir, fragEyeDir, angleAttenuation);
vec3 fresnelColor = fresnelSchlickColor(fresnel, surface);
float power = specularDistribution(surface);
vec3 specular = fresnelColor * power * angleAttenuation;
return vec4(specular, 0.f);
@ -193,15 +235,9 @@ vec4 evalPBRShadingMetallic(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir,
<$declareEvalPBRShading()$>
// Return xyz the specular/reflection component and w the diffuse component
//vec4 evalFragShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float metallic, vec3 fresnel, float roughness) {
// return evalPBRShading(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness);
//}
void evalFragShading(out vec3 diffuse, out vec3 specular,
vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir,
float metallic, vec3 fresnel, float roughness, vec3 albedo) {
vec4 shading = evalPBRShading(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness);
float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {
vec4 shading = evalPBRShading(metallic, fresnel, surface);
diffuse = vec3(shading.w);
if (isAlbedoEnabled() > 0.0) {
diffuse *= albedo;
@ -215,22 +251,19 @@ void evalFragShading(out vec3 diffuse, out vec3 specular,
void evalFragShading(out vec3 diffuse, out vec3 specular,
vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir,
float metallic, vec3 fresnel, float roughness, vec3 albedo,
float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,
float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {
if (scattering * isScatteringEnabled() > 0.0) {
vec3 brdf = evalSkinBRDF(fragLightDir, fragNormal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);
float NdotL = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0);
diffuse = mix(vec3(NdotL), brdf, scattering);
vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);
diffuse = mix(vec3(surface.ndotl), brdf, scattering);
// Specular Lighting
vec3 halfDir = normalize(fragEyeDir + fragLightDir);
vec2 specularBrdf = skinSpecular(fragNormal, fragLightDir, fragEyeDir, roughness, 1.0);
vec2 specularBrdf = skinSpecular(surface, 1.0);
diffuse *= specularBrdf.y;
specular = vec3(specularBrdf.x);
} else {
vec4 shading = evalPBRShading(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness);
vec4 shading = evalPBRShading(metallic, fresnel, surface);
diffuse = vec3(shading.w);
specular = shading.xyz;
}
@ -239,17 +272,15 @@ void evalFragShading(out vec3 diffuse, out vec3 specular,
void evalFragShadingScattering(out vec3 diffuse, out vec3 specular,
vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir,
float metallic, vec3 fresnel, float roughness, vec3 albedo
float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo
,float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
) {
vec3 brdf = evalSkinBRDF(fragLightDir, fragNormal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);
float NdotL = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0);
vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);
float NdotL = surface.ndotl;
diffuse = mix(vec3(NdotL), brdf, scattering);
// Specular Lighting
vec3 halfDir = normalize(fragEyeDir + fragLightDir);
vec2 specularBrdf = skinSpecular(fragNormal, fragLightDir, fragEyeDir, roughness, 1.0);
vec2 specularBrdf = skinSpecular(surface, 1.0);
diffuse *= specularBrdf.y;
specular = vec3(specularBrdf.x);
@ -257,10 +288,9 @@ void evalFragShadingScattering(out vec3 diffuse, out vec3 specular,
}
void evalFragShadingGloss(out vec3 diffuse, out vec3 specular,
vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir,
float metallic, vec3 fresnel, float gloss, vec3 albedo
float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo
) {
vec4 shading = evalPBRShading(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, gloss);
vec4 shading = evalPBRShading(metallic, fresnel, surface);
diffuse = vec3(shading.w);
diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());
specular = shading.xyz;

View file

@ -63,38 +63,6 @@ vec3 scatter(float r) {
<@endfunc@>
<@func declareSkinSpecularLighting()@>
uniform sampler2D scatteringSpecularBeckmann;
float fetchSpecularBeckmann(float ndoth, float roughness) {
return pow( 2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);
}
float fresnelReflectance(vec3 H, vec3 V, float Fo) {
float base = 1.0 - dot(V, H);
float exponential = pow(base, 5.0);
return exponential + Fo * (1.0 - exponential);
}
float skinSpecular(vec3 N, vec3 L, vec3 V, float roughness, float intensity) {
float result = 0.0;
float ndotl = dot(N, L);
if (ndotl > 0.0) {
vec3 h = L + V;
vec3 H = normalize(h);
float ndoth = dot(N, H);
float PH = fetchSpecularBeckmann(ndoth, roughness);
float F = fresnelReflectance(H, V, 0.028);
float frSpec = max(PH * F / dot(h, h), 0.0);
result = ndotl * intensity * frSpec;
}
return result;
}
<@endfunc@>
<@func declareSubsurfaceScatteringIntegrate(NumIntegrationSteps)@>

View file

@ -84,9 +84,8 @@ void main(void) {
// Frag to eye vec
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
// Compute the rougness into gloss2 once:
float fragGloss2 = pow(frag.roughness + 0.001, 4.0);
SurfaceData surface = initSurfaceData(frag.roughness, frag.normal, fragEyeDir);
bool withScattering = (frag.scattering * isScatteringEnabled() > 0.0);
int numLightTouching = 0;
@ -119,16 +118,18 @@ void main(void) {
float fragLightDistance = fragLightDirLen.w;
vec3 fragLightDir = fragLightDirLen.xyz;
updateSurfaceDataWithLight(surface, fragLightDir);
// Eval attenuation
float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);
vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);
// Eval shading
if (withScattering) {
evalFragShadingScattering(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo
evalFragShadingScattering(diffuse, specular, frag.metallic, frag.fresnel, surface, frag.albedo
,frag.scattering, midNormalCurvature, lowNormalCurvature );
} else {
evalFragShadingGloss(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, fragGloss2, frag.albedo);
evalFragShadingGloss(diffuse, specular, frag.metallic, frag.fresnel, surface, frag.albedo);
}
diffuse *= lightEnergy * isDiffuseEnabled();
@ -173,6 +174,8 @@ void main(void) {
float fragLightDistance = fragLightDirLen.w;
vec3 fragLightDir = fragLightDirLen.xyz;
updateSurfaceDataWithLight(surface, fragLightDir);
// Eval attenuation
float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);
float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);
@ -180,10 +183,10 @@ void main(void) {
// Eval shading
if (withScattering) {
evalFragShadingScattering(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo
evalFragShadingScattering(diffuse, specular, frag.metallic, frag.fresnel, surface, frag.albedo
,frag.scattering, midNormalCurvature, lowNormalCurvature );
} else {
evalFragShadingGloss(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, fragGloss2, frag.albedo);
evalFragShadingGloss(diffuse, specular, frag.metallic, frag.fresnel, surface, frag.albedo);
}
diffuse *= lightEnergy * isDiffuseEnabled();

View file

@ -50,13 +50,7 @@ void main(void) {
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
float metallic = getMaterialMetallic(mat);
vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value
if (metallic <= 0.5) {
metallic = 0.0;
} else {
fresnel = albedo;
metallic = 1.0;
}
vec3 fresnel = getFresnelF0(metallic, albedo);
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;

View file

@ -60,13 +60,7 @@ void main(void) {
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
float metallic = getMaterialMetallic(mat);
vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value
if (metallic <= 0.5) {
metallic = 0.0;
} else {
fresnel = albedo;
metallic = 1.0;
}
vec3 fresnel = getFresnelF0(metallic, albedo);
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;

View file

@ -40,12 +40,14 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 a
vec3 fragEyeDir;
<$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$>
SurfaceData surface = initSurfaceData(roughness, normal, fragEyeDir);
vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient);
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation);
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse * isDiffuseEnabled() * isDirectionalEnabled();
color += directionalSpecular * isSpecularEnabled() * isDirectionalEnabled();

View file

@ -40,12 +40,14 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 a
vec3 fragEyeDir;
<$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$>
SurfaceData surface = initSurfaceData(roughness, normal, fragEyeDir);
vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient);
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation);
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse;
color += directionalSpecular / opacity;