|
@@ -12,10 +12,6 @@
|
|
|
|
|
|
precision highp float;
|
|
|
|
|
|
-// Constants
|
|
|
-#define RECIPROCAL_PI2 0.15915494
|
|
|
-#define FRESNEL_MAXIMUM_ON_ROUGH 0.25
|
|
|
-
|
|
|
uniform vec3 vEyePosition;
|
|
|
uniform vec3 vAmbientColor;
|
|
|
uniform vec3 vReflectionColor;
|
|
@@ -40,223 +36,12 @@ uniform vec4 vCameraInfos;
|
|
|
uniform vec4 vOverloadedShadowIntensity;
|
|
|
#endif
|
|
|
|
|
|
-#ifdef USESPHERICALFROMREFLECTIONMAP
|
|
|
- uniform vec3 vSphericalX;
|
|
|
- uniform vec3 vSphericalY;
|
|
|
- uniform vec3 vSphericalZ;
|
|
|
- uniform vec3 vSphericalXX;
|
|
|
- uniform vec3 vSphericalYY;
|
|
|
- uniform vec3 vSphericalZZ;
|
|
|
- uniform vec3 vSphericalXY;
|
|
|
- uniform vec3 vSphericalYZ;
|
|
|
- uniform vec3 vSphericalZX;
|
|
|
-
|
|
|
- vec3 EnvironmentIrradiance(vec3 normal)
|
|
|
- {
|
|
|
- // Note: 'normal' is assumed to be normalised (or near normalised)
|
|
|
- // This isn't as critical as it is with other calculations (e.g. specular highlight), but the result will be incorrect nonetheless.
|
|
|
-
|
|
|
- // TODO: switch to optimal implementation
|
|
|
- vec3 result =
|
|
|
- vSphericalX * normal.x +
|
|
|
- vSphericalY * normal.y +
|
|
|
- vSphericalZ * normal.z +
|
|
|
- vSphericalXX * normal.x * normal.x +
|
|
|
- vSphericalYY * normal.y * normal.y +
|
|
|
- vSphericalZZ * normal.z * normal.z +
|
|
|
- vSphericalYZ * normal.y * normal.z +
|
|
|
- vSphericalZX * normal.z * normal.x +
|
|
|
- vSphericalXY * normal.x * normal.y;
|
|
|
-
|
|
|
- return result.rgb;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
#if defined(REFLECTION) || defined(REFRACTION)
|
|
|
uniform vec2 vMicrosurfaceTextureLods;
|
|
|
#endif
|
|
|
|
|
|
-// PBR CUSTOM CONSTANTS
|
|
|
-const float kPi = 3.1415926535897932384626433832795;
|
|
|
-const float kRougnhessToAlphaScale = 0.1;
|
|
|
-const float kRougnhessToAlphaOffset = 0.29248125;
|
|
|
-
|
|
|
-#include<helperFunctions>
|
|
|
-
|
|
|
-// Based on Beckamm roughness to Blinn exponent + http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
|
|
|
-float getMipMapIndexFromAverageSlope(float maxMipLevel, float alpha)
|
|
|
-{
|
|
|
- // do not take in account lower mips hence -1... and wait from proper preprocess.
|
|
|
- // formula comes from approximation of the mathematical solution.
|
|
|
- //float mip = maxMipLevel + kRougnhessToAlphaOffset + 0.5 * log2(alpha);
|
|
|
-
|
|
|
- // In the mean time
|
|
|
- // Always [0..1] goes from max mip to min mip in a log2 way.
|
|
|
- // Change 5 to nummip below.
|
|
|
- // http://www.wolframalpha.com/input/?i=x+in+0..1+plot+(+5+%2B+0.3+%2B+0.1+*+5+*+log2(+(1+-+x)+*+(1+-+x)+%2B+0.0005))
|
|
|
- float mip = kRougnhessToAlphaOffset + maxMipLevel + (maxMipLevel * kRougnhessToAlphaScale * log2(alpha));
|
|
|
-
|
|
|
- return clamp(mip, 0., maxMipLevel);
|
|
|
-}
|
|
|
-
|
|
|
-float getMipMapIndexFromAverageSlopeWithPMREM(float maxMipLevel, float alphaG)
|
|
|
-{
|
|
|
- float specularPower = clamp(2. / alphaG - 2., 0.000001, 2048.);
|
|
|
-
|
|
|
- // Based on CubeMapGen for cosine power with 2048 spec default and 0.25 dropoff
|
|
|
- return clamp(- 0.5 * log2(specularPower) + 5.5, 0., maxMipLevel);
|
|
|
-}
|
|
|
-
|
|
|
-// From Microfacet Models for Refraction through Rough Surfaces, Walter et al. 2007
|
|
|
-float smithVisibilityG1_TrowbridgeReitzGGX(float dot, float alphaG)
|
|
|
-{
|
|
|
- float tanSquared = (1.0 - dot * dot) / (dot * dot);
|
|
|
- return 2.0 / (1.0 + sqrt(1.0 + alphaG * alphaG * tanSquared));
|
|
|
-}
|
|
|
-
|
|
|
-float smithVisibilityG_TrowbridgeReitzGGX_Walter(float NdotL, float NdotV, float alphaG)
|
|
|
-{
|
|
|
- return smithVisibilityG1_TrowbridgeReitzGGX(NdotL, alphaG) * smithVisibilityG1_TrowbridgeReitzGGX(NdotV, alphaG);
|
|
|
-}
|
|
|
-
|
|
|
-// Trowbridge-Reitz (GGX)
|
|
|
-// Generalised Trowbridge-Reitz with gamma power=2.0
|
|
|
-float normalDistributionFunction_TrowbridgeReitzGGX(float NdotH, float alphaG)
|
|
|
-{
|
|
|
- // Note: alphaG is average slope (gradient) of the normals in slope-space.
|
|
|
- // It is also the (trigonometric) tangent of the median distribution value, i.e. 50% of normals have
|
|
|
- // a tangent (gradient) closer to the macrosurface than this slope.
|
|
|
- float a2 = Square(alphaG);
|
|
|
- float d = NdotH * NdotH * (a2 - 1.0) + 1.0;
|
|
|
- return a2 / (kPi * d * d);
|
|
|
-}
|
|
|
-
|
|
|
-vec3 fresnelSchlickGGX(float VdotH, vec3 reflectance0, vec3 reflectance90)
|
|
|
-{
|
|
|
- return reflectance0 + (reflectance90 - reflectance0) * pow(clamp(1.0 - VdotH, 0., 1.), 5.0);
|
|
|
-}
|
|
|
-
|
|
|
-vec3 FresnelSchlickEnvironmentGGX(float VdotN, vec3 reflectance0, vec3 reflectance90, float smoothness)
|
|
|
-{
|
|
|
- // Schlick fresnel approximation, extended with basic smoothness term so that rough surfaces do not approach reflectance90 at grazing angle
|
|
|
- float weight = mix(FRESNEL_MAXIMUM_ON_ROUGH, 1.0, smoothness);
|
|
|
- return reflectance0 + weight * (reflectance90 - reflectance0) * pow(clamp(1.0 - VdotN, 0., 1.), 5.0);
|
|
|
-}
|
|
|
-
|
|
|
-// Cook Torance Specular computation.
|
|
|
-vec3 computeSpecularTerm(float NdotH, float NdotL, float NdotV, float VdotH, float roughness, vec3 specularColor)
|
|
|
-{
|
|
|
- float alphaG = convertRoughnessToAverageSlope(roughness);
|
|
|
- float distribution = normalDistributionFunction_TrowbridgeReitzGGX(NdotH, alphaG);
|
|
|
- float visibility = smithVisibilityG_TrowbridgeReitzGGX_Walter(NdotL, NdotV, alphaG);
|
|
|
- visibility /= (4.0 * NdotL * NdotV); // Cook Torance Denominator integated in viibility to avoid issues when visibility function changes.
|
|
|
-
|
|
|
- vec3 fresnel = fresnelSchlickGGX(VdotH, specularColor, vec3(1., 1., 1.));
|
|
|
-
|
|
|
- float specTerm = max(0., visibility * distribution) * NdotL;
|
|
|
- return fresnel * specTerm * kPi; // TODO: audit pi constants
|
|
|
-}
|
|
|
-
|
|
|
-float computeDiffuseTerm(float NdotL, float NdotV, float VdotH, float roughness)
|
|
|
-{
|
|
|
- // Diffuse fresnel falloff as per Disney principled BRDF, and in the spirit of
|
|
|
- // of general coupled diffuse/specular models e.g. Ashikhmin Shirley.
|
|
|
- float diffuseFresnelNV = pow(clamp(1.0 - NdotL, 0.000001, 1.), 5.0);
|
|
|
- float diffuseFresnelNL = pow(clamp(1.0 - NdotV, 0.000001, 1.), 5.0);
|
|
|
- float diffuseFresnel90 = 0.5 + 2.0 * VdotH * VdotH * roughness;
|
|
|
- float diffuseFresnelTerm =
|
|
|
- (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNL) *
|
|
|
- (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNV);
|
|
|
-
|
|
|
-
|
|
|
- return diffuseFresnelTerm * NdotL;
|
|
|
- // PI Test
|
|
|
- // diffuseFresnelTerm /= kPi;
|
|
|
-}
|
|
|
-
|
|
|
-float adjustRoughnessFromLightProperties(float roughness, float lightRadius, float lightDistance)
|
|
|
-{
|
|
|
- // At small angle this approximation works.
|
|
|
- float lightRoughness = lightRadius / lightDistance;
|
|
|
- // Distribution can sum.
|
|
|
- float totalRoughness = clamp(lightRoughness + roughness, 0., 1.);
|
|
|
- return totalRoughness;
|
|
|
-}
|
|
|
-
|
|
|
-float computeDefaultMicroSurface(float microSurface, vec3 reflectivityColor)
|
|
|
-{
|
|
|
- float kReflectivityNoAlphaWorkflow_SmoothnessMax = 0.95;
|
|
|
-
|
|
|
- float reflectivityLuminance = getLuminance(reflectivityColor);
|
|
|
- float reflectivityLuma = sqrt(reflectivityLuminance);
|
|
|
- microSurface = reflectivityLuma * kReflectivityNoAlphaWorkflow_SmoothnessMax;
|
|
|
-
|
|
|
- return microSurface;
|
|
|
-}
|
|
|
-
|
|
|
-vec3 toLinearSpace(vec3 color)
|
|
|
-{
|
|
|
- return vec3(pow(color.r, 2.2), pow(color.g, 2.2), pow(color.b, 2.2));
|
|
|
-}
|
|
|
-
|
|
|
-vec3 toGammaSpace(vec3 color)
|
|
|
-{
|
|
|
- return vec3(pow(color.r, 1.0 / 2.2), pow(color.g, 1.0 / 2.2), pow(color.b, 1.0 / 2.2));
|
|
|
-}
|
|
|
-
|
|
|
-float computeLightFalloff(vec3 lightOffset, float lightDistanceSquared, float range)
|
|
|
-{
|
|
|
- #ifdef USEPHYSICALLIGHTFALLOFF
|
|
|
- float lightDistanceFalloff = 1.0 / ((lightDistanceSquared + 0.0001));
|
|
|
- return lightDistanceFalloff;
|
|
|
- #else
|
|
|
- float lightFalloff = max(0., 1.0 - length(lightOffset) / range);
|
|
|
- return lightFalloff;
|
|
|
- #endif
|
|
|
-}
|
|
|
-
|
|
|
-#ifdef CAMERATONEMAP
|
|
|
- vec3 toneMaps(vec3 color)
|
|
|
- {
|
|
|
- color = max(color, 0.0);
|
|
|
-
|
|
|
- // TONE MAPPING / EXPOSURE
|
|
|
- color.rgb = color.rgb * vCameraInfos.x;
|
|
|
-
|
|
|
- float tuning = 1.5; // TODO: sync up so e.g. 18% greys are matched to exposure appropriately
|
|
|
- // PI Test
|
|
|
- // tuning *= kPi;
|
|
|
- vec3 tonemapped = 1.0 - exp2(-color.rgb * tuning); // simple local photographic tonemapper
|
|
|
- color.rgb = mix(color.rgb, tonemapped, 1.0);
|
|
|
- return color;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef CAMERACONTRAST
|
|
|
- vec4 contrasts(vec4 color)
|
|
|
- {
|
|
|
- color = clamp(color, 0.0, 1.0);
|
|
|
-
|
|
|
- vec3 resultHighContrast = color.rgb * color.rgb * (3.0 - 2.0 * color.rgb);
|
|
|
- float contrast = vCameraInfos.y;
|
|
|
- if (contrast < 1.0)
|
|
|
- {
|
|
|
- // Decrease contrast: interpolate towards zero-contrast image (flat grey)
|
|
|
- color.rgb = mix(vec3(0.5, 0.5, 0.5), color.rgb, contrast);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Increase contrast: apply simple shoulder-toe high contrast curve
|
|
|
- color.rgb = mix(color.rgb, resultHighContrast, contrast - 1.0);
|
|
|
- }
|
|
|
-
|
|
|
- return color;
|
|
|
- }
|
|
|
-#endif
|
|
|
-// END PBR HELPER METHODS
|
|
|
-
|
|
|
- uniform vec4 vReflectivityColor;
|
|
|
- uniform vec3 vEmissiveColor;
|
|
|
+uniform vec4 vReflectivityColor;
|
|
|
+uniform vec3 vEmissiveColor;
|
|
|
|
|
|
// Input
|
|
|
varying vec3 vPositionW;
|
|
@@ -367,177 +152,11 @@ varying vec3 vPositionUVW;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
-// Shadows
|
|
|
-#ifdef SHADOWS
|
|
|
-
|
|
|
-float unpack(vec4 color)
|
|
|
-{
|
|
|
- const vec4 bit_shift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);
|
|
|
- return dot(color, bit_shift);
|
|
|
-}
|
|
|
-
|
|
|
-#if defined(POINTLIGHT0) || defined(POINTLIGHT1) || defined(POINTLIGHT2) || defined(POINTLIGHT3)
|
|
|
-uniform vec2 depthValues;
|
|
|
-
|
|
|
-float computeShadowCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, float bias)
|
|
|
-{
|
|
|
- vec3 directionToLight = vPositionW - lightPosition;
|
|
|
- float depth = length(directionToLight);
|
|
|
- depth = clamp(depth, 0., 1.0);
|
|
|
-
|
|
|
- directionToLight = normalize(directionToLight);
|
|
|
- directionToLight.y = - directionToLight.y;
|
|
|
-
|
|
|
- float shadow = unpack(textureCube(shadowSampler, directionToLight)) + bias;
|
|
|
-
|
|
|
- if (depth > shadow)
|
|
|
- {
|
|
|
-#ifdef OVERLOADEDSHADOWVALUES
|
|
|
- return mix(1.0, darkness, vOverloadedShadowIntensity.x);
|
|
|
-#else
|
|
|
- return darkness;
|
|
|
-#endif
|
|
|
- }
|
|
|
- return 1.0;
|
|
|
-}
|
|
|
-
|
|
|
-float computeShadowWithPCFCube(vec3 lightPosition, samplerCube shadowSampler, float mapSize, float bias, float darkness)
|
|
|
-{
|
|
|
- vec3 directionToLight = vPositionW - lightPosition;
|
|
|
- float depth = length(directionToLight);
|
|
|
-
|
|
|
- depth = (depth - depthValues.x) / (depthValues.y - depthValues.x);
|
|
|
- depth = clamp(depth, 0., 1.0);
|
|
|
-
|
|
|
- directionToLight = normalize(directionToLight);
|
|
|
- directionToLight.y = -directionToLight.y;
|
|
|
-
|
|
|
- float visibility = 1.;
|
|
|
-
|
|
|
- vec3 poissonDisk[4];
|
|
|
- poissonDisk[0] = vec3(-1.0, 1.0, -1.0);
|
|
|
- poissonDisk[1] = vec3(1.0, -1.0, -1.0);
|
|
|
- poissonDisk[2] = vec3(-1.0, -1.0, -1.0);
|
|
|
- poissonDisk[3] = vec3(1.0, -1.0, 1.0);
|
|
|
-
|
|
|
- // Poisson Sampling
|
|
|
- float biasedDepth = depth - bias;
|
|
|
-
|
|
|
- if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[0] * mapSize)) < biasedDepth) visibility -= 0.25;
|
|
|
- if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[1] * mapSize)) < biasedDepth) visibility -= 0.25;
|
|
|
- if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[2] * mapSize)) < biasedDepth) visibility -= 0.25;
|
|
|
- if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[3] * mapSize)) < biasedDepth) visibility -= 0.25;
|
|
|
-
|
|
|
-#ifdef OVERLOADEDSHADOWVALUES
|
|
|
- return min(1.0, mix(1.0, visibility + darkness, vOverloadedShadowIntensity.x));
|
|
|
-#else
|
|
|
- return min(1.0, visibility + darkness);
|
|
|
-#endif
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
-#if defined(SPOTLIGHT0) || defined(SPOTLIGHT1) || defined(SPOTLIGHT2) || defined(SPOTLIGHT3) || defined(DIRLIGHT0) || defined(DIRLIGHT1) || defined(DIRLIGHT2) || defined(DIRLIGHT3)
|
|
|
-float computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler, float darkness, float bias)
|
|
|
-{
|
|
|
- vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
|
|
|
- depth = 0.5 * depth + vec3(0.5);
|
|
|
- vec2 uv = depth.xy;
|
|
|
-
|
|
|
- if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
|
|
|
- {
|
|
|
- return 1.0;
|
|
|
- }
|
|
|
-
|
|
|
- float shadow = unpack(texture2D(shadowSampler, uv)) + bias;
|
|
|
-
|
|
|
- if (depth.z > shadow)
|
|
|
- {
|
|
|
-#ifdef OVERLOADEDSHADOWVALUES
|
|
|
- return mix(1.0, darkness, vOverloadedShadowIntensity.x);
|
|
|
-#else
|
|
|
- return darkness;
|
|
|
-#endif
|
|
|
- }
|
|
|
- return 1.;
|
|
|
-}
|
|
|
-
|
|
|
-float computeShadowWithPCF(vec4 vPositionFromLight, sampler2D shadowSampler, float mapSize, float bias, float darkness)
|
|
|
-{
|
|
|
- vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
|
|
|
- depth = 0.5 * depth + vec3(0.5);
|
|
|
- vec2 uv = depth.xy;
|
|
|
-
|
|
|
- if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
|
|
|
- {
|
|
|
- return 1.0;
|
|
|
- }
|
|
|
-
|
|
|
- float visibility = 1.;
|
|
|
-
|
|
|
- vec2 poissonDisk[4];
|
|
|
- poissonDisk[0] = vec2(-0.94201624, -0.39906216);
|
|
|
- poissonDisk[1] = vec2(0.94558609, -0.76890725);
|
|
|
- poissonDisk[2] = vec2(-0.094184101, -0.92938870);
|
|
|
- poissonDisk[3] = vec2(0.34495938, 0.29387760);
|
|
|
-
|
|
|
- // Poisson Sampling
|
|
|
- float biasedDepth = depth.z - bias;
|
|
|
-
|
|
|
- if (unpack(texture2D(shadowSampler, uv + poissonDisk[0] * mapSize)) < biasedDepth) visibility -= 0.25;
|
|
|
- if (unpack(texture2D(shadowSampler, uv + poissonDisk[1] * mapSize)) < biasedDepth) visibility -= 0.25;
|
|
|
- if (unpack(texture2D(shadowSampler, uv + poissonDisk[2] * mapSize)) < biasedDepth) visibility -= 0.25;
|
|
|
- if (unpack(texture2D(shadowSampler, uv + poissonDisk[3] * mapSize)) < biasedDepth) visibility -= 0.25;
|
|
|
-
|
|
|
-#ifdef OVERLOADEDSHADOWVALUES
|
|
|
- return min(1.0, mix(1.0, visibility + darkness, vOverloadedShadowIntensity.x));
|
|
|
-#else
|
|
|
- return min(1.0, visibility + darkness);
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-// Thanks to http://devmaster.net/
|
|
|
-float unpackHalf(vec2 color)
|
|
|
-{
|
|
|
- return color.x + (color.y / 255.0);
|
|
|
-}
|
|
|
-
|
|
|
-float linstep(float low, float high, float v) {
|
|
|
- return clamp((v - low) / (high - low), 0.0, 1.0);
|
|
|
-}
|
|
|
-
|
|
|
-float ChebychevInequality(vec2 moments, float compare, float bias)
|
|
|
-{
|
|
|
- float p = smoothstep(compare - bias, compare, moments.x);
|
|
|
- float variance = max(moments.y - moments.x * moments.x, 0.02);
|
|
|
- float d = compare - moments.x;
|
|
|
- float p_max = linstep(0.2, 1.0, variance / (variance + d * d));
|
|
|
-
|
|
|
- return clamp(max(p, p_max), 0.0, 1.0);
|
|
|
-}
|
|
|
-
|
|
|
-float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler, float bias, float darkness)
|
|
|
-{
|
|
|
- vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
|
|
|
- depth = 0.5 * depth + vec3(0.5);
|
|
|
- vec2 uv = depth.xy;
|
|
|
-
|
|
|
- if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0 || depth.z >= 1.0)
|
|
|
- {
|
|
|
- return 1.0;
|
|
|
- }
|
|
|
-
|
|
|
- vec4 texel = texture2D(shadowSampler, uv);
|
|
|
-
|
|
|
- vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));
|
|
|
-#ifdef OVERLOADEDSHADOWVALUES
|
|
|
- return min(1.0, mix(1.0, 1.0 - ChebychevInequality(moments, depth.z, bias) + darkness, vOverloadedShadowIntensity.x));
|
|
|
-#else
|
|
|
- return min(1.0, 1.0 - ChebychevInequality(moments, depth.z, bias) + darkness);
|
|
|
-#endif
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
-#endif
|
|
|
+// PBR
|
|
|
+#include<pbrShadowFunctions>
|
|
|
+#include<pbrFunctions>
|
|
|
+#include<harmonicsFunctions>
|
|
|
+#include<pbrLightFunctions>
|
|
|
|
|
|
#include<bumpFragmentFunctions>
|
|
|
#include<clipPlaneFragmentDeclaration>
|
|
@@ -546,137 +165,6 @@ float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler, flo
|
|
|
// Fog
|
|
|
#include<fogFragmentDeclaration>
|
|
|
|
|
|
-// Light Computing
|
|
|
-struct lightingInfo
|
|
|
-{
|
|
|
- vec3 diffuse;
|
|
|
-#ifdef SPECULARTERM
|
|
|
- vec3 specular;
|
|
|
-#endif
|
|
|
-};
|
|
|
-
|
|
|
-lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, float range, float roughness, float NdotV, float lightRadius, out float NdotL) {
|
|
|
- lightingInfo result;
|
|
|
-
|
|
|
- vec3 lightDirection;
|
|
|
- float attenuation = 1.0;
|
|
|
- float lightDistance;
|
|
|
-
|
|
|
- // Point
|
|
|
- if (lightData.w == 0.)
|
|
|
- {
|
|
|
- vec3 lightOffset = lightData.xyz - vPositionW;
|
|
|
- float lightDistanceSquared = dot(lightOffset, lightOffset);
|
|
|
- attenuation = computeLightFalloff(lightOffset, lightDistanceSquared, range);
|
|
|
-
|
|
|
- lightDistance = sqrt(lightDistanceSquared);
|
|
|
- lightDirection = normalize(lightOffset);
|
|
|
- }
|
|
|
- // Directional
|
|
|
- else
|
|
|
- {
|
|
|
- lightDistance = length(-lightData.xyz);
|
|
|
- lightDirection = normalize(-lightData.xyz);
|
|
|
- }
|
|
|
-
|
|
|
- // Roughness
|
|
|
- roughness = adjustRoughnessFromLightProperties(roughness, lightRadius, lightDistance);
|
|
|
-
|
|
|
- // diffuse
|
|
|
- vec3 H = normalize(viewDirectionW + lightDirection);
|
|
|
- NdotL = max(0.00000000001, dot(vNormal, lightDirection));
|
|
|
- float VdotH = clamp(0.00000000001, 1.0, dot(viewDirectionW, H));
|
|
|
-
|
|
|
- float diffuseTerm = computeDiffuseTerm(NdotL, NdotV, VdotH, roughness);
|
|
|
- result.diffuse = diffuseTerm * diffuseColor * attenuation;
|
|
|
-
|
|
|
-#ifdef SPECULARTERM
|
|
|
- // Specular
|
|
|
- float NdotH = max(0.00000000001, dot(vNormal, H));
|
|
|
-
|
|
|
- vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, specularColor);
|
|
|
- result.specular = specTerm * attenuation;
|
|
|
-#endif
|
|
|
-
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
-lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor, float range, float roughness, float NdotV, float lightRadius, out float NdotL) {
|
|
|
- lightingInfo result;
|
|
|
-
|
|
|
- vec3 lightOffset = lightData.xyz - vPositionW;
|
|
|
- vec3 lightVectorW = normalize(lightOffset);
|
|
|
-
|
|
|
- // diffuse
|
|
|
- float cosAngle = max(0.000000000000001, dot(-lightDirection.xyz, lightVectorW));
|
|
|
-
|
|
|
- if (cosAngle >= lightDirection.w)
|
|
|
- {
|
|
|
- cosAngle = max(0., pow(cosAngle, lightData.w));
|
|
|
-
|
|
|
- // Inverse squared falloff.
|
|
|
- float lightDistanceSquared = dot(lightOffset, lightOffset);
|
|
|
- float attenuation = computeLightFalloff(lightOffset, lightDistanceSquared, range);
|
|
|
-
|
|
|
- // Directional falloff.
|
|
|
- attenuation *= cosAngle;
|
|
|
-
|
|
|
- // Roughness.
|
|
|
- float lightDistance = sqrt(lightDistanceSquared);
|
|
|
- roughness = adjustRoughnessFromLightProperties(roughness, lightRadius, lightDistance);
|
|
|
-
|
|
|
- // Diffuse
|
|
|
- vec3 H = normalize(viewDirectionW - lightDirection.xyz);
|
|
|
- NdotL = max(0.00000000001, dot(vNormal, -lightDirection.xyz));
|
|
|
- float VdotH = clamp(dot(viewDirectionW, H), 0.00000000001, 1.0);
|
|
|
-
|
|
|
- float diffuseTerm = computeDiffuseTerm(NdotL, NdotV, VdotH, roughness);
|
|
|
- result.diffuse = diffuseTerm * diffuseColor * attenuation;
|
|
|
-
|
|
|
-#ifdef SPECULARTERM
|
|
|
- // Specular
|
|
|
- float NdotH = max(0.00000000001, dot(vNormal, H));
|
|
|
-
|
|
|
- vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, specularColor);
|
|
|
- result.specular = specTerm * attenuation;
|
|
|
-#endif
|
|
|
-
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
- result.diffuse = vec3(0.);
|
|
|
-#ifdef SPECULARTERM
|
|
|
- result.specular = vec3(0.);
|
|
|
-#endif
|
|
|
-
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
-lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor, float roughness, float NdotV, float lightRadius, out float NdotL) {
|
|
|
- lightingInfo result;
|
|
|
-
|
|
|
- // Roughness
|
|
|
- // Do not touch roughness on hemispheric.
|
|
|
-
|
|
|
- // Diffuse
|
|
|
- NdotL = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
|
|
|
- result.diffuse = mix(groundColor, diffuseColor, NdotL);
|
|
|
-
|
|
|
-#ifdef SPECULARTERM
|
|
|
- // Specular
|
|
|
- vec3 lightVectorW = normalize(lightData.xyz);
|
|
|
- vec3 H = normalize(viewDirectionW + lightVectorW);
|
|
|
- float NdotH = max(0.00000000001, dot(vNormal, H));
|
|
|
- NdotL = max(0.00000000001, NdotL);
|
|
|
- float VdotH = clamp(0.00000000001, 1.0, dot(viewDirectionW, H));
|
|
|
-
|
|
|
- vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, specularColor);
|
|
|
- result.specular = specTerm;
|
|
|
-#endif
|
|
|
-
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
void main(void) {
|
|
|
#include<clipPlaneFragment>
|
|
|
|
|
@@ -790,201 +278,12 @@ void main(void) {
|
|
|
#endif
|
|
|
float notShadowLevel = 1.; // 1 - shadowLevel
|
|
|
float NdotL = -1.;
|
|
|
+ lightingInfo info;
|
|
|
|
|
|
-#ifdef LIGHT0
|
|
|
-#ifndef SPECULARTERM
|
|
|
- vec3 vLightSpecular0 = vec3(0.0);
|
|
|
-#endif
|
|
|
-#ifdef SPOTLIGHT0
|
|
|
- lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, roughness, NdotV, vLightRadiuses[0], NdotL);
|
|
|
-#endif
|
|
|
-#ifdef HEMILIGHT0
|
|
|
- lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightGround0, roughness, NdotV, vLightRadiuses[0], NdotL);
|
|
|
-#endif
|
|
|
-#if defined(POINTLIGHT0) || defined(DIRLIGHT0)
|
|
|
- lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, roughness, NdotV, vLightRadiuses[0], NdotL);
|
|
|
-#endif
|
|
|
-#ifdef SHADOW0
|
|
|
-#ifdef SHADOWVSM0
|
|
|
- notShadowLevel = computeShadowWithVSM(vPositionFromLight0, shadowSampler0, shadowsInfo0.z, shadowsInfo0.x);
|
|
|
-#else
|
|
|
-#ifdef SHADOWPCF0
|
|
|
-#if defined(POINTLIGHT0)
|
|
|
- notShadowLevel = computeShadowWithPCFCube(vLightData0.xyz, shadowSampler0, shadowsInfo0.y, shadowsInfo0.z, shadowsInfo0.x);
|
|
|
-#else
|
|
|
- notShadowLevel = computeShadowWithPCF(vPositionFromLight0, shadowSampler0, shadowsInfo0.y, shadowsInfo0.z, shadowsInfo0.x);
|
|
|
-#endif
|
|
|
-#else
|
|
|
-#if defined(POINTLIGHT0)
|
|
|
- notShadowLevel = computeShadowCube(vLightData0.xyz, shadowSampler0, shadowsInfo0.x, shadowsInfo0.z);
|
|
|
-#else
|
|
|
- notShadowLevel = computeShadow(vPositionFromLight0, shadowSampler0, shadowsInfo0.x, shadowsInfo0.z);
|
|
|
-#endif
|
|
|
-#endif
|
|
|
-#endif
|
|
|
-#else
|
|
|
- notShadowLevel = 1.;
|
|
|
-#endif
|
|
|
- lightDiffuseContribution += info.diffuse * notShadowLevel;
|
|
|
-#ifdef OVERLOADEDSHADOWVALUES
|
|
|
- if (NdotL < 0.000000000011)
|
|
|
- {
|
|
|
- notShadowLevel = 1.;
|
|
|
- }
|
|
|
- shadowedOnlyLightDiffuseContribution *= notShadowLevel;
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef SPECULARTERM
|
|
|
- lightSpecularContribution += info.specular * notShadowLevel;
|
|
|
-#endif
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef LIGHT1
|
|
|
-#ifndef SPECULARTERM
|
|
|
- vec3 vLightSpecular1 = vec3(0.0);
|
|
|
-#endif
|
|
|
-#ifdef SPOTLIGHT1
|
|
|
- info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, roughness, NdotV, vLightRadiuses[1], NdotL);
|
|
|
-#endif
|
|
|
-#ifdef HEMILIGHT1
|
|
|
- info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightGround1, roughness, NdotV, vLightRadiuses[1], NdotL);
|
|
|
-#endif
|
|
|
-#if defined(POINTLIGHT1) || defined(DIRLIGHT1)
|
|
|
- info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, roughness, NdotV, vLightRadiuses[1], NdotL);
|
|
|
-#endif
|
|
|
-#ifdef SHADOW1
|
|
|
-#ifdef SHADOWVSM1
|
|
|
- notShadowLevel = computeShadowWithVSM(vPositionFromLight1, shadowSampler1, shadowsInfo1.z, shadowsInfo1.x);
|
|
|
-#else
|
|
|
-#ifdef SHADOWPCF1
|
|
|
-#if defined(POINTLIGHT1)
|
|
|
- notShadowLevel = computeShadowWithPCFCube(vLightData1.xyz, shadowSampler1, shadowsInfo1.y, shadowsInfo1.z, shadowsInfo1.x);
|
|
|
-#else
|
|
|
- notShadowLevel = computeShadowWithPCF(vPositionFromLight1, shadowSampler1, shadowsInfo1.y, shadowsInfo1.z, shadowsInfo1.x);
|
|
|
-#endif
|
|
|
-#else
|
|
|
-#if defined(POINTLIGHT1)
|
|
|
- notShadowLevel = computeShadowCube(vLightData1.xyz, shadowSampler1, shadowsInfo1.x, shadowsInfo1.z);
|
|
|
-#else
|
|
|
- notShadowLevel = computeShadow(vPositionFromLight1, shadowSampler1, shadowsInfo1.x, shadowsInfo1.z);
|
|
|
-#endif
|
|
|
-#endif
|
|
|
-#endif
|
|
|
-#else
|
|
|
- notShadowLevel = 1.;
|
|
|
-#endif
|
|
|
-
|
|
|
- lightDiffuseContribution += info.diffuse * notShadowLevel;
|
|
|
-#ifdef OVERLOADEDSHADOWVALUES
|
|
|
- if (NdotL < 0.000000000011)
|
|
|
- {
|
|
|
- notShadowLevel = 1.;
|
|
|
- }
|
|
|
- shadowedOnlyLightDiffuseContribution *= notShadowLevel;
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef SPECULARTERM
|
|
|
- lightSpecularContribution += info.specular * notShadowLevel;
|
|
|
-#endif
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef LIGHT2
|
|
|
-#ifndef SPECULARTERM
|
|
|
- vec3 vLightSpecular2 = vec3(0.0);
|
|
|
-#endif
|
|
|
-#ifdef SPOTLIGHT2
|
|
|
- info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, roughness, NdotV, vLightRadiuses[2], NdotL);
|
|
|
-#endif
|
|
|
-#ifdef HEMILIGHT2
|
|
|
- info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightGround2, roughness, NdotV, vLightRadiuses[2], NdotL);
|
|
|
-#endif
|
|
|
-#if defined(POINTLIGHT2) || defined(DIRLIGHT2)
|
|
|
- info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, roughness, NdotV, vLightRadiuses[2], NdotL);
|
|
|
-#endif
|
|
|
-#ifdef SHADOW2
|
|
|
-#ifdef SHADOWVSM2
|
|
|
- notShadowLevel = computeShadowWithVSM(vPositionFromLight2, shadowSampler2, shadowsInfo2.z, shadowsInfo2.x);
|
|
|
-#else
|
|
|
-#ifdef SHADOWPCF2
|
|
|
-#if defined(POINTLIGHT2)
|
|
|
- notShadowLevel = computeShadowWithPCFCube(vLightData2.xyz, shadowSampler2, shadowsInfo2.y, shadowsInfo2.z, shadowsInfo2.x);
|
|
|
-#else
|
|
|
- notShadowLevel = computeShadowWithPCF(vPositionFromLight2, shadowSampler2, shadowsInfo2.y, shadowsInfo2.z, shadowsInfo2.x);
|
|
|
-#endif
|
|
|
-#else
|
|
|
-#if defined(POINTLIGHT2)
|
|
|
- notShadowLevel = computeShadowCube(vLightData2.xyz, shadowSampler2, shadowsInfo2.x, shadowsInfo2.z);
|
|
|
-#else
|
|
|
- notShadowLevel = computeShadow(vPositionFromLight2, shadowSampler2, shadowsInfo2.x, shadowsInfo2.z);
|
|
|
-#endif
|
|
|
-#endif
|
|
|
-#endif
|
|
|
-#else
|
|
|
- notShadowLevel = 1.;
|
|
|
-#endif
|
|
|
-
|
|
|
- lightDiffuseContribution += info.diffuse * notShadowLevel;
|
|
|
-#ifdef OVERLOADEDSHADOWVALUES
|
|
|
- if (NdotL < 0.000000000011)
|
|
|
- {
|
|
|
- notShadowLevel = 1.;
|
|
|
- }
|
|
|
- shadowedOnlyLightDiffuseContribution *= notShadowLevel;
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef SPECULARTERM
|
|
|
- lightSpecularContribution += info.specular * notShadowLevel;
|
|
|
-#endif
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef LIGHT3
|
|
|
-#ifndef SPECULARTERM
|
|
|
- vec3 vLightSpecular3 = vec3(0.0);
|
|
|
-#endif
|
|
|
-#ifdef SPOTLIGHT3
|
|
|
- info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, roughness, NdotV, vLightRadiuses[3], NdotL);
|
|
|
-#endif
|
|
|
-#ifdef HEMILIGHT3
|
|
|
- info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightGround3, roughness, NdotV, vLightRadiuses[3], NdotL);
|
|
|
-#endif
|
|
|
-#if defined(POINTLIGHT3) || defined(DIRLIGHT3)
|
|
|
- info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, roughness, NdotV, vLightRadiuses[3], NdotL);
|
|
|
-#endif
|
|
|
-#ifdef SHADOW3
|
|
|
-#ifdef SHADOWVSM3
|
|
|
- notShadowLevel = computeShadowWithVSM(vPositionFromLight3, shadowSampler3, shadowsInfo3.z, shadowsInfo3.x);
|
|
|
-#else
|
|
|
-#ifdef SHADOWPCF3
|
|
|
-#if defined(POINTLIGHT3)
|
|
|
- notShadowLevel = computeShadowWithPCFCube(vLightData3.xyz, shadowSampler3, shadowsInfo3.y, shadowsInfo3.z, shadowsInfo3.x);
|
|
|
-#else
|
|
|
- notShadowLevel = computeShadowWithPCF(vPositionFromLight3, shadowSampler3, shadowsInfo3.y, shadowsInfo3.z, shadowsInfo3.x);
|
|
|
-#endif
|
|
|
-#else
|
|
|
-#if defined(POINTLIGHT3)
|
|
|
- notShadowLevel = computeShadowCube(vLightData3.xyz, shadowSampler3, shadowsInfo3.x, shadowsInfo3.z);
|
|
|
-#else
|
|
|
- notShadowLevel = computeShadow(vPositionFromLight3, shadowSampler3, shadowsInfo3.x, shadowsInfo3.z);
|
|
|
-#endif
|
|
|
-#endif
|
|
|
-#endif
|
|
|
-#else
|
|
|
- notShadowLevel = 1.;
|
|
|
-#endif
|
|
|
-
|
|
|
- lightDiffuseContribution += info.diffuse * notShadowLevel;
|
|
|
-#ifdef OVERLOADEDSHADOWVALUES
|
|
|
- if (NdotL < 0.000000000011)
|
|
|
- {
|
|
|
- notShadowLevel = 1.;
|
|
|
- }
|
|
|
- shadowedOnlyLightDiffuseContribution *= notShadowLevel;
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef SPECULARTERM
|
|
|
- lightSpecularContribution += info.specular * notShadowLevel;
|
|
|
-#endif
|
|
|
-#endif
|
|
|
+#include<pbrLightFunctionsCall>[0]
|
|
|
+#include<pbrLightFunctionsCall>[1]
|
|
|
+#include<pbrLightFunctionsCall>[2]
|
|
|
+#include<pbrLightFunctionsCall>[3]
|
|
|
|
|
|
#ifdef SPECULARTERM
|
|
|
lightSpecularContribution *= vLightingIntensity.w;
|