From 8a0f3ab01b7beaefa3b2662465ccbd71674ab219 Mon Sep 17 00:00:00 2001 From: Gauthier Billot Date: Wed, 24 May 2017 13:54:12 +0200 Subject: [PATCH] Updated coreData --- res/coreData/RenderPaths/Deferred.xml | 5 +- res/coreData/RenderPaths/DeferredHWDepth.xml | 4 +- res/coreData/RenderPaths/ForwardDepth.xml | 6 +- res/coreData/RenderPaths/ForwardHWDepth.xml | 8 +- res/coreData/RenderPaths/PBRDeferred.xml | 32 ++ .../RenderPaths/PBRDeferredHWDepth.xml | 31 ++ res/coreData/RenderPaths/Prepass.xml | 5 +- res/coreData/RenderPaths/PrepassHWDepth.xml | 4 +- res/coreData/Shaders/GLSL/BRDF.glsl | 135 +++++++ res/coreData/Shaders/GLSL/Constants.glsl | 7 + res/coreData/Shaders/GLSL/DeferredLight.glsl | 8 +- res/coreData/Shaders/GLSL/IBL.glsl | 312 ++++++++++++++++ res/coreData/Shaders/GLSL/Lighting.glsl | 243 +++++++++---- res/coreData/Shaders/GLSL/LitParticle.glsl | 43 ++- res/coreData/Shaders/GLSL/LitSolid.glsl | 24 +- res/coreData/Shaders/GLSL/PBR.glsl | 124 +++++++ res/coreData/Shaders/GLSL/PBRDeferred.glsl | 125 +++++++ res/coreData/Shaders/GLSL/PBRLitSolid.glsl | 261 +++++++++++++ res/coreData/Shaders/GLSL/PrepassLight.glsl | 8 +- res/coreData/Shaders/GLSL/Samplers.glsl | 8 +- res/coreData/Shaders/GLSL/ScreenPos.glsl | 13 +- res/coreData/Shaders/GLSL/Shadow.glsl | 21 +- res/coreData/Shaders/GLSL/ShadowBlur.glsl | 34 ++ res/coreData/Shaders/GLSL/Skybox.glsl | 6 +- res/coreData/Shaders/GLSL/Skydome.glsl | 19 + res/coreData/Shaders/GLSL/TerrainBlend.glsl | 12 +- res/coreData/Shaders/GLSL/Text.glsl | 106 ++++-- res/coreData/Shaders/GLSL/Transform.glsl | 112 +++++- res/coreData/Shaders/GLSL/Uniforms.glsl | 49 ++- res/coreData/Shaders/GLSL/Unlit.glsl | 1 + res/coreData/Shaders/GLSL/UnlitParticle.glsl | 90 +++++ res/coreData/Shaders/GLSL/Vegetation.glsl | 31 +- res/coreData/Shaders/GLSL/Water.glsl | 9 +- res/coreData/Shaders/HLSL/BRDF.hlsl | 135 +++++++ res/coreData/Shaders/HLSL/Basic.hlsl | 10 +- res/coreData/Shaders/HLSL/Constants.hlsl | 7 + res/coreData/Shaders/HLSL/DeferredLight.hlsl | 10 +- res/coreData/Shaders/HLSL/Depth.hlsl | 13 +- res/coreData/Shaders/HLSL/IBL.hlsl | 305 ++++++++++++++++ res/coreData/Shaders/HLSL/Lighting.hlsl | 211 ++++++++--- res/coreData/Shaders/HLSL/LitParticle.hlsl | 62 +++- res/coreData/Shaders/HLSL/LitSolid.hlsl | 24 +- res/coreData/Shaders/HLSL/PBR.hlsl | 127 +++++++ res/coreData/Shaders/HLSL/PBRDeferred.hlsl | 128 +++++++ res/coreData/Shaders/HLSL/PBRLitSolid.hlsl | 344 ++++++++++++++++++ res/coreData/Shaders/HLSL/PrepassLight.hlsl | 8 +- res/coreData/Shaders/HLSL/Samplers.hlsl | 11 +- res/coreData/Shaders/HLSL/ScreenPos.hlsl | 11 +- res/coreData/Shaders/HLSL/Shadow.hlsl | 41 ++- res/coreData/Shaders/HLSL/ShadowBlur.hlsl | 48 +++ res/coreData/Shaders/HLSL/Skybox.hlsl | 11 +- res/coreData/Shaders/HLSL/Skydome.hlsl | 22 ++ res/coreData/Shaders/HLSL/TerrainBlend.hlsl | 13 +- res/coreData/Shaders/HLSL/Text.hlsl | 80 ++-- res/coreData/Shaders/HLSL/Transform.hlsl | 84 ++++- res/coreData/Shaders/HLSL/Uniforms.hlsl | 40 +- res/coreData/Shaders/HLSL/Unlit.hlsl | 12 +- res/coreData/Shaders/HLSL/UnlitParticle.hlsl | 145 ++++++++ res/coreData/Shaders/HLSL/Vegetation.hlsl | 61 +++- .../Shaders/HLSL/VegetationDepth.hlsl | 20 +- .../Shaders/HLSL/VegetationShadow.hlsl | 20 +- res/coreData/Shaders/HLSL/Water.hlsl | 3 + .../Techniques/DiffAlphaTranslucent.xml | 5 + .../Techniques/DiffLitParticleAlphaSoft.xml | 5 + .../DiffLitParticleAlphaSoftExpand.xml | 5 + res/coreData/Techniques/DiffNormal.xml | 4 +- res/coreData/Techniques/DiffNormalAO.xml | 4 +- res/coreData/Techniques/DiffNormalAOAlpha.xml | 2 +- res/coreData/Techniques/DiffNormalAlpha.xml | 2 +- .../Techniques/DiffNormalAlphaTranslucent.xml | 5 + .../Techniques/DiffNormalEmissive.xml | 4 +- .../Techniques/DiffNormalEmissiveAlpha.xml | 2 +- res/coreData/Techniques/DiffNormalEnvCube.xml | 4 +- .../Techniques/DiffNormalEnvCubeAlpha.xml | 2 +- res/coreData/Techniques/DiffNormalSpec.xml | 4 +- res/coreData/Techniques/DiffNormalSpecAO.xml | 4 +- .../Techniques/DiffNormalSpecAOAlpha.xml | 2 +- .../Techniques/DiffNormalSpecAlpha.xml | 2 +- .../Techniques/DiffNormalSpecEmissive.xml | 4 +- .../DiffNormalSpecEmissiveAlpha.xml | 2 +- .../Techniques/DiffSkyboxHDRScale.xml | 3 + res/coreData/Techniques/DiffSkydome.xml | 3 + .../Techniques/DiffUnlitParticleAdd.xml | 3 + .../Techniques/DiffUnlitParticleAddSoft.xml | 3 + .../DiffUnlitParticleAddSoftExpand.xml | 3 + .../Techniques/DiffUnlitParticleAlpha.xml | 3 + .../Techniques/DiffUnlitParticleAlphaSoft.xml | 3 + .../DiffUnlitParticleAlphaSoftExpand.xml | 3 + res/coreData/Techniques/NoTextureNormal.xml | 4 +- .../Techniques/NoTextureNormalAlpha.xml | 2 +- .../Techniques/PBR/DiffNormalSpecEmissive.xml | 8 + .../PBR/DiffNormalSpecEmissiveAlpha.xml | 5 + res/coreData/Techniques/PBR/PBRDiff.xml | 8 + res/coreData/Techniques/PBR/PBRDiffAlpha.xml | 5 + res/coreData/Techniques/PBR/PBRDiffNormal.xml | 8 + .../Techniques/PBR/PBRDiffNormalAlpha.xml | 5 + .../Techniques/PBR/PBRDiffNormalEmissive.xml | 7 + .../PBR/PBRDiffNormalEmissiveAlpha.xml | 5 + .../PBR/PBRMetallicRoughDiffNormalSpec.xml | 8 + ...PBRMetallicRoughDiffNormalSpecEmissive.xml | 8 + ...tallicRoughDiffNormalSpecEmissiveAlpha.xml | 5 + .../PBR/PBRMetallicRoughDiffSpec.xml | 8 + .../PBR/PBRMetallicRoughDiffSpecAlpha.xml | 5 + res/coreData/Techniques/PBR/PBRNoTexture.xml | 9 + .../Techniques/PBR/PBRNoTextureAlpha.xml | 5 + 105 files changed, 3762 insertions(+), 331 deletions(-) create mode 100644 res/coreData/RenderPaths/PBRDeferred.xml create mode 100644 res/coreData/RenderPaths/PBRDeferredHWDepth.xml create mode 100644 res/coreData/Shaders/GLSL/BRDF.glsl create mode 100644 res/coreData/Shaders/GLSL/Constants.glsl create mode 100644 res/coreData/Shaders/GLSL/IBL.glsl create mode 100644 res/coreData/Shaders/GLSL/PBR.glsl create mode 100644 res/coreData/Shaders/GLSL/PBRDeferred.glsl create mode 100644 res/coreData/Shaders/GLSL/PBRLitSolid.glsl create mode 100644 res/coreData/Shaders/GLSL/ShadowBlur.glsl create mode 100644 res/coreData/Shaders/GLSL/Skydome.glsl create mode 100644 res/coreData/Shaders/GLSL/UnlitParticle.glsl create mode 100644 res/coreData/Shaders/HLSL/BRDF.hlsl create mode 100644 res/coreData/Shaders/HLSL/Constants.hlsl create mode 100644 res/coreData/Shaders/HLSL/IBL.hlsl create mode 100644 res/coreData/Shaders/HLSL/PBR.hlsl create mode 100644 res/coreData/Shaders/HLSL/PBRDeferred.hlsl create mode 100644 res/coreData/Shaders/HLSL/PBRLitSolid.hlsl create mode 100644 res/coreData/Shaders/HLSL/ShadowBlur.hlsl create mode 100644 res/coreData/Shaders/HLSL/Skydome.hlsl create mode 100644 res/coreData/Shaders/HLSL/UnlitParticle.hlsl create mode 100644 res/coreData/Techniques/DiffAlphaTranslucent.xml create mode 100644 res/coreData/Techniques/DiffLitParticleAlphaSoft.xml create mode 100644 res/coreData/Techniques/DiffLitParticleAlphaSoftExpand.xml create mode 100644 res/coreData/Techniques/DiffNormalAlphaTranslucent.xml create mode 100644 res/coreData/Techniques/DiffSkyboxHDRScale.xml create mode 100644 res/coreData/Techniques/DiffSkydome.xml create mode 100644 res/coreData/Techniques/DiffUnlitParticleAdd.xml create mode 100644 res/coreData/Techniques/DiffUnlitParticleAddSoft.xml create mode 100644 res/coreData/Techniques/DiffUnlitParticleAddSoftExpand.xml create mode 100644 res/coreData/Techniques/DiffUnlitParticleAlpha.xml create mode 100644 res/coreData/Techniques/DiffUnlitParticleAlphaSoft.xml create mode 100644 res/coreData/Techniques/DiffUnlitParticleAlphaSoftExpand.xml create mode 100644 res/coreData/Techniques/PBR/DiffNormalSpecEmissive.xml create mode 100644 res/coreData/Techniques/PBR/DiffNormalSpecEmissiveAlpha.xml create mode 100644 res/coreData/Techniques/PBR/PBRDiff.xml create mode 100644 res/coreData/Techniques/PBR/PBRDiffAlpha.xml create mode 100644 res/coreData/Techniques/PBR/PBRDiffNormal.xml create mode 100644 res/coreData/Techniques/PBR/PBRDiffNormalAlpha.xml create mode 100644 res/coreData/Techniques/PBR/PBRDiffNormalEmissive.xml create mode 100644 res/coreData/Techniques/PBR/PBRDiffNormalEmissiveAlpha.xml create mode 100644 res/coreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpec.xml create mode 100644 res/coreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissive.xml create mode 100644 res/coreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissiveAlpha.xml create mode 100644 res/coreData/Techniques/PBR/PBRMetallicRoughDiffSpec.xml create mode 100644 res/coreData/Techniques/PBR/PBRMetallicRoughDiffSpecAlpha.xml create mode 100644 res/coreData/Techniques/PBR/PBRNoTexture.xml create mode 100644 res/coreData/Techniques/PBR/PBRNoTextureAlpha.xml diff --git a/res/coreData/RenderPaths/Deferred.xml b/res/coreData/RenderPaths/Deferred.xml index f0adf8f..bd41960 100644 --- a/res/coreData/RenderPaths/Deferred.xml +++ b/res/coreData/RenderPaths/Deferred.xml @@ -2,6 +2,7 @@ + @@ -18,6 +19,8 @@ - + + + diff --git a/res/coreData/RenderPaths/DeferredHWDepth.xml b/res/coreData/RenderPaths/DeferredHWDepth.xml index 9b3d866..d2391b2 100644 --- a/res/coreData/RenderPaths/DeferredHWDepth.xml +++ b/res/coreData/RenderPaths/DeferredHWDepth.xml @@ -18,6 +18,8 @@ - + + + diff --git a/res/coreData/RenderPaths/ForwardDepth.xml b/res/coreData/RenderPaths/ForwardDepth.xml index 41df160..7cc68a6 100644 --- a/res/coreData/RenderPaths/ForwardDepth.xml +++ b/res/coreData/RenderPaths/ForwardDepth.xml @@ -2,13 +2,15 @@ - + - + + + \ No newline at end of file diff --git a/res/coreData/RenderPaths/ForwardHWDepth.xml b/res/coreData/RenderPaths/ForwardHWDepth.xml index 1306e47..7a518c8 100644 --- a/res/coreData/RenderPaths/ForwardHWDepth.xml +++ b/res/coreData/RenderPaths/ForwardHWDepth.xml @@ -1,14 +1,14 @@ - - - + - + + + \ No newline at end of file diff --git a/res/coreData/RenderPaths/PBRDeferred.xml b/res/coreData/RenderPaths/PBRDeferred.xml new file mode 100644 index 0000000..28bb90c --- /dev/null +++ b/res/coreData/RenderPaths/PBRDeferred.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/coreData/RenderPaths/PBRDeferredHWDepth.xml b/res/coreData/RenderPaths/PBRDeferredHWDepth.xml new file mode 100644 index 0000000..b8922a1 --- /dev/null +++ b/res/coreData/RenderPaths/PBRDeferredHWDepth.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/coreData/RenderPaths/Prepass.xml b/res/coreData/RenderPaths/Prepass.xml index 8b4f7b0..0ff3280 100644 --- a/res/coreData/RenderPaths/Prepass.xml +++ b/res/coreData/RenderPaths/Prepass.xml @@ -2,6 +2,7 @@ + @@ -19,6 +20,8 @@ - + + + diff --git a/res/coreData/RenderPaths/PrepassHWDepth.xml b/res/coreData/RenderPaths/PrepassHWDepth.xml index b11316c..82a8d93 100644 --- a/res/coreData/RenderPaths/PrepassHWDepth.xml +++ b/res/coreData/RenderPaths/PrepassHWDepth.xml @@ -16,6 +16,8 @@ - + + + diff --git a/res/coreData/Shaders/GLSL/BRDF.glsl b/res/coreData/Shaders/GLSL/BRDF.glsl new file mode 100644 index 0000000..b226a4f --- /dev/null +++ b/res/coreData/Shaders/GLSL/BRDF.glsl @@ -0,0 +1,135 @@ +#line 20001 +#ifdef COMPILEPS + #ifdef PBR + // Following BRDF methods are based upon research Frostbite EA + //[Lagrade et al. 2014, "Moving Frostbite to Physically Based Rendering"] + + //Schlick Fresnel + //specular = the rgb specular color value of the pixel + //VdotH = the dot product of the camera view direction and the half vector + vec3 SchlickFresnel(vec3 specular, float VdotH) + { + return specular + (vec3(1.0, 1.0, 1.0) - specular) * pow(1.0 - VdotH, 5.0); + } + + //Schlick Gaussian Fresnel + //specular = the rgb specular color value of the pixel + //VdotH = the dot product of the camera view direction and the half vector + vec3 SchlickGaussianFresnel(in vec3 specular, in float VdotH) + { + float sphericalGaussian = pow(2.0, (-5.55473 * VdotH - 6.98316) * VdotH); + return specular + (vec3(1.0, 1.0, 1.0) - specular) * sphericalGaussian; + } + + //Get Fresnel + //specular = the rgb specular color value of the pixel + //VdotH = the dot product of the camera view direction and the half vector + vec3 Fresnel(vec3 specular, float VdotH) + { + return SchlickFresnel(specular, VdotH); + } + + // Smith GGX corrected Visibility + // NdotL = the dot product of the normal and direction to the light + // NdotV = the dot product of the normal and the camera view direction + // roughness = the roughness of the pixel + float SmithGGXSchlickVisibility(float NdotL, float NdotV, float roughness) + { + float rough2 = roughness * roughness; + float lambdaV = NdotL * sqrt((-NdotV * rough2 + NdotV) * NdotV + rough2); + float lambdaL = NdotV * sqrt((-NdotL * rough2 + NdotL) * NdotL + rough2); + + return 0.5 / (lambdaV + lambdaL); + } + + // Get Visibility + // NdotL = the dot product of the normal and direction to the light + // NdotV = the dot product of the normal and the camera view direction + // roughness = the roughness of the pixel + float Visibility(float NdotL, float NdotV, float roughness) + { + return SmithGGXSchlickVisibility(NdotL, NdotV, roughness); + } + + // Blinn Distribution + // NdotH = the dot product of the normal and the half vector + // roughness = the roughness of the pixel + float BlinnPhongDistribution(in float NdotH, in float roughness) + { + float specPower = max((2.0 / (roughness * roughness)) - 2.0, 1e-4); // Calculate specular power from roughness + return pow(clamp(NdotH, 0.0, 1.0), specPower); + } + + // Beckmann Distribution + // NdotH = the dot product of the normal and the half vector + // roughness = the roughness of the pixel + float BeckmannDistribution(in float NdotH, in float roughness) + { + float rough2 = roughness * roughness; + float roughnessA = 1.0 / (4.0 * rough2 * pow(NdotH, 4.0)); + float roughnessB = NdotH * NdotH - 1.0; + float roughnessC = rough2 * NdotH * NdotH; + return roughnessA * exp(roughnessB / roughnessC); + } + + // GGX Distribution + // NdotH = the dot product of the normal and the half vector + // roughness = the roughness of the pixel + float GGXDistribution(float NdotH, float roughness) + { + float rough2 = roughness * roughness; + float tmp = (NdotH * rough2 - NdotH) * NdotH + 1.0; + return rough2 / (tmp * tmp); + } + + // Get Distribution + // NdotH = the dot product of the normal and the half vector + // roughness = the roughness of the pixel + float Distribution(float NdotH, float roughness) + { + return GGXDistribution(NdotH, roughness); + } + + // Lambertian Diffuse + // diffuseColor = the rgb color value of the pixel + // roughness = the roughness of the pixel + // NdotV = the normal dot with the camera view direction + // NdotL = the normal dot with the light direction + // VdotH = the camera view direction dot with the half vector + vec3 LambertianDiffuse(vec3 diffuseColor, float NdotL) + { + return diffuseColor * NdotL; + } + + // Burley Diffuse + // diffuseColor = the rgb color value of the pixel + // roughness = the roughness of the pixel + // NdotV = the normal dot with the camera view direction + // NdotL = the normal dot with the light direction + // VdotH = the camera view direction dot with the half vector + vec3 BurleyDiffuse(vec3 diffuseColor, float roughness, float NdotV, float NdotL, float VdotH) + { + float energyBias = mix(roughness, 0.0, 0.5); + float energyFactor = mix(roughness, 1.0, 1.0 / 1.51); + float fd90 = energyBias + 2.0 * VdotH * VdotH * roughness; + float f0 = 1.0; + float lightScatter = f0 + (fd90 - f0) * pow(1.0 - NdotL, 5.0); + float viewScatter = f0 + (fd90 - f0) * pow(1.0 - NdotV, 5.0); + + return diffuseColor * lightScatter * viewScatter * energyFactor; + } + + //Get Diffuse + // diffuseColor = the rgb color value of the pixel + // roughness = the roughness of the pixel + // NdotV = the normal dot with the camera view direction + // NdotL = the normal dot with the light direction + // VdotH = the camera view direction dot with the half vector + vec3 Diffuse(vec3 diffuseColor, float roughness, float NdotV, float NdotL, float VdotH) + { + //return LambertianDiffuse(diffuseColor, NdotL); + return BurleyDiffuse(diffuseColor, roughness, NdotV, NdotL, VdotH); + } + + #endif +#endif diff --git a/res/coreData/Shaders/GLSL/Constants.glsl b/res/coreData/Shaders/GLSL/Constants.glsl new file mode 100644 index 0000000..4e83774 --- /dev/null +++ b/res/coreData/Shaders/GLSL/Constants.glsl @@ -0,0 +1,7 @@ +#define M_PI 3.14159265358979323846 +#define M_EPSILON 0.0001 + +#ifdef PBR +#define ROUGHNESS_FLOOR 0.003 +#define METALNESS_FLOOR 0.03 +#endif diff --git a/res/coreData/Shaders/GLSL/DeferredLight.glsl b/res/coreData/Shaders/GLSL/DeferredLight.glsl index 8c22eab..c5e9e49 100644 --- a/res/coreData/Shaders/GLSL/DeferredLight.glsl +++ b/res/coreData/Shaders/GLSL/DeferredLight.glsl @@ -66,6 +66,10 @@ void PS() vec4 normalInput = texture2DProj(sNormalBuffer, vScreenPos); #endif + // Position acquired via near/far ray is relative to camera. Bring position to world space + vec3 eyeVec = -worldPos; + worldPos += cCameraPosPS; + vec3 normal = normalize(normalInput.rgb * 2.0 - 1.0); vec4 projWorldPos = vec4(worldPos, 1.0); vec3 lightColor; @@ -74,7 +78,7 @@ void PS() float diff = GetDiffuse(normal, worldPos, lightDir); #ifdef SHADOW - diff *= GetShadowDeferred(projWorldPos, depth); + diff *= GetShadowDeferred(projWorldPos, normal, depth); #endif #if defined(SPOTLIGHT) @@ -88,7 +92,7 @@ void PS() #endif #ifdef SPECULAR - float spec = GetSpecular(normal, -worldPos, lightDir, normalInput.a * 255.0); + float spec = GetSpecular(normal, eyeVec, lightDir, normalInput.a * 255.0); gl_FragColor = diff * vec4(lightColor * (albedoInput.rgb + spec * cLightColor.a * albedoInput.aaa), 0.0); #else gl_FragColor = diff * vec4(lightColor * albedoInput.rgb, 0.0); diff --git a/res/coreData/Shaders/GLSL/IBL.glsl b/res/coreData/Shaders/GLSL/IBL.glsl new file mode 100644 index 0000000..d84a636 --- /dev/null +++ b/res/coreData/Shaders/GLSL/IBL.glsl @@ -0,0 +1,312 @@ +#line 10001 +#ifdef COMPILEPS + + // + // Legacy Importance Sampled IBL + // + + // vec3 ImportanceSampleSimple(in vec2 Xi, in float roughness, in vec3 T, in vec3 B, in vec3 N) + // { + // float a = roughness * roughness; + // mat3 tbn = mat3(T, B, N); + // #ifdef IBLFAST + // const float blurFactor = 0.0; + // #else + // const float blurFactor = 5.0; + // #endif + // vec2 xx = Xi.xy * blurFactor; + // xx = xx - 1.0 * trunc(xx/1.0); // hlsl style modulo + // vec3 Xi3 = mix(vec3(0,0,1), normalize(vec3(xx, 1.0)), a); + // vec3 XiWS = tbn * Xi3; + // return normalize(N + XiWS); + // } + + // // Karis '13 + // vec3 ImportanceSampleGGX(in vec2 Xi, in float roughness, in vec3 T, in vec3 B, in vec3 N) + // { + // float a = roughness * roughness; + // float Phi = 2.0 * M_PI * Xi.x; + // float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); + // float SinTheta = sqrt(1.0 - CosTheta * CosTheta); + // vec3 H = vec3(0,0,0); + // H.x = SinTheta * cos(Phi); + // H.y = SinTheta * sin(Phi); + // H.z = CosTheta; + + // vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + // vec3 TangentX = normalize(cross(UpVector, N)); + // vec3 TangentY = cross(N, TangentX); + // // Tangent to world space + // return TangentX * H.x + TangentY * H.y + N * H.z; + // } + + // #ifdef IBLFAST + // #define IMPORTANCE_SAMPLES 1 + // #else + // #define IMPORTANCE_SAMPLES 4 + // #endif + + // #define IMPORTANCE_KERNEL_SIZE 16 + // vec2 IMPORTANCE_KERNEL[IMPORTANCE_KERNEL_SIZE] = vec2[] ( + // vec2(-0.0780436, 0.0558389), + // vec2(0.034318, -0.0635879), + // vec2(0.00230821, 0.0807279), + // vec2(0.0124638, 0.117585), + // vec2(0.093943, -0.0944602), + // vec2(0.139348, -0.109816), + // vec2(-0.181872, -0.129649), + // vec2(0.240066, -0.0494057), + // vec2(0.115965, -0.0374714), + // vec2(-0.294819, -0.100726), + // vec2(-0.149652, 0.37459), + // vec2(0.261695, -0.292813), + // vec2(-0.37944, -0.425145), + // vec2(0.628994, -0.189387), + // vec2(-0.331257, -0.646864), + // vec2(-0.467004, 0.439687) + // ); + + // float GetMipFromRougness(float roughness) + // { + // float smoothness = 1.0 - roughness; + // return (1.0 - smoothness * smoothness) * 10.0; + // } + + // /// Perform importance sampling + // /// reflectVec: calculated vector of reflection + // /// wsNormal: world-space normal of the surface + // /// toCamera: direction from the pixel to the camera + // /// specular: specular color + // /// roughness: surface roughness + // /// reflectionCubeColor: output color for diffuse + // // Implementation based on Epics 2013 course notes + // vec3 ImportanceSampling(in vec3 reflectVec, in vec3 tangent, in vec3 bitangent, in vec3 wsNormal, in vec3 toCamera, in vec3 diffColor, in vec3 specColor, in float roughness, inout vec3 reflectionCubeColor) + // { + // reflectionCubeColor = vec3(1,1,1); + + // vec3 reflectSpec = normalize(GetSpecularDominantDir(wsNormal, reflectVec, roughness)); + + // vec3 V = normalize(-toCamera); + // vec3 N = normalize(wsNormal); + // float ndv = clamp(abs(dot(N, V)), 0.0, 1.0); + + // float specMipLevel = GetMipFromRougness(roughness); + + // vec3 accumulatedColor = vec3(0,0,0); + // for (int i = 0; i < IMPORTANCE_SAMPLES; ++i) + // { + // vec3 kd = vec3(1,1,1); + // vec3 diffuseFactor = vec3(0,0,0); + // vec3 specularFactor = vec3(0,0,0); + + // { + // // Diffuse IBL + // const float rough = 1.0; + // const float mipLevel = 9.0; + + // vec3 H = ImportanceSampleSimple(IMPORTANCE_KERNEL[i], rough, tangent, bitangent, N); + // vec3 L = 2.0 * dot( V, H ) * H - V; + + // float vdh = clamp(abs(dot(V, H)), 0.0, 1.0); + // float ndh = clamp(abs(dot(N, H)), 0.0, 1.0); + // float ndl = clamp(abs(dot(N, L)), 0.0, 1.0); + + // vec3 sampledColor = textureLod(sZoneCubeMap, L, mipLevel).rgb; + + // vec3 diffuseTerm = Diffuse(diffColor, rough, ndv, ndl, vdh); + // vec3 lightTerm = sampledColor; + + // diffuseFactor = lightTerm * diffuseTerm; + // } + + // { + // // Specular IBL + // float rough = roughness; + // float mipLevel = specMipLevel; + + // vec3 H = ImportanceSampleSimple(IMPORTANCE_KERNEL[i], rough, tangent, bitangent, N); + // vec3 L = 2.0 * dot( V, H ) * H - V; + // vec3 sampledColor = textureLod(sZoneCubeMap, L, mipLevel).rgb; + + // float vdh = clamp(abs(dot(V, H)), 0.0, 1.0); + // float ndh = clamp(abs(dot(N, H)), 0.0, 1.0); + // float ndl = clamp(abs(dot(N, L)), 0.0, 1.0); + + // vec3 fresnelTerm = Fresnel(specColor, vdh); + // float distTerm = 1.0; // Optimization, this term is mathematically cancelled out -- Distribution(ndh, roughness); + // float visTerm = Visibility(ndl, ndv, rough); + + // vec3 lightTerm = sampledColor * ndl; + + // float pdf = ndl > 0.05 ? ImportanceSamplePDF(distTerm, ndh, vdh) : 4.0; // reduce artifacts at extreme grazing angles + + // vec3 specularTerm = SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndv); + + // // energy conservation: + // // Specular conservation: + // specularFactor = lightTerm * specularTerm / pdf; + // specularFactor = max( + // clamp(normalize(specularFactor) * (length(sampledColor * specColor)), 0.0, 1.0), + // specularFactor + // ); + + // // Diffuse conservation: + // //kd = (sampledColor * specColor)/specularFactor; //energy conservation + // kd = 1.0 - specularFactor; + // } + + // accumulatedColor += specularFactor + diffuseFactor * kd; + // } + + // return (accumulatedColor / IMPORTANCE_SAMPLES); + // } + + // vec3 ImportanceSamplingSimple(in vec3 reflectVec, in vec3 tangent, in vec3 bitangent, in vec3 wsNormal, in vec3 toCamera, in vec3 diffColor, in vec3 specColor, in float roughness, inout vec3 reflectionCubeColor) + // { + // reflectionCubeColor = vec3(1,1,1); + + // reflectVec = normalize(GetSpecularDominantDir(wsNormal, reflectVec, roughness)); + + // vec3 Hn = normalize(-toCamera + wsNormal); + // float ndv = clamp(dot(-toCamera, wsNormal), 0.0, 1.0); + // float vdh = clamp(dot(-toCamera, Hn), 0.0, 1.0); + // float ndh = clamp(dot(wsNormal, Hn), 0.0, 1.0); + + // vec3 accumulatedColor = vec3(0,0,0); + // for (int i = 0; i < IMPORTANCE_SAMPLES; ++i) + // { + // vec3 kd = vec3(1,1,1); + // vec3 diffuseFactor = vec3(0,0,0); + // vec3 specularFactor = vec3(0,0,0); + + // { + // // Diffuse IBL + // const float rough = 1.0; + // const float mipLevel = 9.0; + + // vec3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, tangent, bitangent, wsNormal); + // vec3 sampleVec = wsNormal + perturb; //perturb by the sample vector + + // vec3 sampledColor = textureLod(sZoneCubeMap, sampleVec, mipLevel).rgb; + // float ndl = clamp(dot(sampleVec, wsNormal), 0.0, 1.0); + + // vec3 diffuseTerm = Diffuse(diffColor, rough, ndv, ndl, vdh); + // vec3 lightTerm = sampledColor; + + // diffuseFactor = lightTerm * diffuseTerm; + // } + + // { + // // Specular IBL + // float rough = roughness; + // float mipLevel = GetMipFromRougness(rough); + + // vec3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, tangent, bitangent, reflectVec); + // vec3 sampleVec = reflectVec + perturb; //perturb by the sample vector + + // vec3 sampledColor = textureCube(sZoneCubeMap, sampleVec, mipLevel).rgb; + // float ndl = clamp(dot(sampleVec, wsNormal), 0.0, 1.0); + + // vec3 fresnelTerm = SchlickFresnel(specColor, ndh) ; + // float distTerm = 1.0; //Optimization, this term is mathematically cancelled out //Distribution(ndh, roughness); + // float visTerm = SmithGGXVisibility(ndl, ndv, rough); + // vec3 lightTerm = sampledColor * ndl; + + // float pdf = 1.0; //ImportanceSamplePDF(distTerm, ndh, vdh); + + // specularFactor = lightTerm * SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndv) / pdf; + // specularFactor *= pdf * ndv * (4.0 * ndl * ndv); // hacks + // kd = (1.0 - clamp(specularFactor, 0.0, 1.0)); //energy conservation + // } + + // accumulatedColor += specularFactor + diffuseFactor * kd; + // } + + // return accumulatedColor / IMPORTANCE_SAMPLES; + // } + + /// Determine reflection vector based on surface roughness, rougher uses closer to the normal and smoother uses closer to the reflection vector + /// normal: surface normal + /// reflection: vector of reflection off of the surface + /// roughness: surface roughness + vec3 GetSpecularDominantDir(vec3 normal, vec3 reflection, float roughness) + { + float smoothness = 1.0 - roughness; + float lerpFactor = smoothness * (sqrt(smoothness) + roughness); + return mix(normal, reflection, lerpFactor); + } + + float GetMipFromRoughness(float roughness) + { + float Level = 3 - 1.15 * log2( roughness ); + return 9.0 - 1 - Level; + } + + + vec3 EnvBRDFApprox (vec3 SpecularColor, float Roughness, float NoV) + { + vec4 c0 = vec4(-1, -0.0275, -0.572, 0.022 ); + vec4 c1 = vec4(1, 0.0425, 1.0, -0.04 ); + vec4 r = Roughness * c0 + c1; + float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y; + vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw; + return SpecularColor * AB.x + AB.y; + } + + vec3 FixCubeLookup(vec3 v) + { + float M = max(max(abs(v.x), abs(v.y)), abs(v.z)); + float scale = (1024 - 1) / 1024; + + if (abs(v.x) != M) v.x += scale; + if (abs(v.y) != M) v.y += scale; + if (abs(v.z) != M) v.z += scale; + + return v; + } + + /// Calculate IBL contributation + /// reflectVec: reflection vector for cube sampling + /// wsNormal: surface normal in word space + /// toCamera: normalized direction from surface point to camera + /// roughness: surface roughness + /// ambientOcclusion: ambient occlusion + vec3 ImageBasedLighting(vec3 reflectVec, vec3 tangent, vec3 bitangent, vec3 wsNormal, vec3 toCamera, vec3 diffColor, vec3 specColor, float roughness, inout vec3 reflectionCubeColor) + { + reflectVec = GetSpecularDominantDir(wsNormal, reflectVec, roughness); + float ndv = clamp(dot(-toCamera, wsNormal), 0.0, 1.0); + + // PMREM Mipmapmode https://seblagarde.wordpress.com/2012/06/10/amd-cubemapgen-for-physically-based-rendering/ + //float GlossScale = 16.0; + //float GlossBias = 5.0; + float mipSelect = GetMipFromRoughness(roughness); //exp2(GlossScale * roughness * roughness + GlossBias) - exp2(GlossBias); + + // OpenGL ES does not support textureLod without extensions and does not have the sZoneCubeMap sampler, + // so for now, sample without explicit LOD, and from the environment sampler, where the zone texture will be put + // on mobile hardware + #ifndef GL_ES + vec3 cube = textureLod(sZoneCubeMap, FixCubeLookup(reflectVec), mipSelect).rgb; + vec3 cubeD = textureLod(sZoneCubeMap, FixCubeLookup(wsNormal), 9.0).rgb; + #else + vec3 cube = textureCube(sEnvCubeMap, FixCubeLookup(reflectVec)).rgb; + vec3 cubeD = textureCube(sEnvCubeMap, FixCubeLookup(wsNormal)).rgb; + #endif + + // Fake the HDR texture + float brightness = clamp(cAmbientColor.a, 0.0, 1.0); + float darknessCutoff = clamp((cAmbientColor.a - 1.0) * 0.1, 0.0, 0.25); + + const float hdrMaxBrightness = 5.0; + vec3 hdrCube = pow(cube + darknessCutoff, vec3(max(1.0, cAmbientColor.a))); + hdrCube += max(vec3(0.0), hdrCube - vec3(1.0)) * hdrMaxBrightness; + + vec3 hdrCubeD = pow(cubeD + darknessCutoff, vec3(max(1.0, cAmbientColor.a))); + hdrCubeD += max(vec3(0.0), hdrCubeD - vec3(1.0)) * hdrMaxBrightness; + + vec3 environmentSpecular = EnvBRDFApprox(specColor, roughness, ndv); + vec3 environmentDiffuse = EnvBRDFApprox(diffColor, 1.0, ndv); + + return (hdrCube * environmentSpecular + hdrCubeD * environmentDiffuse) * brightness; + //return ImportanceSampling(reflectVec, tangent, bitangent, wsNormal, toCamera, diffColor, specColor, roughness, reflectionCubeColor); + } +#endif diff --git a/res/coreData/Shaders/GLSL/Lighting.glsl b/res/coreData/Shaders/GLSL/Lighting.glsl index 08157da..76af1d1 100644 --- a/res/coreData/Shaders/GLSL/Lighting.glsl +++ b/res/coreData/Shaders/GLSL/Lighting.glsl @@ -16,7 +16,11 @@ float GetVertexLight(int index, vec3 worldPos, vec3 normal) // Directional light if (invRange == 0.0) { - float NdotL = max(dot(normal, lightDir), 0.0); + #ifdef TRANSLUCENT + float NdotL = abs(dot(normal, lightDir)); + #else + float NdotL = max(dot(normal, lightDir), 0.0); + #endif return NdotL; } // Point/spot light @@ -25,7 +29,11 @@ float GetVertexLight(int index, vec3 worldPos, vec3 normal) vec3 lightVec = (lightPos - worldPos) * invRange; float lightDist = length(lightVec); vec3 localDir = lightVec / lightDist; - float NdotL = max(dot(normal, localDir), 0.0); + #ifdef TRANSLUCENT + float NdotL = abs(dot(normal, localDir)); + #else + float NdotL = max(dot(normal, localDir), 0.0); + #endif float atten = clamp(1.0 - lightDist * lightDist, 0.0, 1.0); float spotEffect = dot(localDir, lightDir); float spotAtten = clamp((spotEffect - cutoff) * invCutoff, 0.0, 1.0); @@ -66,8 +74,23 @@ float GetVertexLightVolumetric(int index, vec3 worldPos) #define NUMCASCADES 1 #endif -vec4 GetShadowPos(int index, vec4 projWorldPos) +vec4 GetShadowPos(int index, vec3 normal, vec4 projWorldPos) { + #ifdef NORMALOFFSET + float normalOffsetScale[4]; + normalOffsetScale[0] = cNormalOffsetScale.x; + normalOffsetScale[1] = cNormalOffsetScale.y; + normalOffsetScale[2] = cNormalOffsetScale.z; + normalOffsetScale[3] = cNormalOffsetScale.w; + + #ifdef DIRLIGHT + float cosAngle = clamp(1.0 - dot(normal, cLightDir), 0.0, 1.0); + #else + float cosAngle = clamp(1.0 - dot(normal, normalize(cLightPos.xyz - projWorldPos.xyz)), 0.0, 1.0); + #endif + projWorldPos.xyz += cosAngle * normalOffsetScale[index] * normal; + #endif + #if defined(DIRLIGHT) return projWorldPos * cLightMatrices[index]; #elif defined(SPOTLIGHT) @@ -85,15 +108,50 @@ float GetDiffuse(vec3 normal, vec3 worldPos, out vec3 lightDir) { #ifdef DIRLIGHT lightDir = cLightDirPS; - return max(dot(normal, lightDir), 0.0); + #ifdef TRANSLUCENT + return abs(dot(normal, lightDir)); + #else + return max(dot(normal, lightDir), 0.0); + #endif #else vec3 lightVec = (cLightPosPS.xyz - worldPos) * cLightPosPS.w; float lightDist = length(lightVec); lightDir = lightVec / lightDist; - return max(dot(normal, lightDir), 0.0) * texture2D(sLightRampMap, vec2(lightDist, 0.0)).r; + #ifdef TRANSLUCENT + return abs(dot(normal, lightDir)) * texture2D(sLightRampMap, vec2(lightDist, 0.0)).r; + #else + return max(dot(normal, lightDir), 0.0) * texture2D(sLightRampMap, vec2(lightDist, 0.0)).r; + #endif #endif } +float GetAtten(vec3 normal, vec3 worldPos, out vec3 lightDir) +{ + lightDir = cLightDirPS; + return clamp(dot(normal, lightDir), 0.0, 1.0); +} + +float GetAttenPoint(vec3 normal, vec3 worldPos, out vec3 lightDir) +{ + vec3 lightVec = (cLightPosPS.xyz - worldPos) * cLightPosPS.w; + float lightDist = length(lightVec); + float falloff = pow(clamp(1.0 - pow(lightDist / 1.0, 4.0), 0.0, 1.0), 2.0) * 3.14159265358979323846 / (4.0 * 3.14159265358979323846)*(pow(lightDist, 2.0) + 1.0); + lightDir = lightVec / lightDist; + return clamp(dot(normal, lightDir), 0.0, 1.0) * falloff; + +} + +float GetAttenSpot(vec3 normal, vec3 worldPos, out vec3 lightDir) +{ + vec3 lightVec = (cLightPosPS.xyz - worldPos) * cLightPosPS.w; + float lightDist = length(lightVec); + float falloff = pow(clamp(1.0 - pow(lightDist / 1.0, 4.0), 0.0, 1.0), 2.0) / (pow(lightDist, 2.0) + 1.0); + + lightDir = lightVec / lightDist; + return clamp(dot(normal, lightDir), 0.0, 1.0) * falloff; + +} + float GetDiffuseVolumetric(vec3 worldPos) { #ifdef DIRLIGHT @@ -107,7 +165,7 @@ float GetDiffuseVolumetric(vec3 worldPos) float GetSpecular(vec3 normal, vec3 eyeVec, vec3 lightDir, float specularPower) { - vec3 halfVec = normalize(normalize(eyeVec) + lightDir); + vec3 halfVec = normalize(normalize(eyeVec) + lightDir); return pow(max(dot(normal, halfVec), 0.0), specularPower); } @@ -124,54 +182,88 @@ float GetIntensity(vec3 color) #define NUMCASCADES 1 #endif +#ifdef VSM_SHADOW +float ReduceLightBleeding(float min, float p_max) +{ + return clamp((p_max - min) / (1.0 - min), 0.0, 1.0); +} + +float Chebyshev(vec2 Moments, float depth) +{ + //One-tailed inequality valid if depth > Moments.x + float p = float(depth <= Moments.x); + //Compute variance. + float Variance = Moments.y - (Moments.x * Moments.x); + + float minVariance = cVSMShadowParams.x; + Variance = max(Variance, minVariance); + //Compute probabilistic upper bound. + float d = depth - Moments.x; + float p_max = Variance / (Variance + d*d); + // Prevent light bleeding + p_max = ReduceLightBleeding(cVSMShadowParams.y, p_max); + + return max(p, p_max); +} +#endif + +#ifndef GL_ES float GetShadow(vec4 shadowPos) { - #ifndef GL_ES - #ifndef LQSHADOW - // Take four samples and average them - // Note: in case of sampling a point light cube shadow, we optimize out the w divide as it has already been performed - #ifndef POINTLIGHT - vec2 offsets = cShadowMapInvSize * shadowPos.w; - #else - vec2 offsets = cShadowMapInvSize; - #endif - #ifndef GL3 - return cShadowIntensity.y + cShadowIntensity.x * (shadow2DProj(sShadowMap, shadowPos).r + - shadow2DProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)).r + - shadow2DProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r + - shadow2DProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw)).r); - #else - return cShadowIntensity.y + cShadowIntensity.x * (textureProj(sShadowMap, shadowPos) + - textureProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)) + - textureProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)) + - textureProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw))); - #endif + #if defined(SIMPLE_SHADOW) + // Take one sample + #ifndef GL3 + float inLight = shadow2DProj(sShadowMap, shadowPos).r; #else - // Take one sample - #ifndef GL3 - float inLight = shadow2DProj(sShadowMap, shadowPos).r; - #else - float inLight = textureProj(sShadowMap, shadowPos); - #endif - return cShadowIntensity.y + cShadowIntensity.x * inLight; + float inLight = textureProj(sShadowMap, shadowPos); #endif - #else - #ifndef LQSHADOW - // Take four samples and average them + return cShadowIntensity.y + cShadowIntensity.x * inLight; + #elif defined(PCF_SHADOW) + // Take four samples and average them + // Note: in case of sampling a point light cube shadow, we optimize out the w divide as it has already been performed + #ifndef POINTLIGHT vec2 offsets = cShadowMapInvSize * shadowPos.w; - vec4 inLight = vec4( - texture2DProj(sShadowMap, shadowPos).r * shadowPos.w > shadowPos.z, - texture2DProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)).r * shadowPos.w > shadowPos.z, - texture2DProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r * shadowPos.w > shadowPos.z, - texture2DProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw)).r * shadowPos.w > shadowPos.z - ); - return cShadowIntensity.y + dot(inLight, vec4(cShadowIntensity.x)); #else - // Take one sample - return cShadowIntensity.y + (texture2DProj(sShadowMap, shadowPos).r * shadowPos.w > shadowPos.z ? cShadowIntensity.x : 0.0); + vec2 offsets = cShadowMapInvSize; + #endif + #ifndef GL3 + return cShadowIntensity.y + cShadowIntensity.x * (shadow2DProj(sShadowMap, shadowPos).r + + shadow2DProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)).r + + shadow2DProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r + + shadow2DProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw)).r); + #else + return cShadowIntensity.y + cShadowIntensity.x * (textureProj(sShadowMap, shadowPos) + + textureProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)) + + textureProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)) + + textureProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw))); #endif + #elif defined(VSM_SHADOW) + vec2 samples = texture2D(sShadowMap, shadowPos.xy / shadowPos.w).rg; + return cShadowIntensity.y + cShadowIntensity.x * Chebyshev(samples, shadowPos.z / shadowPos.w); #endif } +#else +float GetShadow(highp vec4 shadowPos) +{ + #if defined(SIMPLE_SHADOW) + // Take one sample + return cShadowIntensity.y + (texture2DProj(sShadowMap, shadowPos).r * shadowPos.w > shadowPos.z ? cShadowIntensity.x : 0.0); + #elif defined(PCF_SHADOW) + // Take four samples and average them + vec2 offsets = cShadowMapInvSize * shadowPos.w; + vec4 inLight = vec4( + texture2DProj(sShadowMap, shadowPos).r * shadowPos.w > shadowPos.z, + texture2DProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)).r * shadowPos.w > shadowPos.z, + texture2DProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r * shadowPos.w > shadowPos.z, + texture2DProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw)).r * shadowPos.w > shadowPos.z + ); + return cShadowIntensity.y + dot(inLight, vec4(cShadowIntensity.x)); + #elif defined(VSM_SHADOW) + vec2 samples = texture2D(sShadowMap, shadowPos.xy / shadowPos.w).rg; + return cShadowIntensity.y + cShadowIntensity.x * Chebyshev(samples, shadowPos.z / shadowPos.w); + #endif +} +#endif #ifdef POINTLIGHT float GetPointShadow(vec3 lightVec) @@ -218,32 +310,48 @@ float GetDirShadow(const vec4 iShadowPos[NUMCASCADES], float depth) return GetDirShadowFade(GetShadow(shadowPos), depth); } #else -float GetDirShadow(const vec4 iShadowPos[NUMCASCADES], float depth) +float GetDirShadow(const highp vec4 iShadowPos[NUMCASCADES], float depth) { return GetDirShadowFade(GetShadow(iShadowPos[0]), depth); } #endif #ifndef GL_ES -float GetDirShadowDeferred(vec4 projWorldPos, float depth) +float GetDirShadowDeferred(vec4 projWorldPos, vec3 normal, float depth) { vec4 shadowPos; - if (depth < cShadowSplits.x) - shadowPos = projWorldPos * cLightMatricesPS[0]; - else if (depth < cShadowSplits.y) - shadowPos = projWorldPos * cLightMatricesPS[1]; - else if (depth < cShadowSplits.z) - shadowPos = projWorldPos * cLightMatricesPS[2]; - else - shadowPos = projWorldPos * cLightMatricesPS[3]; + #ifdef NORMALOFFSET + float cosAngle = clamp(1.0 - dot(normal, cLightDirPS), 0.0, 1.0); + if (depth < cShadowSplits.x) + shadowPos = vec4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.x * normal, 1.0) * cLightMatricesPS[0]; + else if (depth < cShadowSplits.y) + shadowPos = vec4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.y * normal, 1.0) * cLightMatricesPS[1]; + else if (depth < cShadowSplits.z) + shadowPos = vec4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.z * normal, 1.0) * cLightMatricesPS[2]; + else + shadowPos = vec4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.w * normal, 1.0) * cLightMatricesPS[3]; + #else + if (depth < cShadowSplits.x) + shadowPos = projWorldPos * cLightMatricesPS[0]; + else if (depth < cShadowSplits.y) + shadowPos = projWorldPos * cLightMatricesPS[1]; + else if (depth < cShadowSplits.z) + shadowPos = projWorldPos * cLightMatricesPS[2]; + else + shadowPos = projWorldPos * cLightMatricesPS[3]; + #endif return GetDirShadowFade(GetShadow(shadowPos), depth); } #endif #endif -float GetShadow(vec4 iShadowPos[NUMCASCADES], float depth) +#ifndef GL_ES +float GetShadow(const vec4 iShadowPos[NUMCASCADES], float depth) +#else +float GetShadow(const highp vec4 iShadowPos[NUMCASCADES], float depth) +#endif { #if defined(DIRLIGHT) return GetDirShadow(iShadowPos, depth); @@ -255,16 +363,23 @@ float GetShadow(vec4 iShadowPos[NUMCASCADES], float depth) } #ifndef GL_ES -float GetShadowDeferred(vec4 projWorldPos, float depth) +float GetShadowDeferred(vec4 projWorldPos, vec3 normal, float depth) { - #if defined(DIRLIGHT) - return GetDirShadowDeferred(projWorldPos, depth); - #elif defined(SPOTLIGHT) - vec4 shadowPos = projWorldPos * cLightMatricesPS[1]; - return GetShadow(shadowPos); + #ifdef DIRLIGHT + return GetDirShadowDeferred(projWorldPos, normal, depth); #else - vec3 shadowPos = projWorldPos.xyz - cLightPosPS.xyz; - return GetPointShadow(shadowPos); + #ifdef NORMALOFFSET + float cosAngle = clamp(1.0 - dot(normal, normalize(cLightPosPS.xyz - projWorldPos.xyz)), 0.0, 1.0); + projWorldPos.xyz += cosAngle * cNormalOffsetScalePS.x * normal; + #endif + + #ifdef SPOTLIGHT + vec4 shadowPos = projWorldPos * cLightMatricesPS[1]; + return GetShadow(shadowPos); + #else + vec3 shadowPos = projWorldPos.xyz - cLightPosPS.xyz; + return GetPointShadow(shadowPos); + #endif #endif } #endif diff --git a/res/coreData/Shaders/GLSL/LitParticle.glsl b/res/coreData/Shaders/GLSL/LitParticle.glsl index ca759db..5659f8b 100644 --- a/res/coreData/Shaders/GLSL/LitParticle.glsl +++ b/res/coreData/Shaders/GLSL/LitParticle.glsl @@ -1,6 +1,7 @@ #include "Uniforms.glsl" #include "Samplers.glsl" #include "Transform.glsl" +#include "ScreenPos.glsl" #include "Lighting.glsl" #include "Fog.glsl" @@ -9,9 +10,17 @@ varying vec4 vWorldPos; #ifdef VERTEXCOLOR varying vec4 vColor; #endif +#ifdef SOFTPARTICLES + varying vec4 vScreenPos; + uniform float cSoftParticleFadeScale; +#endif #ifdef PERPIXEL #ifdef SHADOW - varying vec4 vShadowPos[NUMCASCADES]; + #ifndef GL_ES + varying vec4 vShadowPos[NUMCASCADES]; + #else + varying highp vec4 vShadowPos[NUMCASCADES]; + #endif #endif #ifdef SPOTLIGHT varying vec4 vSpotPos; @@ -31,6 +40,10 @@ void VS() vTexCoord = GetTexCoord(iTexCoord); vWorldPos = vec4(worldPos, GetDepth(gl_Position)); + #ifdef SOFTPARTICLES + vScreenPos = GetScreenPos(gl_Position); + #endif + #ifdef VERTEXCOLOR vColor = iColor; #endif @@ -42,7 +55,7 @@ void VS() #ifdef SHADOW // Shadow projection: transform from world space to shadow space for (int i = 0; i < NUMCASCADES; i++) - vShadowPos[i] = GetShadowPos(i, projWorldPos); + vShadowPos[i] = GetShadowPos(i, vec3(0, 0, 0), projWorldPos); #endif #ifdef SPOTLIGHT @@ -89,6 +102,32 @@ void PS() float fogFactor = GetFogFactor(vWorldPos.w); #endif + // Soft particle fade + // In expand mode depth test should be off. In that case do manual alpha discard test first to reduce fill rate + #ifdef SOFTPARTICLES + #ifdef EXPAND + if (diffColor.a < 0.01) + discard; + #endif + + float particleDepth = vWorldPos.w; + #ifdef HWDEPTH + float depth = ReconstructDepth(texture2DProj(sDepthBuffer, vScreenPos).r); + #else + float depth = DecodeDepth(texture2DProj(sDepthBuffer, vScreenPos).rgb); + #endif + + #ifdef EXPAND + float diffZ = max(particleDepth - depth, 0.0) * (cFarClipPS - cNearClipPS); + float fade = clamp(diffZ * cSoftParticleFadeScale, 0.0, 1.0); + #else + float diffZ = (depth - particleDepth) * (cFarClipPS - cNearClipPS); + float fade = clamp(1.0 - diffZ * cSoftParticleFadeScale, 0.0, 1.0); + #endif + + diffColor.a = max(diffColor.a - fade, 0.0); + #endif + #ifdef PERPIXEL // Per-pixel forward lighting vec3 lightColor; diff --git a/res/coreData/Shaders/GLSL/LitSolid.glsl b/res/coreData/Shaders/GLSL/LitSolid.glsl index aa60a98..3a6008e 100644 --- a/res/coreData/Shaders/GLSL/LitSolid.glsl +++ b/res/coreData/Shaders/GLSL/LitSolid.glsl @@ -18,7 +18,11 @@ varying vec4 vWorldPos; #endif #ifdef PERPIXEL #ifdef SHADOW - varying vec4 vShadowPos[NUMCASCADES]; + #ifndef GL_ES + varying vec4 vShadowPos[NUMCASCADES]; + #else + varying highp vec4 vShadowPos[NUMCASCADES]; + #endif #endif #ifdef SPOTLIGHT varying vec4 vSpotPos; @@ -50,10 +54,10 @@ void VS() #endif #ifdef NORMALMAP - vec3 tangent = GetWorldTangent(modelMatrix); - vec3 bitangent = cross(tangent, vNormal) * iTangent.w; + vec4 tangent = GetWorldTangent(modelMatrix); + vec3 bitangent = cross(tangent.xyz, vNormal) * tangent.w; vTexCoord = vec4(GetTexCoord(iTexCoord), bitangent.xy); - vTangent = vec4(tangent, bitangent.z); + vTangent = vec4(tangent.xyz, bitangent.z); #else vTexCoord = GetTexCoord(iTexCoord); #endif @@ -65,12 +69,12 @@ void VS() #ifdef SHADOW // Shadow projection: transform from world space to shadow space for (int i = 0; i < NUMCASCADES; i++) - vShadowPos[i] = GetShadowPos(i, projWorldPos); + vShadowPos[i] = GetShadowPos(i, vNormal, projWorldPos); #endif #ifdef SPOTLIGHT // Spotlight projection: transform from world space to projector texture coordinates - vSpotPos = projWorldPos * cLightMatrices[0]; + vSpotPos = projWorldPos * cLightMatrices[0]; #endif #ifdef POINTLIGHT @@ -82,7 +86,7 @@ void VS() // If using lightmap, disregard zone ambient light // If using AO, calculate ambient in the PS vVertexLight = vec3(0.0, 0.0, 0.0); - vTexCoord2 = iTexCoord2; + vTexCoord2 = iTexCoord1; #else vVertexLight = GetAmbient(GetZonePos(worldPos)); #endif @@ -168,7 +172,7 @@ void PS() #endif #ifdef AMBIENT - finalColor += cAmbientColor * diffColor.rgb; + finalColor += cAmbientColor.rgb * diffColor.rgb; finalColor += cMatEmissiveColor; gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a); #else @@ -188,7 +192,7 @@ void PS() vec3 finalColor = vVertexLight * diffColor.rgb; #ifdef AO // If using AO, the vertex light ambient is black, calculate occluded ambient here - finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor * diffColor.rgb; + finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor.rgb * diffColor.rgb; #endif #ifdef ENVCUBEMAP @@ -212,7 +216,7 @@ void PS() vec3 finalColor = vVertexLight * diffColor.rgb; #ifdef AO // If using AO, the vertex light ambient is black, calculate occluded ambient here - finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor * diffColor.rgb; + finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor.rgb * diffColor.rgb; #endif #ifdef MATERIAL diff --git a/res/coreData/Shaders/GLSL/PBR.glsl b/res/coreData/Shaders/GLSL/PBR.glsl new file mode 100644 index 0000000..46de2c3 --- /dev/null +++ b/res/coreData/Shaders/GLSL/PBR.glsl @@ -0,0 +1,124 @@ +#include "BRDF.glsl" +#ifdef COMPILEPS + + vec3 SphereLight(vec3 worldPos, vec3 lightVec, vec3 normal, vec3 toCamera, float roughness, vec3 specColor, out float ndl) + { + vec3 pos = (cLightPosPS.xyz - worldPos); + float radius = cLightRad; + + vec3 reflectVec = reflect(-toCamera, normal); + vec3 centreToRay = dot(pos, reflectVec) * reflectVec - pos; + vec3 closestPoint = pos + centreToRay * clamp(radius / length(centreToRay), 0.0, 1.0); + + vec3 l = normalize(closestPoint); + vec3 h = normalize(toCamera + l); + + ndl = clamp(dot(normal, l), 0.0, 1.0); + float hdn = clamp(dot(h, normal), 0.0, 1.0); + float hdv = dot(h, toCamera); + float ndv = clamp(dot(normal, toCamera), 0.0, 1.0); + + float distL = length(pos); + float alpha = roughness * roughness; + float alphaPrime = clamp(radius / (distL * 2.0) + alpha, 0.0, 1.0); + + vec3 fresnelTerm = Fresnel(specColor, hdv) ; + float distTerm = Distribution(hdn, alphaPrime); + float visTerm = Visibility(ndl, ndv, roughness); + + return distTerm * visTerm * fresnelTerm ; + } + + vec3 TubeLight(vec3 worldPos, vec3 lightVec, vec3 normal, vec3 toCamera, float roughness, vec3 specColor, out float ndl) + { + float radius = cLightRad; + float len = cLightLength; + vec3 pos = (cLightPosPS.xyz - worldPos); + vec3 reflectVec = reflect(-toCamera, normal); + + vec3 L01 = cLightDirPS * len; + vec3 L0 = pos - 0.5 * L01; + vec3 L1 = pos + 0.5 * L01; + vec3 ld = L1 - L0; + + float distL0 = length( L0 ); + float distL1 = length( L1 ); + + float NoL0 = dot( L0, normal ) / ( 2.0 * distL0 ); + float NoL1 = dot( L1, normal ) / ( 2.0 * distL1 ); + ndl = ( 2.0 * clamp( NoL0 + NoL1, 0.0, 1.0 ) ) + / ( distL0 * distL1 + dot( L0, L1 ) + 2.0 ); + + float a = len * len; + float b = dot( reflectVec, L01 ); + float t = clamp( dot( L0, b * reflectVec - L01 ) / (a - b*b), 0.0, 1.0 ); + + vec3 closestPoint = L0 + ld * clamp(t, 0.0, 1.0); + vec3 centreToRay = dot( closestPoint, reflectVec ) * reflectVec - closestPoint; + closestPoint = closestPoint + centreToRay * clamp(radius / length(centreToRay), 0.0, 1.0); + + vec3 l = normalize(closestPoint); + vec3 h = normalize(toCamera + l); + + ndl = clamp(dot(normal, lightVec), 0.0, 1.0); + float hdn = clamp(dot(h, normal), 0.0, 1.0); + float hdv = dot(h, toCamera); + float ndv = clamp(dot(normal, toCamera), 0.0 ,1.0); + + float distL = length(closestPoint); + float alpha = roughness * roughness; + float alphaPrime = clamp(radius / (distL * 2.0) + alpha, 0.0, 1.0); + + vec3 fresnelTerm = Fresnel(specColor, hdv) ; + float distTerm = Distribution(hdn, alphaPrime); + float visTerm = Visibility(ndl, ndv, roughness); + + return distTerm * visTerm * fresnelTerm ; + } + + //Return the PBR BRDF value + // lightDir = the vector to the light + // lightVev = normalised lightDir + // toCamera = vector to the camera + // normal = surface normal of the pixel + // roughness = roughness of the pixel + // diffColor = the rgb color of the pixel + // specColor = the rgb specular color of the pixel + vec3 GetBRDF(vec3 worldPos, vec3 lightDir, vec3 lightVec, vec3 toCamera, vec3 normal, float roughness, vec3 diffColor, vec3 specColor) + { + vec3 Hn = normalize(toCamera + lightDir); + float vdh = clamp((dot(toCamera, Hn)), M_EPSILON, 1.0); + float ndh = clamp((dot(normal, Hn)), M_EPSILON, 1.0); + float ndl = clamp((dot(normal, lightVec)), M_EPSILON, 1.0); + float ndv = clamp((dot(normal, toCamera)), M_EPSILON, 1.0); + + vec3 diffuseFactor = Diffuse(diffColor, roughness, ndv, ndl, vdh); + vec3 specularFactor = vec3(0.0, 0.0, 0.0); + + #ifdef SPECULAR + if(cLightRad > 0.0) + { + if(cLightLength > 0.0) + { + specularFactor = TubeLight(worldPos, lightVec, normal, toCamera, roughness, specColor, ndl); + specularFactor *= ndl; + } + else + { + specularFactor = SphereLight(worldPos, lightVec, normal, toCamera, roughness, specColor, ndl); + specularFactor *= ndl; + } + } + else + { + vec3 fresnelTerm = Fresnel(specColor, vdh) ; + float distTerm = Distribution(ndh, roughness); + float visTerm = Visibility(ndl, ndv, roughness); + + specularFactor = fresnelTerm * distTerm * visTerm / M_PI; + } + #endif + + return diffuseFactor + specularFactor; + } +#endif diff --git a/res/coreData/Shaders/GLSL/PBRDeferred.glsl b/res/coreData/Shaders/GLSL/PBRDeferred.glsl new file mode 100644 index 0000000..c1222e7 --- /dev/null +++ b/res/coreData/Shaders/GLSL/PBRDeferred.glsl @@ -0,0 +1,125 @@ +#include "Uniforms.glsl" +#include "Samplers.glsl" +#include "Transform.glsl" +#include "ScreenPos.glsl" +#include "Lighting.glsl" +#include "Constants.glsl" +#include "PBR.glsl" +#line 40007 + +#ifdef DIRLIGHT + varying vec2 vScreenPos; +#else + varying vec4 vScreenPos; +#endif +varying vec3 vFarRay; +#ifdef ORTHO + varying vec3 vNearRay; +#endif + +void VS() +{ + mat4 modelMatrix = iModelMatrix; + vec3 worldPos = GetWorldPos(modelMatrix); + gl_Position = GetClipPos(worldPos); + #ifdef DIRLIGHT + vScreenPos = GetScreenPosPreDiv(gl_Position); + vFarRay = GetFarRay(gl_Position); + #ifdef ORTHO + vNearRay = GetNearRay(gl_Position); + #endif + #else + vScreenPos = GetScreenPos(gl_Position); + vFarRay = GetFarRay(gl_Position) * gl_Position.w; + #ifdef ORTHO + vNearRay = GetNearRay(gl_Position) * gl_Position.w; + #endif + #endif +} + + +void PS() +{ + // If rendering a directional light quad, optimize out the w divide + #ifdef DIRLIGHT + vec4 depthInput = texture2D(sDepthBuffer, vScreenPos); + #ifdef HWDEPTH + float depth = ReconstructDepth(depthInput.r); + #else + float depth = DecodeDepth(depthInput.rgb); + #endif + #ifdef ORTHO + vec3 worldPos = mix(vNearRay, vFarRay, depth); + #else + vec3 worldPos = vFarRay * depth; + #endif + vec4 albedoInput = texture2D(sAlbedoBuffer, vScreenPos); + vec4 normalInput = texture2D(sNormalBuffer, vScreenPos); + vec4 specularInput = texture2D(sSpecMap, vScreenPos); + #else + vec4 depthInput = texture2DProj(sDepthBuffer, vScreenPos); + #ifdef HWDEPTH + float depth = ReconstructDepth(depthInput.r); + #else + float depth = DecodeDepth(depthInput.rgb); + #endif + #ifdef ORTHO + vec3 worldPos = mix(vNearRay, vFarRay, depth) / vScreenPos.w; + #else + vec3 worldPos = vFarRay * depth / vScreenPos.w; + #endif + vec4 albedoInput = texture2DProj(sAlbedoBuffer, vScreenPos); + vec4 normalInput = texture2DProj(sNormalBuffer, vScreenPos); + vec4 specularInput = texture2DProj(sSpecMap, vScreenPos); + #endif + + // Position acquired via near/far ray is relative to camera. Bring position to world space + vec3 eyeVec = -worldPos; + worldPos += cCameraPosPS; + + vec3 normal = normalInput.rgb; + float roughness = length(normal); + normal = normalize(normal); + + vec3 specColor = specularInput.rgb; + + vec4 projWorldPos = vec4(worldPos, 1.0); + + vec3 lightDir; + + float atten = 1; + + #if defined(DIRLIGHT) + atten = GetAtten(normal, worldPos, lightDir); + #elif defined(SPOTLIGHT) + atten = GetAttenSpot(normal, worldPos, lightDir); + #else + atten = GetAttenPoint(normal, worldPos, lightDir); + #endif + + float shadow = 1; + #ifdef SHADOW + shadow *= GetShadowDeferred(projWorldPos, normal, depth); + #endif + + #if defined(SPOTLIGHT) + vec4 spotPos = projWorldPos * cLightMatricesPS[0]; + vec3 lightColor = spotPos.w > 0.0 ? texture2DProj(sLightSpotMap, spotPos).rgb * cLightColor.rgb : vec3(0.0); + #elif defined(CUBEMASK) + mat3 lightVecRot = mat3(cLightMatricesPS[0][0].xyz, cLightMatricesPS[0][1].xyz, cLightMatricesPS[0][2].xyz); + vec3 lightColor = textureCube(sLightCubeMap, (worldPos - cLightPosPS.xyz) * lightVecRot).rgb * cLightColor.rgb; + #else + vec3 lightColor = cLightColor.rgb; + #endif + + vec3 toCamera = normalize(eyeVec); + vec3 lightVec = normalize(lightDir); + + float ndl = clamp(abs(dot(normal, lightVec)), M_EPSILON, 1.0); + + vec3 BRDF = GetBRDF(worldPos, lightDir, lightVec, toCamera, normal, roughness, albedoInput.rgb, specColor); + + gl_FragColor.a = 1.0; + gl_FragColor.rgb = BRDF * lightColor * (atten * shadow) / M_PI; + +} diff --git a/res/coreData/Shaders/GLSL/PBRLitSolid.glsl b/res/coreData/Shaders/GLSL/PBRLitSolid.glsl new file mode 100644 index 0000000..0281c88 --- /dev/null +++ b/res/coreData/Shaders/GLSL/PBRLitSolid.glsl @@ -0,0 +1,261 @@ +#include "Uniforms.glsl" +#include "Samplers.glsl" +#include "Transform.glsl" +#include "ScreenPos.glsl" +#include "Lighting.glsl" +#include "Constants.glsl" +#include "Fog.glsl" +#include "PBR.glsl" +#include "IBL.glsl" +#line 30010 + +#if defined(NORMALMAP) || defined(IBL) + varying vec4 vTexCoord; + varying vec4 vTangent; +#else + varying vec2 vTexCoord; +#endif +varying vec3 vNormal; +varying vec4 vWorldPos; +#ifdef VERTEXCOLOR + varying vec4 vColor; +#endif +#ifdef PERPIXEL + #ifdef SHADOW + #ifndef GL_ES + varying vec4 vShadowPos[NUMCASCADES]; + #else + varying highp vec4 vShadowPos[NUMCASCADES]; + #endif + #endif + #ifdef SPOTLIGHT + varying vec4 vSpotPos; + #endif + #ifdef POINTLIGHT + varying vec3 vCubeMaskVec; + #endif +#else + varying vec3 vVertexLight; + varying vec4 vScreenPos; + #ifdef ENVCUBEMAP + varying vec3 vReflectionVec; + #endif + #if defined(LIGHTMAP) || defined(AO) + varying vec2 vTexCoord2; + #endif +#endif + +void VS() +{ + mat4 modelMatrix = iModelMatrix; + vec3 worldPos = GetWorldPos(modelMatrix); + gl_Position = GetClipPos(worldPos); + vNormal = GetWorldNormal(modelMatrix); + vWorldPos = vec4(worldPos, GetDepth(gl_Position)); + + #ifdef VERTEXCOLOR + vColor = iColor; + #endif + + #if defined(NORMALMAP) || defined(DIRBILLBOARD) || defined(IBL) + vec4 tangent = GetWorldTangent(modelMatrix); + vec3 bitangent = cross(tangent.xyz, vNormal) * tangent.w; + vTexCoord = vec4(GetTexCoord(iTexCoord), bitangent.xy); + vTangent = vec4(tangent.xyz, bitangent.z); + #else + vTexCoord = GetTexCoord(iTexCoord); + #endif + + #ifdef PERPIXEL + // Per-pixel forward lighting + vec4 projWorldPos = vec4(worldPos, 1.0); + + #ifdef SHADOW + // Shadow projection: transform from world space to shadow space + for (int i = 0; i < NUMCASCADES; i++) + vShadowPos[i] = GetShadowPos(i, vNormal, projWorldPos); + #endif + + #ifdef SPOTLIGHT + // Spotlight projection: transform from world space to projector texture coordinates + vSpotPos = projWorldPos * cLightMatrices[0]; + #endif + + #ifdef POINTLIGHT + vCubeMaskVec = (worldPos - cLightPos.xyz) * mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz); + #endif + #else + // Ambient & per-vertex lighting + #if defined(LIGHTMAP) || defined(AO) + // If using lightmap, disregard zone ambient light + // If using AO, calculate ambient in the PS + vVertexLight = vec3(0.0, 0.0, 0.0); + vTexCoord2 = iTexCoord1; + #else + vVertexLight = GetAmbient(GetZonePos(worldPos)); + #endif + + #ifdef NUMVERTEXLIGHTS + for (int i = 0; i < NUMVERTEXLIGHTS; ++i) + vVertexLight += GetVertexLight(i, worldPos, vNormal) * cVertexLights[i * 3].rgb; + #endif + + vScreenPos = GetScreenPos(gl_Position); + + #ifdef ENVCUBEMAP + vReflectionVec = worldPos - cCameraPos; + #endif + #endif +} + +void PS() +{ + // Get material diffuse albedo + #ifdef DIFFMAP + vec4 diffInput = texture2D(sDiffMap, vTexCoord.xy); + #ifdef ALPHAMASK + if (diffInput.a < 0.5) + discard; + #endif + vec4 diffColor = cMatDiffColor * diffInput; + #else + vec4 diffColor = cMatDiffColor; + #endif + + #ifdef VERTEXCOLOR + diffColor *= vColor; + #endif + + #ifdef METALLIC + vec4 roughMetalSrc = texture2D(sSpecMap, vTexCoord.xy); + + float roughness = roughMetalSrc.r + cRoughness; + float metalness = roughMetalSrc.g + cMetallic; + #else + float roughness = cRoughness; + float metalness = cMetallic; + #endif + + roughness *= roughness; + + roughness = clamp(roughness, ROUGHNESS_FLOOR, 1.0); + metalness = clamp(metalness, METALNESS_FLOOR, 1.0); + + vec3 specColor = mix(0.08 * cMatSpecColor.rgb, diffColor.rgb, metalness); + diffColor.rgb = diffColor.rgb - diffColor.rgb * metalness; + + // Get normal + #if defined(NORMALMAP) || defined(DIRBILLBOARD) || defined(IBL) + vec3 tangent = vTangent.xyz; + vec3 bitangent = vec3(vTexCoord.zw, vTangent.w); + mat3 tbn = mat3(tangent, bitangent, vNormal); + #endif + + #ifdef NORMALMAP + vec3 nn = DecodeNormal(texture2D(sNormalMap, vTexCoord.xy)); + //nn.rg *= 2.0; + vec3 normal = normalize(tbn * nn); + #else + vec3 normal = normalize(vNormal); + #endif + + // Get fog factor + #ifdef HEIGHTFOG + float fogFactor = GetHeightFogFactor(vWorldPos.w, vWorldPos.y); + #else + float fogFactor = GetFogFactor(vWorldPos.w); + #endif + + #if defined(PERPIXEL) + // Per-pixel forward lighting + vec3 lightColor; + vec3 lightDir; + vec3 finalColor; + + float atten = 1; + + #if defined(DIRLIGHT) + atten = GetAtten(normal, vWorldPos.xyz, lightDir); + #elif defined(SPOTLIGHT) + atten = GetAttenSpot(normal, vWorldPos.xyz, lightDir); + #else + atten = GetAttenPoint(normal, vWorldPos.xyz, lightDir); + #endif + + float shadow = 1.0; + #ifdef SHADOW + shadow = GetShadow(vShadowPos, vWorldPos.w); + #endif + + #if defined(SPOTLIGHT) + lightColor = vSpotPos.w > 0.0 ? texture2DProj(sLightSpotMap, vSpotPos).rgb * cLightColor.rgb : vec3(0.0, 0.0, 0.0); + #elif defined(CUBEMASK) + lightColor = textureCube(sLightCubeMap, vCubeMaskVec).rgb * cLightColor.rgb; + #else + lightColor = cLightColor.rgb; + #endif + vec3 toCamera = normalize(cCameraPosPS - vWorldPos.xyz); + vec3 lightVec = normalize(lightDir); + float ndl = clamp((dot(normal, lightVec)), M_EPSILON, 1.0); + + vec3 BRDF = GetBRDF(vWorldPos.xyz, lightDir, lightVec, toCamera, normal, roughness, diffColor.rgb, specColor); + + finalColor.rgb = BRDF * lightColor * (atten * shadow) / M_PI; + + #ifdef AMBIENT + finalColor += cAmbientColor.rgb * diffColor.rgb; + finalColor += cMatEmissiveColor; + gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a); + #else + gl_FragColor = vec4(GetLitFog(finalColor, fogFactor), diffColor.a); + #endif + #elif defined(DEFERRED) + // Fill deferred G-buffer + const vec3 spareData = vec3(0,0,0); // Can be used to pass more data to deferred renderer + gl_FragData[0] = vec4(specColor, spareData.r); + gl_FragData[1] = vec4(diffColor.rgb, spareData.g); + gl_FragData[2] = vec4(normal * roughness, spareData.b); + gl_FragData[3] = vec4(EncodeDepth(vWorldPos.w), 0.0); + #else + // Ambient & per-vertex lighting + vec3 finalColor = vVertexLight * diffColor.rgb; + #ifdef AO + // If using AO, the vertex light ambient is black, calculate occluded ambient here + finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor.rgb * diffColor.rgb; + #endif + + #ifdef MATERIAL + // Add light pre-pass accumulation result + // Lights are accumulated at half intensity. Bring back to full intensity now + vec4 lightInput = 2.0 * texture2DProj(sLightBuffer, vScreenPos); + vec3 lightSpecColor = lightInput.a * lightInput.rgb / max(GetIntensity(lightInput.rgb), 0.001); + + finalColor += lightInput.rgb * diffColor.rgb + lightSpecColor * specColor; + #endif + + vec3 toCamera = normalize(vWorldPos.xyz - cCameraPosPS); + vec3 reflection = normalize(reflect(toCamera, normal)); + + vec3 cubeColor = vVertexLight.rgb; + + #ifdef IBL + vec3 iblColor = ImageBasedLighting(reflection, tangent, bitangent, normal, toCamera, diffColor.rgb, specColor.rgb, roughness, cubeColor); + float gamma = 0.0; + finalColor.rgb += iblColor; + #endif + + #ifdef ENVCUBEMAP + finalColor += cMatEnvMapColor * textureCube(sEnvCubeMap, reflect(vReflectionVec, normal)).rgb; + #endif + #ifdef LIGHTMAP + finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * diffColor.rgb; + #endif + #ifdef EMISSIVEMAP + finalColor += cMatEmissiveColor * texture2D(sEmissiveMap, vTexCoord.xy).rgb; + #else + finalColor += cMatEmissiveColor; + #endif + + gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a); + #endif +} diff --git a/res/coreData/Shaders/GLSL/PrepassLight.glsl b/res/coreData/Shaders/GLSL/PrepassLight.glsl index 79d8b53..2a2b487 100644 --- a/res/coreData/Shaders/GLSL/PrepassLight.glsl +++ b/res/coreData/Shaders/GLSL/PrepassLight.glsl @@ -63,6 +63,10 @@ void PS() vec4 normalInput = texture2DProj(sNormalBuffer, vScreenPos); #endif + // Position acquired via near/far ray is relative to camera. Bring position to world space + vec3 eyeVec = -worldPos; + worldPos += cCameraPosPS; + vec3 normal = normalize(normalInput.rgb * 2.0 - 1.0); vec4 projWorldPos = vec4(worldPos, 1.0); vec3 lightColor; @@ -72,7 +76,7 @@ void PS() float diff = 0.5 * GetDiffuse(normal, worldPos, lightDir); #ifdef SHADOW - diff *= GetShadowDeferred(projWorldPos, depth); + diff *= GetShadowDeferred(projWorldPos, normal, depth); #endif #if defined(SPOTLIGHT) @@ -86,7 +90,7 @@ void PS() #endif #ifdef SPECULAR - float spec = lightColor.g * GetSpecular(normal, -worldPos, lightDir, normalInput.a * 255.0); + float spec = lightColor.g * GetSpecular(normal, eyeVec, lightDir, normalInput.a * 255.0); gl_FragColor = diff * vec4(lightColor, spec * cLightColor.a); #else gl_FragColor = diff * vec4(lightColor, 0.0); diff --git a/res/coreData/Shaders/GLSL/Samplers.glsl b/res/coreData/Shaders/GLSL/Samplers.glsl index 4cdec39..08d50c4 100644 --- a/res/coreData/Shaders/GLSL/Samplers.glsl +++ b/res/coreData/Shaders/GLSL/Samplers.glsl @@ -15,13 +15,17 @@ uniform samplerCube sLightCubeMap; uniform sampler2D sNormalBuffer; uniform sampler2D sDepthBuffer; uniform sampler2D sLightBuffer; - uniform sampler2DShadow sShadowMap; + #ifdef VSM_SHADOW + uniform sampler2D sShadowMap; + #else + uniform sampler2DShadow sShadowMap; + #endif uniform samplerCube sFaceSelectCubeMap; uniform samplerCube sIndirectionCubeMap; uniform samplerCube sZoneCubeMap; uniform sampler3D sZoneVolumeMap; #else - uniform sampler2D sShadowMap; + uniform highp sampler2D sShadowMap; #endif #ifdef GL3 diff --git a/res/coreData/Shaders/GLSL/ScreenPos.glsl b/res/coreData/Shaders/GLSL/ScreenPos.glsl index b8db5b8..12ebc9c 100644 --- a/res/coreData/Shaders/GLSL/ScreenPos.glsl +++ b/res/coreData/Shaders/GLSL/ScreenPos.glsl @@ -1,4 +1,11 @@ #ifdef COMPILEVS +mat3 GetCameraRot() +{ + return mat3(cViewInv[0][0], cViewInv[0][1], cViewInv[0][2], + cViewInv[1][0], cViewInv[1][1], cViewInv[1][2], + cViewInv[2][0], cViewInv[2][1], cViewInv[2][2]); +} + vec4 GetScreenPos(vec4 clipPos) { return vec4( @@ -36,7 +43,7 @@ vec3 GetFarRay(vec4 clipPos) clipPos.y / clipPos.w * cFrustumSize.y, cFrustumSize.z); - return viewRay * cCameraRot; + return viewRay * GetCameraRot(); } vec3 GetNearRay(vec4 clipPos) @@ -45,7 +52,7 @@ vec3 GetNearRay(vec4 clipPos) clipPos.x / clipPos.w * cFrustumSize.x, clipPos.y / clipPos.w * cFrustumSize.y, 0.0); - - return (viewRay * cCameraRot) * cDepthMode.x; + + return (viewRay * GetCameraRot()) * cDepthMode.x; } #endif diff --git a/res/coreData/Shaders/GLSL/Shadow.glsl b/res/coreData/Shaders/GLSL/Shadow.glsl index 0fea365..4f57e66 100644 --- a/res/coreData/Shaders/GLSL/Shadow.glsl +++ b/res/coreData/Shaders/GLSL/Shadow.glsl @@ -2,23 +2,36 @@ #include "Samplers.glsl" #include "Transform.glsl" -varying vec2 vTexCoord; +#ifdef VSM_SHADOW + varying vec4 vTexCoord; +#else + varying vec2 vTexCoord; +#endif void VS() { mat4 modelMatrix = iModelMatrix; vec3 worldPos = GetWorldPos(modelMatrix); gl_Position = GetClipPos(worldPos); - vTexCoord = GetTexCoord(iTexCoord); + #ifdef VSM_SHADOW + vTexCoord = vec4(GetTexCoord(iTexCoord), gl_Position.z, gl_Position.w); + #else + vTexCoord = GetTexCoord(iTexCoord); + #endif } void PS() { #ifdef ALPHAMASK - float alpha = texture2D(sDiffMap, vTexCoord).a; + float alpha = texture2D(sDiffMap, vTexCoord.xy).a; if (alpha < 0.5) discard; #endif - gl_FragColor = vec4(1.0); + #ifdef VSM_SHADOW + float depth = vTexCoord.z / vTexCoord.w * 0.5 + 0.5; + gl_FragColor = vec4(depth, depth * depth, 1.0, 1.0); + #else + gl_FragColor = vec4(1.0); + #endif } diff --git a/res/coreData/Shaders/GLSL/ShadowBlur.glsl b/res/coreData/Shaders/GLSL/ShadowBlur.glsl new file mode 100644 index 0000000..c4c6e1d --- /dev/null +++ b/res/coreData/Shaders/GLSL/ShadowBlur.glsl @@ -0,0 +1,34 @@ +#include "Uniforms.glsl" +#include "Samplers.glsl" +#include "Transform.glsl" +#include "ScreenPos.glsl" + +#ifdef COMPILEPS +uniform vec2 cBlurOffsets; +#endif + +varying vec2 vScreenPos; + +void VS() +{ + mat4 modelMatrix = iModelMatrix; + vec3 worldPos = GetWorldPos(modelMatrix); + gl_Position = GetClipPos(worldPos); + vScreenPos = GetScreenPosPreDiv(gl_Position); +} + +void PS() +{ + vec2 color = vec2(0.0); + + color += 0.015625 * texture2D(sDiffMap, vScreenPos + vec2(-3.0) * cBlurOffsets).rg; + color += 0.09375 * texture2D(sDiffMap, vScreenPos + vec2(-2.0) * cBlurOffsets).rg; + color += 0.234375 * texture2D(sDiffMap, vScreenPos + vec2(-1.0) * cBlurOffsets).rg; + color += 0.3125 * texture2D(sDiffMap, vScreenPos).rg; + color += 0.234375 * texture2D(sDiffMap, vScreenPos + vec2(1.0) * cBlurOffsets).rg; + color += 0.09375 * texture2D(sDiffMap, vScreenPos + vec2(2.0) * cBlurOffsets).rg; + color += 0.015625 * texture2D(sDiffMap, vScreenPos + vec2(3.0) * cBlurOffsets).rg; + + gl_FragColor = vec4(color, 0.0, 0.0); +} + diff --git a/res/coreData/Shaders/GLSL/Skybox.glsl b/res/coreData/Shaders/GLSL/Skybox.glsl index a5743fc..e5aee3a 100644 --- a/res/coreData/Shaders/GLSL/Skybox.glsl +++ b/res/coreData/Shaders/GLSL/Skybox.glsl @@ -15,5 +15,9 @@ void VS() void PS() { - gl_FragColor = cMatDiffColor * textureCube(sDiffCubeMap, vTexCoord); + vec4 sky = cMatDiffColor * textureCube(sDiffCubeMap, vTexCoord); + #ifdef HDRSCALE + sky = pow(sky + clamp((cAmbientColor.a - 1.0) * 0.1, 0.0, 0.25), max(vec4(cAmbientColor.a), 1.0)) * clamp(cAmbientColor.a, 0.0, 1.0); + #endif + gl_FragColor = sky; } diff --git a/res/coreData/Shaders/GLSL/Skydome.glsl b/res/coreData/Shaders/GLSL/Skydome.glsl new file mode 100644 index 0000000..cc47913 --- /dev/null +++ b/res/coreData/Shaders/GLSL/Skydome.glsl @@ -0,0 +1,19 @@ +#include "Uniforms.glsl" +#include "Samplers.glsl" +#include "Transform.glsl" + +varying vec2 vTexCoord; + +void VS() +{ + mat4 modelMatrix = iModelMatrix; + vec3 worldPos = GetWorldPos(modelMatrix); + gl_Position = GetClipPos(worldPos); + gl_Position.z = gl_Position.w; + vTexCoord = iTexCoord.xy; +} + +void PS() +{ + gl_FragColor = texture2D(sDiffMap, vTexCoord); +} diff --git a/res/coreData/Shaders/GLSL/TerrainBlend.glsl b/res/coreData/Shaders/GLSL/TerrainBlend.glsl index 82e91cc..8ef38c0 100644 --- a/res/coreData/Shaders/GLSL/TerrainBlend.glsl +++ b/res/coreData/Shaders/GLSL/TerrainBlend.glsl @@ -17,7 +17,11 @@ varying vec3 vNormal; varying vec4 vWorldPos; #ifdef PERPIXEL #ifdef SHADOW - varying vec4 vShadowPos[NUMCASCADES]; + #ifndef GL_ES + varying vec4 vShadowPos[NUMCASCADES]; + #else + varying highp vec4 vShadowPos[NUMCASCADES]; + #endif #endif #ifdef SPOTLIGHT varying vec4 vSpotPos; @@ -64,7 +68,7 @@ void VS() #ifdef SHADOW // Shadow projection: transform from world space to shadow space for (int i = 0; i < NUMCASCADES; i++) - vShadowPos[i] = GetShadowPos(i, projWorldPos); + vShadowPos[i] = GetShadowPos(i, vNormal, projWorldPos); #endif #ifdef SPOTLIGHT @@ -81,7 +85,7 @@ void VS() // If using lightmap, disregard zone ambient light // If using AO, calculate ambient in the PS vVertexLight = vec3(0.0, 0.0, 0.0); - vTexCoord2 = iTexCoord2; + vTexCoord2 = iTexCoord1; #else vVertexLight = GetAmbient(GetZonePos(worldPos)); #endif @@ -152,7 +156,7 @@ void PS() #endif #ifdef AMBIENT - finalColor += cAmbientColor * diffColor.rgb; + finalColor += cAmbientColor.rgb * diffColor.rgb; finalColor += cMatEmissiveColor; gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a); #else diff --git a/res/coreData/Shaders/GLSL/Text.glsl b/res/coreData/Shaders/GLSL/Text.glsl index 1fbef08..ec89911 100644 --- a/res/coreData/Shaders/GLSL/Text.glsl +++ b/res/coreData/Shaders/GLSL/Text.glsl @@ -19,46 +19,104 @@ void VS() mat4 modelMatrix = iModelMatrix; vec3 worldPos = GetWorldPos(modelMatrix); gl_Position = GetClipPos(worldPos); - + vTexCoord = iTexCoord; vColor = iColor; } -void PS() -{ - gl_FragColor.rgb = vColor.rgb; +/* + 1) Simplest SDF shader: -#ifdef SIGNED_DISTANCE_FIELD float distance = texture2D(sDiffMap, vTexCoord).a; - if (distance < 0.5) - { - #ifdef TEXT_EFFECT_SHADOW - if (texture2D(sDiffMap, vTexCoord - cShadowOffset).a > 0.5) - gl_FragColor = cShadowColor; - else - #endif - gl_FragColor.a = 0.0; - } + if (distance >= 0.5) + gl_FragColor.a = vColor.a; // This is glyph else + gl_FragColor.a = 0.0; // Outside glyph + + 2) Glyph with antialiazed border: + + float distance = texture2D(sDiffMap, vTexCoord).a; + gl_FragColor.a = vColor.a * smoothstep(0.495, 0.505, distance); + + 3) Quality improvement for far and small text: + + float distance = texture2D(sDiffMap, vTexCoord).a; + // How much "distance" is changed for neighboring pixels. + // If text is far then width is big. Far text will be blurred. + float width = fwidth(distance); + gl_FragColor.a = vColor.a * smoothstep(0.5 - width, 0.5 + width, distance); +*/ + +#if defined(COMPILEPS) && defined(SIGNED_DISTANCE_FIELD) + float GetAlpha(float distance, float width) { + return smoothstep(0.5 - width, 0.5 + width, distance); + } + + // Comment this define to turn off supersampling + #define SUPERSAMPLING +#endif + +void PS() +{ +#ifdef SIGNED_DISTANCE_FIELD + gl_FragColor.rgb = vColor.rgb; + float distance = texture2D(sDiffMap, vTexCoord).a; + #ifdef TEXT_EFFECT_STROKE - if (distance < 0.525) - gl_FragColor.rgb = cStrokeColor.rgb; + #ifdef SUPERSAMPLING + float outlineFactor = smoothstep(0.5, 0.525, distance); // Border of glyph + gl_FragColor.rgb = mix(cStrokeColor.rgb, vColor.rgb, outlineFactor); + #else + if (distance < 0.525) + gl_FragColor.rgb = cStrokeColor.rgb; + #endif #endif #ifdef TEXT_EFFECT_SHADOW - if (texture2D(sDiffMap, vTexCoord + cShadowOffset).a < 0.5) - gl_FragColor.a = vColor.a; + if (texture2D(sDiffMap, vTexCoord - cShadowOffset).a > 0.5 && distance <= 0.5) + gl_FragColor = cShadowColor; + #ifndef SUPERSAMPLING + else if (distance <= 0.5) + gl_FragColor.a = 0; + #endif else #endif - gl_FragColor.a = vColor.a * smoothstep(0.5, 0.505, distance); - } + { + float width = fwidth(distance); + float alpha = GetAlpha(distance, width); + + #ifdef SUPERSAMPLING + vec2 deltaUV = 0.354 * fwidth(vTexCoord); // (1.0 / sqrt(2.0)) / 2.0 = 0.354 + vec4 square = vec4(vTexCoord - deltaUV, vTexCoord + deltaUV); + + float distance2 = texture2D(sDiffMap, square.xy).a; + float distance3 = texture2D(sDiffMap, square.zw).a; + float distance4 = texture2D(sDiffMap, square.xw).a; + float distance5 = texture2D(sDiffMap, square.zy).a; + + alpha += GetAlpha(distance2, width) + + GetAlpha(distance3, width) + + GetAlpha(distance4, width) + + GetAlpha(distance5, width); + + // For calculating of average correct would be dividing by 5. + // But when text is blurred, its brightness is lost. Therefore divide by 4. + alpha = alpha * 0.25; + #endif + + gl_FragColor.a = alpha; + } #else - // Non-SDF font will likely be monochrome, in which case the alpha channel will be on the R channel on OpenGL 3 - #ifdef GL3 - gl_FragColor.a = vColor.a * texture2D(sDiffMap, vTexCoord).r; + #ifdef ALPHAMAP + gl_FragColor.rgb = vColor.rgb; + #ifdef GL3 + gl_FragColor.a = vColor.a * texture2D(sDiffMap, vTexCoord).r; + #else + gl_FragColor.a = vColor.a * texture2D(sDiffMap, vTexCoord).a; + #endif #else - gl_FragColor.a = vColor.a * texture2D(sDiffMap, vTexCoord).a; + gl_FragColor = vColor * texture2D(sDiffMap, vTexCoord); #endif #endif } diff --git a/res/coreData/Shaders/GLSL/Transform.glsl b/res/coreData/Shaders/GLSL/Transform.glsl index ebb45a4..5799137 100644 --- a/res/coreData/Shaders/GLSL/Transform.glsl +++ b/res/coreData/Shaders/GLSL/Transform.glsl @@ -10,17 +10,18 @@ attribute vec4 iPos; attribute vec3 iNormal; attribute vec4 iColor; attribute vec2 iTexCoord; -attribute vec2 iTexCoord2; +attribute vec2 iTexCoord1; attribute vec4 iTangent; attribute vec4 iBlendWeights; attribute vec4 iBlendIndices; attribute vec3 iCubeTexCoord; -attribute vec4 iCubeTexCoord2; +attribute vec4 iCubeTexCoord1; #ifdef INSTANCED - attribute vec4 iInstanceMatrix1; - attribute vec4 iInstanceMatrix2; - attribute vec4 iInstanceMatrix3; + attribute vec4 iTexCoord4; + attribute vec4 iTexCoord5; + attribute vec4 iTexCoord6; #endif +attribute float iObjectIndex; #ifdef SKINNED mat4 GetSkinMatrix(vec4 blendWeights, vec4 blendIndices) @@ -38,7 +39,7 @@ mat4 GetSkinMatrix(vec4 blendWeights, vec4 blendIndices) mat4 GetInstanceMatrix() { const vec4 lastColumn = vec4(0.0, 0.0, 0.0, 1.0); - return mat4(iInstanceMatrix1, iInstanceMatrix2, iInstanceMatrix3, lastColumn); + return mat4(iTexCoord4, iTexCoord5, iTexCoord6, lastColumn); } #endif @@ -86,10 +87,67 @@ vec3 GetBillboardNormal() } #endif +#ifdef DIRBILLBOARD +mat3 GetFaceCameraRotation(vec3 position, vec3 direction) +{ + vec3 cameraDir = normalize(position - cCameraPos); + vec3 front = normalize(direction); + vec3 right = normalize(cross(front, cameraDir)); + vec3 up = normalize(cross(front, right)); + + return mat3( + right.x, up.x, front.x, + right.y, up.y, front.y, + right.z, up.z, front.z + ); +} + +vec3 GetBillboardPos(vec4 iPos, vec3 iDirection, mat4 modelMatrix) +{ + vec3 worldPos = (iPos * modelMatrix).xyz; + return worldPos + vec3(iTexCoord1.x, 0.0, iTexCoord1.y) * GetFaceCameraRotation(worldPos, iDirection); +} + +vec3 GetBillboardNormal(vec4 iPos, vec3 iDirection, mat4 modelMatrix) +{ + vec3 worldPos = (iPos * modelMatrix).xyz; + return vec3(0.0, 1.0, 0.0) * GetFaceCameraRotation(worldPos, iDirection); +} +#endif + +#ifdef TRAILFACECAM +vec3 GetTrailPos(vec4 iPos, vec3 iFront, float iScale, mat4 modelMatrix) +{ + vec3 up = normalize(cCameraPos - iPos.xyz); + vec3 right = normalize(cross(iFront, up)); + return (vec4((iPos.xyz + right * iScale), 1.0) * modelMatrix).xyz; +} + +vec3 GetTrailNormal(vec4 iPos) +{ + return normalize(cCameraPos - iPos.xyz); +} +#endif + +#ifdef TRAILBONE +vec3 GetTrailPos(vec4 iPos, vec3 iParentPos, float iScale, mat4 modelMatrix) +{ + vec3 right = iParentPos - iPos.xyz; + return (vec4((iPos.xyz + right * iScale), 1.0) * modelMatrix).xyz; +} + +vec3 GetTrailNormal(vec4 iPos, vec3 iParentPos, vec3 iForward) +{ + vec3 left = normalize(iPos.xyz - iParentPos); + vec3 up = normalize(cross(normalize(iForward), left)); + return up; +} +#endif + #if defined(SKINNED) #define iModelMatrix GetSkinMatrix(iBlendWeights, iBlendIndices) #elif defined(INSTANCED) - #define iModelMatrix GetInstanceMatrix(); + #define iModelMatrix GetInstanceMatrix() #else #define iModelMatrix cModel #endif @@ -97,7 +155,13 @@ vec3 GetBillboardNormal() vec3 GetWorldPos(mat4 modelMatrix) { #if defined(BILLBOARD) - return GetBillboardPos(iPos, iTexCoord2, modelMatrix); + return GetBillboardPos(iPos, iTexCoord1, modelMatrix); + #elif defined(DIRBILLBOARD) + return GetBillboardPos(iPos, iNormal, modelMatrix); + #elif defined(TRAILFACECAM) + return GetTrailPos(iPos, iTangent.xyz, iTangent.w, modelMatrix); + #elif defined(TRAILBONE) + return GetTrailPos(iPos, iTangent.xyz, iTangent.w, modelMatrix); #else return (iPos * modelMatrix).xyz; #endif @@ -107,14 +171,26 @@ vec3 GetWorldNormal(mat4 modelMatrix) { #if defined(BILLBOARD) return GetBillboardNormal(); + #elif defined(DIRBILLBOARD) + return GetBillboardNormal(iPos, iNormal, modelMatrix); + #elif defined(TRAILFACECAM) + return GetTrailNormal(iPos); + #elif defined(TRAILBONE) + return GetTrailNormal(iPos, iTangent.xyz, iNormal); #else return normalize(iNormal * GetNormalMatrix(modelMatrix)); #endif } -vec3 GetWorldTangent(mat4 modelMatrix) +vec4 GetWorldTangent(mat4 modelMatrix) { - return normalize(iTangent.xyz * GetNormalMatrix(modelMatrix)); + #if defined(BILLBOARD) + return vec4(normalize(vec3(1.0, 0.0, 0.0) * cBillboardRot), 1.0); + #elif defined(DIRBILLBOARD) + return vec4(normalize(vec3(1.0, 0.0, 0.0) * GetNormalMatrix(modelMatrix)), 1.0); + #else + return vec4(normalize(iTangent.xyz * GetNormalMatrix(modelMatrix)), iTangent.w); + #endif } #else @@ -123,17 +199,23 @@ vec3 GetWorldTangent(mat4 modelMatrix) #ifdef GL3 #define varying in -// \todo: should not hardcode the number of MRT outputs according to defines +#ifndef MRT_COUNT + #if defined(DEFERRED) -out vec4 fragData[4]; +#define MRT_COUNT 4 #elif defined(PREPASS) -out vec4 fragData[2]; +#define MRT_COUNT 2 #else -out vec4 fragData[1]; +#define MRT_COUNT 1 +#endif + #endif +out vec4 fragData[MRT_COUNT]; + + #define gl_FragColor fragData[0] #define gl_FragData fragData #endif -#endif \ No newline at end of file +#endif diff --git a/res/coreData/Shaders/GLSL/Uniforms.glsl b/res/coreData/Shaders/GLSL/Uniforms.glsl index 35ef368..ed60dcf 100644 --- a/res/coreData/Shaders/GLSL/Uniforms.glsl +++ b/res/coreData/Shaders/GLSL/Uniforms.glsl @@ -6,13 +6,12 @@ // OpenGL 2 uniforms (no constant buffers) #ifdef COMPILEVS - + // Vertex shader uniforms uniform vec3 cAmbientStartColor; uniform vec3 cAmbientEndColor; uniform mat3 cBillboardRot; uniform vec3 cCameraPos; -uniform mat3 cCameraRot; uniform float cNearClip; uniform float cFarClip; uniform vec4 cDepthMode; @@ -20,9 +19,12 @@ uniform vec3 cFrustumSize; uniform float cDeltaTime; uniform float cElapsedTime; uniform vec4 cGBufferOffsets; -uniform vec3 cLightDir; uniform vec4 cLightPos; +uniform vec3 cLightDir; +uniform vec4 cNormalOffsetScale; uniform mat4 cModel; +uniform mat4 cView; +uniform mat4 cViewInv; uniform mat4 cViewProj; uniform vec4 cUOffset; uniform vec4 cVOffset; @@ -30,7 +32,7 @@ uniform mat4 cZone; #if !defined(GL_ES) || defined(WEBGL) uniform mat4 cLightMatrices[4]; #else - uniform mat4 cLightMatrices[2]; + uniform highp mat4 cLightMatrices[2]; #endif #ifdef SKINNED uniform vec4 cSkinMatrices[MAXBONES*3]; @@ -50,7 +52,7 @@ uniform mat4 cZone; precision mediump float; #endif -uniform vec3 cAmbientColor; +uniform vec4 cAmbientColor; uniform vec3 cCameraPosPS; uniform float cDeltaTimePS; uniform vec4 cDepthReconstruct; @@ -59,12 +61,21 @@ uniform vec4 cFogParams; uniform vec3 cFogColor; uniform vec2 cGBufferInvSize; uniform vec4 cLightColor; -uniform vec3 cLightDirPS; uniform vec4 cLightPosPS; +uniform vec3 cLightDirPS; +uniform vec4 cNormalOffsetScalePS; uniform vec4 cMatDiffColor; uniform vec3 cMatEmissiveColor; uniform vec3 cMatEnvMapColor; uniform vec4 cMatSpecColor; +#ifdef PBR + uniform float cRoughness; + uniform float cMetallic; + uniform float cLightRad; + uniform float cLightLength; +#endif +uniform vec3 cZoneMin; +uniform vec3 cZoneMax; uniform float cNearClipPS; uniform float cFarClipPS; uniform vec4 cShadowCubeAdjust; @@ -73,7 +84,9 @@ uniform vec2 cShadowIntensity; uniform vec2 cShadowMapInvSize; uniform vec4 cShadowSplits; uniform mat4 cLightMatricesPS[4]; - +#ifdef VSM_SHADOW +uniform vec2 cVSMShadowParams; +#endif #endif #else @@ -91,12 +104,13 @@ uniform FrameVS uniform CameraVS { vec3 cCameraPos; - mat3 cCameraRot; float cNearClip; float cFarClip; vec4 cDepthMode; vec3 cFrustumSize; vec4 cGBufferOffsets; + mat4 cView; + mat4 cViewInv; mat4 cViewProj; vec4 cClipPlane; }; @@ -110,8 +124,9 @@ uniform ZoneVS uniform LightVS { - vec3 cLightDir; vec4 cLightPos; + vec3 cLightDir; + vec4 cNormalOffsetScale; #ifdef NUMVERTEXLIGHTS vec4 cVertexLights[4 * 3]; #else @@ -160,9 +175,11 @@ uniform CameraPS uniform ZonePS { - vec3 cAmbientColor; + vec4 cAmbientColor; vec4 cFogParams; vec3 cFogColor; + vec3 cZoneMin; + vec3 cZoneMax; }; uniform LightPS @@ -170,12 +187,20 @@ uniform LightPS vec4 cLightColor; vec4 cLightPosPS; vec3 cLightDirPS; + vec4 cNormalOffsetScalePS; vec4 cShadowCubeAdjust; vec4 cShadowDepthFade; vec2 cShadowIntensity; vec2 cShadowMapInvSize; vec4 cShadowSplits; mat4 cLightMatricesPS[4]; +#ifdef VSM_SHADOW + vec2 cVSMShadowParams; +#endif +#ifdef PBR + float cLightRad; + float cLightLength; +#endif }; #ifndef CUSTOM_MATERIAL_CBUFFER @@ -185,6 +210,10 @@ uniform MaterialPS vec3 cMatEmissiveColor; vec3 cMatEnvMapColor; vec4 cMatSpecColor; +#ifdef PBR + float cRoughness; + float cMetallic; +#endif }; #endif diff --git a/res/coreData/Shaders/GLSL/Unlit.glsl b/res/coreData/Shaders/GLSL/Unlit.glsl index 468d2b4..6b2e378 100644 --- a/res/coreData/Shaders/GLSL/Unlit.glsl +++ b/res/coreData/Shaders/GLSL/Unlit.glsl @@ -21,6 +21,7 @@ void VS() #ifdef VERTEXCOLOR vColor = iColor; #endif + } void PS() diff --git a/res/coreData/Shaders/GLSL/UnlitParticle.glsl b/res/coreData/Shaders/GLSL/UnlitParticle.glsl new file mode 100644 index 0000000..9be25ef --- /dev/null +++ b/res/coreData/Shaders/GLSL/UnlitParticle.glsl @@ -0,0 +1,90 @@ +#include "Uniforms.glsl" +#include "Samplers.glsl" +#include "Transform.glsl" +#include "ScreenPos.glsl" +#include "Fog.glsl" + +varying vec2 vTexCoord; +varying vec4 vWorldPos; +#ifdef VERTEXCOLOR + varying vec4 vColor; +#endif +#ifdef SOFTPARTICLES + varying vec4 vScreenPos; + uniform float cSoftParticleFadeScale; +#endif + +void VS() +{ + mat4 modelMatrix = iModelMatrix; + vec3 worldPos = GetWorldPos(modelMatrix); + gl_Position = GetClipPos(worldPos); + vTexCoord = GetTexCoord(iTexCoord); + vWorldPos = vec4(worldPos, GetDepth(gl_Position)); + + #ifdef SOFTPARTICLES + vScreenPos = GetScreenPos(gl_Position); + #endif + + #ifdef VERTEXCOLOR + vColor = iColor; + #endif + +} + +void PS() +{ + // Get material diffuse albedo + #ifdef DIFFMAP + vec4 diffColor = cMatDiffColor * texture2D(sDiffMap, vTexCoord); + #ifdef ALPHAMASK + if (diffColor.a < 0.5) + discard; + #endif + #else + vec4 diffColor = cMatDiffColor; + #endif + + #ifdef VERTEXCOLOR + diffColor *= vColor; + #endif + + // Get fog factor + #ifdef HEIGHTFOG + float fogFactor = GetHeightFogFactor(vWorldPos.w, vWorldPos.y); + #else + float fogFactor = GetFogFactor(vWorldPos.w); + #endif + + // Soft particle fade + // In expand mode depth test should be off. In that case do manual alpha discard test first to reduce fill rate + #ifdef SOFTPARTICLES + #ifdef EXPAND + if (diffColor.a < 0.01) + discard; + #endif + + float particleDepth = vWorldPos.w; + #ifdef HWDEPTH + float depth = ReconstructDepth(texture2DProj(sDepthBuffer, vScreenPos).r); + #else + float depth = DecodeDepth(texture2DProj(sDepthBuffer, vScreenPos).rgb); + #endif + + #ifdef EXPAND + float diffZ = max(particleDepth - depth, 0.0) * (cFarClipPS - cNearClipPS); + float fade = clamp(diffZ * cSoftParticleFadeScale, 0.0, 1.0); + #else + float diffZ = (depth - particleDepth) * (cFarClipPS - cNearClipPS); + float fade = clamp(1.0 - diffZ * cSoftParticleFadeScale, 0.0, 1.0); + #endif + + #ifndef ADDITIVE + diffColor.a = max(diffColor.a - fade, 0.0); + #else + diffColor.rgb = max(diffColor.rgb - fade, vec3(0.0, 0.0, 0.0)); + #endif + #endif + + gl_FragColor = vec4(GetFog(diffColor.rgb, fogFactor), diffColor.a); +} diff --git a/res/coreData/Shaders/GLSL/Vegetation.glsl b/res/coreData/Shaders/GLSL/Vegetation.glsl index 2b6b5aa..9592577 100644 --- a/res/coreData/Shaders/GLSL/Vegetation.glsl +++ b/res/coreData/Shaders/GLSL/Vegetation.glsl @@ -16,9 +16,16 @@ uniform vec2 cWindWorldSpacing; #endif varying vec3 vNormal; varying vec4 vWorldPos; +#ifdef VERTEXCOLOR + varying vec4 vColor; +#endif #ifdef PERPIXEL #ifdef SHADOW - varying vec4 vShadowPos[NUMCASCADES]; + #ifndef GL_ES + varying vec4 vShadowPos[NUMCASCADES]; + #else + varying highp vec4 vShadowPos[NUMCASCADES]; + #endif #endif #ifdef SPOTLIGHT varying vec4 vSpotPos; @@ -41,7 +48,7 @@ void VS() { mat4 modelMatrix = iModelMatrix; vec3 worldPos = GetWorldPos(modelMatrix); - float height = worldPos.y - cModel[1][3]; + float height = worldPos.y - modelMatrix[1][3]; float windStrength = max(height - cWindHeightPivot, 0.0) * cWindHeightFactor; float windPeriod = cElapsedTime * cWindPeriod + dot(worldPos.xz, cWindWorldSpacing); @@ -52,11 +59,15 @@ void VS() vNormal = GetWorldNormal(modelMatrix); vWorldPos = vec4(worldPos, GetDepth(gl_Position)); + #ifdef VERTEXCOLOR + vColor = iColor; + #endif + #ifdef NORMALMAP - vec3 tangent = GetWorldTangent(modelMatrix); - vec3 bitangent = cross(tangent, vNormal) * iTangent.w; + vec4 tangent = GetWorldTangent(modelMatrix); + vec3 bitangent = cross(tangent.xyz, vNormal) * tangent.w; vTexCoord = vec4(GetTexCoord(iTexCoord), bitangent.xy); - vTangent = vec4(tangent, bitangent.z); + vTangent = vec4(tangent.xyz, bitangent.z); #else vTexCoord = GetTexCoord(iTexCoord); #endif @@ -68,14 +79,14 @@ void VS() #ifdef SHADOW // Shadow projection: transform from world space to shadow space for (int i = 0; i < NUMCASCADES; i++) - vShadowPos[i] = GetShadowPos(i, projWorldPos); + vShadowPos[i] = GetShadowPos(i, vNormal, projWorldPos); #endif #ifdef SPOTLIGHT // Spotlight projection: transform from world space to projector texture coordinates vSpotPos = projWorldPos * cLightMatrices[0]; #endif - + #ifdef POINTLIGHT vCubeMaskVec = (worldPos - cLightPos.xyz) * mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz); #endif @@ -85,16 +96,16 @@ void VS() // If using lightmap, disregard zone ambient light // If using AO, calculate ambient in the PS vVertexLight = vec3(0.0, 0.0, 0.0); - vTexCoord2 = iTexCoord2; + vTexCoord2 = iTexCoord1; #else vVertexLight = GetAmbient(GetZonePos(worldPos)); #endif - + #ifdef NUMVERTEXLIGHTS for (int i = 0; i < NUMVERTEXLIGHTS; ++i) vVertexLight += GetVertexLight(i, worldPos, vNormal) * cVertexLights[i * 3].rgb; #endif - + vScreenPos = GetScreenPos(gl_Position); #ifdef ENVCUBEMAP diff --git a/res/coreData/Shaders/GLSL/Water.glsl b/res/coreData/Shaders/GLSL/Water.glsl index 081f9b4..478e5fb 100644 --- a/res/coreData/Shaders/GLSL/Water.glsl +++ b/res/coreData/Shaders/GLSL/Water.glsl @@ -4,11 +4,18 @@ #include "ScreenPos.glsl" #include "Fog.glsl" +#ifndef GL_ES varying vec4 vScreenPos; varying vec2 vReflectUV; varying vec2 vWaterUV; -varying vec3 vNormal; varying vec4 vEyeVec; +#else +varying highp vec4 vScreenPos; +varying highp vec2 vReflectUV; +varying highp vec2 vWaterUV; +varying highp vec4 vEyeVec; +#endif +varying vec3 vNormal; #ifdef COMPILEVS uniform vec2 cNoiseSpeed; diff --git a/res/coreData/Shaders/HLSL/BRDF.hlsl b/res/coreData/Shaders/HLSL/BRDF.hlsl new file mode 100644 index 0000000..98aa1f8 --- /dev/null +++ b/res/coreData/Shaders/HLSL/BRDF.hlsl @@ -0,0 +1,135 @@ +#ifdef COMPILEPS + #ifdef PBR + + // Following BRDF methods are based upon research Frostbite EA + //[Lagrade et al. 2014, "Moving Frostbite to Physically Based Rendering"] + + //Schlick Fresnel + //specular = the rgb specular color value of the pixel + //VdotH = the dot product of the camera view direction and the half vector + float3 SchlickFresnel(float3 specular, float VdotH) + { + return specular + (float3(1.0, 1.0, 1.0) - specular) * pow(1.0 - VdotH, 5.0); + } + + //Schlick Gaussian Fresnel + //specular = the rgb specular color value of the pixel + //VdotH = the dot product of the camera view direction and the half vector + float3 SchlickGaussianFresnel(in float3 specular, in float VdotH) + { + float sphericalGaussian = pow(2.0, (-5.55473 * VdotH - 6.98316) * VdotH); + return specular + (float3(1.0, 1.0, 1.0) - specular) * sphericalGaussian; + } + + //Get Fresnel + //specular = the rgb specular color value of the pixel + //VdotH = the dot product of the camera view direction and the half vector + float3 Fresnel(float3 specular, float VdotH) + { + return SchlickFresnel(specular, VdotH); + } + + // Smith GGX corrected Visibility + // NdotL = the dot product of the normal and direction to the light + // NdotV = the dot product of the normal and the camera view direction + // roughness = the roughness of the pixel + float SmithGGXSchlickVisibility(float NdotL, float NdotV, float roughness) + { + float rough2 = roughness * roughness; + float lambdaV = NdotL * sqrt((-NdotV * rough2 + NdotV) * NdotV + rough2); + float lambdaL = NdotV * sqrt((-NdotL * rough2 + NdotL) * NdotL + rough2); + + return 0.5 / (lambdaV + lambdaL); + } + + // Get Visibility + // NdotL = the dot product of the normal and direction to the light + // NdotV = the dot product of the normal and the camera view direction + // roughness = the roughness of the pixel + float Visibility(float NdotL, float NdotV, float roughness) + { + return SmithGGXSchlickVisibility(NdotL, NdotV, roughness); + } + + // GGX Distribution + // NdotH = the dot product of the normal and the half vector + // roughness = the roughness of the pixel + float GGXDistribution(float NdotH, float roughness) + { + float rough2 = roughness * roughness; + float tmp = (NdotH * rough2 - NdotH) * NdotH + 1; + return rough2 / (tmp * tmp); + } + + // Blinn Distribution + // NdotH = the dot product of the normal and the half vector + // roughness = the roughness of the pixel + float BlinnPhongDistribution(in float NdotH, in float roughness) + { + const float specPower = max((2.0 / (roughness * roughness)) - 2.0, 1e-4f); // Calculate specular power from roughness + return pow(saturate(NdotH), specPower); + } + + // Beckmann Distribution + // NdotH = the dot product of the normal and the half vector + // roughness = the roughness of the pixel + float BeckmannDistribution(in float NdotH, in float roughness) + { + const float rough2 = roughness * roughness; + const float roughnessA = 1.0 / (4.0 * rough2 * pow(NdotH, 4.0)); + const float roughnessB = NdotH * NdotH - 1.0; + const float roughnessC = rough2 * NdotH * NdotH; + return roughnessA * exp(roughnessB / roughnessC); + } + + // Get Distribution + // NdotH = the dot product of the normal and the half vector + // roughness = the roughness of the pixel + float Distribution(float NdotH, float roughness) + { + return GGXDistribution(NdotH, roughness); + } + + // Lambertian Diffuse + // diffuseColor = the rgb color value of the pixel + // roughness = the roughness of the pixel + // NdotV = the normal dot with the camera view direction + // NdotL = the normal dot with the light direction + // VdotH = the camera view direction dot with the half vector + float3 LambertianDiffuse(float3 diffuseColor, float NdotL) + { + return diffuseColor * NdotL; + } + + // Burley Diffuse + // diffuseColor = the rgb color value of the pixel + // roughness = the roughness of the pixel + // NdotV = the normal dot with the camera view direction + // NdotL = the normal dot with the light direction + // VdotH = the camera view direction dot with the half vector + float3 BurleyDiffuse(float3 diffuseColor, float roughness, float NdotV, float NdotL, float VdotH) + { + const float energyBias = lerp(0, 0.5, roughness); + const float energyFactor = lerp(1.0, 1.0 / 1.51, roughness); + const float fd90 = energyBias + 2.0 * VdotH * VdotH * roughness; + const float f0 = 1.0; + const float lightScatter = f0 + (fd90 - f0) * pow(1.0f - NdotL, 5.0f); + const float viewScatter = f0 + (fd90 - f0) * pow(1.0f - NdotV, 5.0f); + + return diffuseColor * lightScatter * viewScatter * energyFactor; + } + + //Get Diffuse + // diffuseColor = the rgb color value of the pixel + // roughness = the roughness of the pixel + // NdotV = the normal dot with the camera view direction + // NdotL = the normal dot with the light direction + // VdotH = the camera view direction dot with the half vector + float3 Diffuse(float3 diffuseColor, float roughness, float NdotV, float NdotL, float VdotH) + { + //return LambertianDiffuse(diffuseColor, NdotL); + return BurleyDiffuse(diffuseColor, roughness, NdotV, NdotL, VdotH); + } + + #endif +#endif diff --git a/res/coreData/Shaders/HLSL/Basic.hlsl b/res/coreData/Shaders/HLSL/Basic.hlsl index 9abce43..d8a8557 100644 --- a/res/coreData/Shaders/HLSL/Basic.hlsl +++ b/res/coreData/Shaders/HLSL/Basic.hlsl @@ -14,11 +14,17 @@ void VS(float4 iPos : POSITION, int4 iBlendIndices : BLENDINDICES, #endif #ifdef INSTANCED - float4x3 iModelInstance : TEXCOORD2, + float4x3 iModelInstance : TEXCOORD4, #endif - #ifdef BILLBOARD + #if defined(BILLBOARD) || defined(DIRBILLBOARD) float2 iSize : TEXCOORD1, #endif + #if defined(DIRBILLBOARD) || defined(TRAILBONE) + float3 iNormal : NORMAL, + #endif + #if defined(TRAILFACECAM) || defined(TRAILBONE) + float4 iTangent : TANGENT, + #endif #ifdef DIFFMAP out float2 oTexCoord : TEXCOORD0, #endif diff --git a/res/coreData/Shaders/HLSL/Constants.hlsl b/res/coreData/Shaders/HLSL/Constants.hlsl new file mode 100644 index 0000000..4e83774 --- /dev/null +++ b/res/coreData/Shaders/HLSL/Constants.hlsl @@ -0,0 +1,7 @@ +#define M_PI 3.14159265358979323846 +#define M_EPSILON 0.0001 + +#ifdef PBR +#define ROUGHNESS_FLOOR 0.003 +#define METALNESS_FLOOR 0.03 +#endif diff --git a/res/coreData/Shaders/HLSL/DeferredLight.hlsl b/res/coreData/Shaders/HLSL/DeferredLight.hlsl index fb2e18d..5a7ab18 100644 --- a/res/coreData/Shaders/HLSL/DeferredLight.hlsl +++ b/res/coreData/Shaders/HLSL/DeferredLight.hlsl @@ -72,7 +72,11 @@ void PS( float4 albedoInput = Sample2DProj(AlbedoBuffer, iScreenPos); float4 normalInput = Sample2DProj(NormalBuffer, iScreenPos); #endif - + + // Position acquired via near/far ray is relative to camera. Bring position to world space + float3 eyeVec = -worldPos; + worldPos += cCameraPosPS; + float3 normal = normalize(normalInput.rgb * 2.0 - 1.0); float4 projWorldPos = float4(worldPos, 1.0); float3 lightColor; @@ -81,7 +85,7 @@ void PS( float diff = GetDiffuse(normal, worldPos, lightDir); #ifdef SHADOW - diff *= GetShadowDeferred(projWorldPos, depth); + diff *= GetShadowDeferred(projWorldPos, normal, depth); #endif #if defined(SPOTLIGHT) @@ -94,7 +98,7 @@ void PS( #endif #ifdef SPECULAR - float spec = GetSpecular(normal, -worldPos, lightDir, normalInput.a * 255.0); + float spec = GetSpecular(normal, eyeVec, lightDir, normalInput.a * 255.0); oColor = diff * float4(lightColor * (albedoInput.rgb + spec * cLightColor.a * albedoInput.aaa), 0.0); #else oColor = diff * float4(lightColor * albedoInput.rgb, 0.0); diff --git a/res/coreData/Shaders/HLSL/Depth.hlsl b/res/coreData/Shaders/HLSL/Depth.hlsl index d4c24e4..1355903 100644 --- a/res/coreData/Shaders/HLSL/Depth.hlsl +++ b/res/coreData/Shaders/HLSL/Depth.hlsl @@ -8,12 +8,19 @@ void VS(float4 iPos : POSITION, int4 iBlendIndices : BLENDINDICES, #endif #ifdef INSTANCED - float4x3 iModelInstance : TEXCOORD2, + float4x3 iModelInstance : TEXCOORD4, + #endif + #ifndef NOUV + float2 iTexCoord : TEXCOORD0, #endif - float2 iTexCoord : TEXCOORD0, out float3 oTexCoord : TEXCOORD0, out float4 oPos : OUTPOSITION) { + // Define a 0,0 UV coord if not expected from the vertex data + #ifdef NOUV + float2 iTexCoord = float2(0.0, 0.0); + #endif + float4x3 modelMatrix = iModelMatrix; float3 worldPos = GetWorldPos(modelMatrix); oPos = GetClipPos(worldPos); @@ -25,7 +32,7 @@ void PS( out float4 oColor : OUTCOLOR0) { #ifdef ALPHAMASK - float alpha = Sample2D(sDiffMap, iTexCoord.xy).a; + float alpha = Sample2D(DiffMap, iTexCoord.xy).a; if (alpha < 0.5) discard; #endif diff --git a/res/coreData/Shaders/HLSL/IBL.hlsl b/res/coreData/Shaders/HLSL/IBL.hlsl new file mode 100644 index 0000000..585cf39 --- /dev/null +++ b/res/coreData/Shaders/HLSL/IBL.hlsl @@ -0,0 +1,305 @@ +#ifdef COMPILEPS + + // float3 ImportanceSampleSimple(in float2 Xi, in float roughness, in float3 T, in float3 B, in float3 N) + // { + // const float a = roughness * roughness; + // const float3x3 tbn = float3x3(T, B, N); + // #ifdef IBLFAST + // const float blurFactor = 0.0; + // #else + // const float blurFactor = 5.0; + // #endif + // const float3 Xi3 = lerp(float3(0,0,1), normalize(float3(Xi.xy * blurFactor % 1.0 , 1.0)), a); + // const float3 XiWS = mul(Xi3, tbn); + // return normalize(N + XiWS); + // } + + // // Karis '13 + // float3 ImportanceSampleGGX(in float2 Xi, in float roughness, in float3 T, in float3 B, in float3 N) + // { + // float a = roughness * roughness; + // float Phi = 2.0 * M_PI * Xi.x; + // float CosTheta = (sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y))); + // float SinTheta = sqrt(1.0 - CosTheta * CosTheta); + // float3 H = 0; + // H.x = SinTheta * cos(Phi); + // H.y = SinTheta * sin(Phi); + // H.z = CosTheta; + + // float3 UpVector = abs(N.z) < 0.999 ? float3(0, 0, 1) : float3(1, 0, 0); + // float3 TangentX = normalize(cross(UpVector, N)); + // float3 TangentY = cross(N, TangentX); + // // Tangent to world space + // return TangentX * H.x + TangentY * H.y + N * H.z; + // } + + // #ifdef IBLFAST + // #define IMPORTANCE_SAMPLES 1 + // #else + // #define IMPORTANCE_SAMPLES 16 + // #endif + + // #define IMPORTANCE_KERNEL_SIZE 16 + // static const float2 IMPORTANCE_KERNEL[IMPORTANCE_KERNEL_SIZE] = + // { + // float2(-0.0780436, 0.0558389), + // float2(0.034318, -0.0635879), + // float2(0.00230821, 0.0807279), + // float2(0.0124638, 0.117585), + // float2(0.093943, -0.0944602), + // float2(0.139348, -0.109816), + // float2(-0.181872, -0.129649), + // float2(0.240066, -0.0494057), + // float2(0.115965, -0.0374714), + // float2(-0.294819, -0.100726), + // float2(-0.149652, 0.37459), + // float2(0.261695, -0.292813), + // float2(-0.37944, -0.425145), + // float2(0.628994, -0.189387), + // float2(-0.331257, -0.646864), + // float2(-0.467004, 0.439687), + // }; + + // float GetMipFromRougness(float roughness) + // { + // const float smoothness = 1.0 - roughness; + // return (1.0 - smoothness * smoothness) * 10.0; + // } + + // /// Perform importance sampling + // /// reflectVec: calculated vector of reflection + // /// wsNormal: world-space normal of the surface + // /// toCamera: direction from the pixel to the camera + // /// specular: specular color + // /// roughness: surface roughness + // /// reflectionCubeColor: output color for diffuse + + // // Implementation based on Epics 2013 course notes + // float3 ImportanceSampling(in float3 reflectVec, in float3 tangent, in float3 bitangent, in float3 wsNormal, in float3 toCamera, in float3 diffColor, in float3 specColor, in float roughness, inout float3 reflectionCubeColor) + // { + // reflectionCubeColor = 1.0; + + // const float3 reflectSpec = normalize(GetSpecularDominantDir(wsNormal, reflectVec, roughness)); + + // const float3 V = normalize(-toCamera); + // const float3 N = normalize(wsNormal); + // const float ndv = saturate(abs(dot(N, V))); + + // const float specMipLevel = GetMipFromRougness(roughness); + + // float3 accumulatedColor = float3(0,0,0); + // for (int i = 0; i < IMPORTANCE_SAMPLES; ++i) + // { + // float3 kd = 1.0; + // float3 diffuseFactor = 0.0; + // float3 specularFactor = 0.0; + + // { + // // Diffuse IBL + // const float rough = 1.0; + // const float mipLevel = 9.0; + + // const float3 H = ImportanceSampleSimple(IMPORTANCE_KERNEL[i], rough, tangent, bitangent, N); + // const float3 L = 2.0 * dot( V, H ) * H - V; + + // const float vdh = saturate(abs(dot(V, H))); + // const float ndh = saturate(abs(dot(N, H))); + // const float ndl = saturate(abs(dot(N, L))); + + // const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(L, mipLevel)); + + // const float3 diffuseTerm = Diffuse(diffColor, rough, ndv, ndl, vdh); + // const float3 lightTerm = sampledColor; + + // diffuseFactor = lightTerm * diffuseTerm; + // } + + // { + // // Specular IBL + // const float rough = roughness; + // const float mipLevel = specMipLevel; + + // const float3 H = ImportanceSampleSimple(IMPORTANCE_KERNEL[i], rough, tangent, bitangent, N); + // const float3 L = 2.0 * dot( V, H ) * H - V; + // const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(L, mipLevel)); + + // const float vdh = saturate(abs(dot(V, H))); + // const float ndh = saturate(abs(dot(N, H))); + // const float ndl = saturate(abs(dot(N, L))); + + // const float3 fresnelTerm = Fresnel(specColor, vdh); + // const float distTerm = 1.0;//Distribution(ndh_, roughness); + // const float visTerm = Visibility(ndl, ndv, rough); + // const float3 lightTerm = sampledColor * ndl; + + // const float pdf = ndl > 0.05 ? ImportanceSamplePDF(distTerm, ndh, vdh) : 4.0; // reduce artifacts at extreme grazing angles + + // const float3 specularTerm = SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndv); + + // // Energy conservation: + // // Specular conservation: + // specularFactor = lightTerm * specularTerm / pdf; + // specularFactor = max(saturate(normalize(specularFactor) * (length(sampledColor * specColor))), specularFactor); + + // // Diffuse conservation: + // kd = 1.0 - specularFactor; + // } + + // accumulatedColor += specularFactor + diffuseFactor * kd; + // } + + // return (accumulatedColor / IMPORTANCE_SAMPLES); + // } + + + // float3 ImportanceSamplingSimple(in float3 reflectVec, in float3 tangent, in float3 bitangent, in float3 wsNormal, in float3 toCamera, in float3 diffColor, in float3 specColor, in float roughness, inout float3 reflectionCubeColor) + // { + // reflectionCubeColor = 1.0; + + // reflectVec = normalize(GetSpecularDominantDir(wsNormal, reflectVec, roughness)); + + // const float3 Hn = normalize(-toCamera + wsNormal); + // const float ndv = saturate(dot(-toCamera, wsNormal)); + // const float vdh = saturate(dot(-toCamera, Hn)); + // const float ndh = saturate(dot(wsNormal, Hn)); + + // float3 accumulatedColor = float3(0,0,0); + // for (int i = 0; i < IMPORTANCE_SAMPLES; ++i) + // { + // float3 kd = 1.0; + // float3 diffuseFactor = 0.0; + // float3 specularFactor = 0.0; + + // { + // // Diffuse IBL + // const float rough = 1.0; + // const float mipLevel = 9.0; + + // const float3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, tangent, bitangent, wsNormal); + // const float3 sampleVec = wsNormal + perturb; //perturb by the sample vector + + // const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(sampleVec, mipLevel)); + // const float ndl = saturate(dot(sampleVec, wsNormal)); + + // const float3 diffuseTerm = Diffuse(diffColor, rough, ndv, ndl, vdh); + // const float3 lightTerm = sampledColor; + + // diffuseFactor = lightTerm * diffuseTerm; + // } + + // { + // // Specular IBL + // const float rough = roughness; + // const float mipLevel = GetMipFromRougness(rough); + + // const float3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, tangent, bitangent, reflectVec); + // const float3 sampleVec = reflectVec + perturb; //perturb by the sample vector + + // const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(sampleVec, mipLevel)); + // const float ndl = saturate(dot(sampleVec, wsNormal)); + + // const float3 fresnelTerm = SchlickFresnel(specColor, ndh) ; + // const float distTerm = 1.0; //Optimization, this term is mathematically cancelled out //Distribution(ndh, roughness); + // const float visTerm = SmithGGXVisibility(ndl, ndv, rough); + // const float3 lightTerm = sampledColor * ndl; + + // const float pdf = 1.0;//ImportanceSamplePDF(distTerm, ndh, vdh); + + // specularFactor = lightTerm * SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndv) / pdf; + // specularFactor *= pdf * ndv * (4.0 * ndl * ndv); // hacks + // kd = (1.0 - saturate(specularFactor)); //energy conservation + // } + + // accumulatedColor += specularFactor + diffuseFactor * kd; + // } + + // return accumulatedColor / IMPORTANCE_SAMPLES; + // } + + /// Determine reflection vector based on surface roughness, rougher uses closer to the normal and smoother uses closer to the reflection vector + /// normal: surface normal + /// reflection: vector of reflection off of the surface + /// roughness: surface roughness + float3 GetSpecularDominantDir(float3 normal, float3 reflection, float roughness) + { + const float smoothness = 1.0 - roughness; + const float lerpFactor = smoothness * (sqrt(smoothness) + roughness); + return lerp(normal, reflection, lerpFactor); + } + + float GetMipFromRoughness(float roughness) + { + float Level = 3 - 1.15 * log2( roughness ); + return 9.0 - 1 - Level; + } + + + float3 EnvBRDFApprox (float3 specColor, float roughness, float ndv) + { + const float4 c0 = float4(-1, -0.0275, -0.572, 0.022 ); + const float4 c1 = float4(1, 0.0425, 1.0, -0.04 ); + float4 r = roughness * c0 + c1; + float a004 = min( r.x * r.x, exp2( -9.28 * ndv ) ) * r.x + r.y; + float2 AB = float2( -1.04, 1.04 ) * a004 + r.zw; + return specColor * AB.x + AB.y; + } + + float3 FixCubeLookup(float3 v) + { + float M = max(max(abs(v.x), abs(v.y)), abs(v.z)); + float scale = (1024 - 1) / 1024; + + if (abs(v.x) != M) v.x += scale; + if (abs(v.y) != M) v.y += scale; + if (abs(v.z) != M) v.z += scale; + + return v; + } + + /// Calculate IBL contributation + /// reflectVec: reflection vector for cube sampling + /// wsNormal: surface normal in word space + /// toCamera: normalized direction from surface point to camera + /// roughness: surface roughness + /// ambientOcclusion: ambient occlusion + float3 ImageBasedLighting(in float3 reflectVec, in float3 tangent, in float3 bitangent, in float3 wsNormal, in float3 toCamera, in float3 diffColor, in float3 specColor, in float roughness, inout float3 reflectionCubeColor) + { + reflectVec = GetSpecularDominantDir(wsNormal, reflectVec, roughness); + const float ndv = saturate(dot(-toCamera, wsNormal)); + + /// Test: Parallax correction, currently not working + + // float3 intersectMax = (cZoneMax - toCamera) / reflectVec; + // float3 intersectMin = (cZoneMin - toCamera) / reflectVec; + + // float3 furthestPlane = max(intersectMax, intersectMin); + + // float planeDistance = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z); + + // // Get the intersection position + // float3 intersectionPos = toCamera + reflectVec * planeDistance; + // // Get corrected reflection + // reflectVec = intersectionPos - ((cZoneMin + cZoneMax )/ 2); + + const float mipSelect = GetMipFromRoughness(roughness); + float3 cube = SampleCubeLOD(ZoneCubeMap, float4(FixCubeLookup(reflectVec), mipSelect)).rgb; + float3 cubeD = SampleCubeLOD(ZoneCubeMap, float4(FixCubeLookup(wsNormal), 9.0)).rgb; + + // Fake the HDR texture + float brightness = clamp(cAmbientColor.a, 0.0, 1.0); + float darknessCutoff = clamp((cAmbientColor.a - 1.0) * 0.1, 0.0, 0.25); + + const float hdrMaxBrightness = 5.0; + float3 hdrCube = pow(cube + darknessCutoff, max(1.0, cAmbientColor.a)); + hdrCube += max(0.0, hdrCube - 1.0) * hdrMaxBrightness; + + float3 hdrCubeD = pow(cubeD + darknessCutoff, max(1.0, cAmbientColor.a)); + hdrCubeD += max(0.0, hdrCubeD - 1.0) * hdrMaxBrightness; + + const float3 environmentSpecular = EnvBRDFApprox(specColor, roughness, ndv); + const float3 environmentDiffuse = EnvBRDFApprox(diffColor, 1.0, ndv); + + return (hdrCube * environmentSpecular + hdrCubeD * environmentDiffuse) * brightness; + //return ImportanceSampling(reflectVec, tangent, bitangent, wsNormal, toCamera, diffColor, specColor, roughness, reflectionCubeColor); + } +#endif diff --git a/res/coreData/Shaders/HLSL/Lighting.hlsl b/res/coreData/Shaders/HLSL/Lighting.hlsl index f4b7cb5..a218dc2 100644 --- a/res/coreData/Shaders/HLSL/Lighting.hlsl +++ b/res/coreData/Shaders/HLSL/Lighting.hlsl @@ -18,7 +18,11 @@ float GetVertexLight(int index, float3 worldPos, float3 normal) // Directional light if (invRange == 0.0) { - float NdotL = max(dot(normal, lightDir), 0.0); + #ifdef TRANSLUCENT + float NdotL = abs(dot(normal, lightDir)); + #else + float NdotL = max(dot(normal, lightDir), 0.0); + #endif return NdotL; } // Point/spot light @@ -27,7 +31,11 @@ float GetVertexLight(int index, float3 worldPos, float3 normal) float3 lightVec = (lightPos - worldPos) * invRange; float lightDist = length(lightVec); float3 localDir = lightVec / lightDist; - float NdotL = max(dot(normal, localDir), 0.0); + #ifdef TRANSLUCENT + float NdotL = abs(dot(normal, localDir)); + #else + float NdotL = max(dot(normal, localDir), 0.0); + #endif float atten = saturate(1.0 - lightDist * lightDist); float spotEffect = dot(localDir, lightDir); float spotAtten = saturate((spotEffect - cutoff) * invCutoff); @@ -70,18 +78,37 @@ float GetVertexLightVolumetric(int index, float3 worldPos) #define NUMCASCADES 1 #endif -void GetShadowPos(float4 projWorldPos, out float4 shadowPos[NUMCASCADES]) +void GetShadowPos(float4 projWorldPos, float3 normal, out float4 shadowPos[NUMCASCADES]) { // Shadow projection: transform from world space to shadow space - #if defined(DIRLIGHT) - shadowPos[0] = mul(projWorldPos, cLightMatrices[0]); - shadowPos[1] = mul(projWorldPos, cLightMatrices[1]); - shadowPos[2] = mul(projWorldPos, cLightMatrices[2]); - shadowPos[3] = mul(projWorldPos, cLightMatrices[3]); - #elif defined(SPOTLIGHT) - shadowPos[0] = mul(projWorldPos, cLightMatrices[1]); + #ifdef NORMALOFFSET + #ifdef DIRLIGHT + float cosAngle = saturate(1.0 - dot(normal, cLightDir)); + #else + float cosAngle = saturate(1.0 - dot(normal, normalize(cLightPos.xyz - projWorldPos.xyz))); + #endif + + #if defined(DIRLIGHT) + shadowPos[0] = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScale.x * normal, 1.0), cLightMatrices[0]); + shadowPos[1] = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScale.y * normal, 1.0), cLightMatrices[1]); + shadowPos[2] = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScale.z * normal, 1.0), cLightMatrices[2]); + shadowPos[3] = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScale.w * normal, 1.0), cLightMatrices[3]); + #elif defined(SPOTLIGHT) + shadowPos[0] = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScale.x * normal, 1.0), cLightMatrices[1]); + #else + shadowPos[0] = float4(projWorldPos.xyz + cosAngle * cNormalOffsetScale.x * normal - cLightPos.xyz, 0.0); + #endif #else - shadowPos[0] = float4(projWorldPos.xyz - cLightPos.xyz, 0.0); + #if defined(DIRLIGHT) + shadowPos[0] = mul(projWorldPos, cLightMatrices[0]); + shadowPos[1] = mul(projWorldPos, cLightMatrices[1]); + shadowPos[2] = mul(projWorldPos, cLightMatrices[2]); + shadowPos[3] = mul(projWorldPos, cLightMatrices[3]); + #elif defined(SPOTLIGHT) + shadowPos[0] = mul(projWorldPos, cLightMatrices[1]); + #else + shadowPos[0] = float4(projWorldPos.xyz - cLightPos.xyz, 0.0); + #endif #endif } #endif @@ -92,15 +119,52 @@ float GetDiffuse(float3 normal, float3 worldPos, out float3 lightDir) { #ifdef DIRLIGHT lightDir = cLightDirPS; - return saturate(dot(normal, lightDir)); + #ifdef TRANSLUCENT + return abs(dot(normal, lightDir)); + #else + return saturate(dot(normal, lightDir)); + #endif #else float3 lightVec = (cLightPosPS.xyz - worldPos) * cLightPosPS.w; float lightDist = length(lightVec); lightDir = lightVec / lightDist; - return saturate(dot(normal, lightDir)) * Sample2D(LightRampMap, float2(lightDist, 0.0)).r; + #ifdef TRANSLUCENT + return abs(dot(normal, lightDir)) * Sample2D(LightRampMap, float2(lightDist, 0.0)).r; + #else + return saturate(dot(normal, lightDir)) * Sample2D(LightRampMap, float2(lightDist, 0.0)).r; + #endif #endif } +float GetAtten(float3 normal, float3 worldPos, out float3 lightDir) +{ + lightDir = cLightDirPS; + return saturate(dot(normal, lightDir)); + +} + +float GetAttenPoint(float3 normal, float3 worldPos, out float3 lightDir) +{ + float3 lightVec = (cLightPosPS.xyz - worldPos) * cLightPosPS.w; + float lightDist = length(lightVec); + float falloff = pow(saturate(1.0 - pow(lightDist / 1.0, 4.0)), 2.0) * 3.14159265358979323846 / (4 * 3.14159265358979323846)*(pow(lightDist, 2.0) + 1.0); + lightDir = lightVec / lightDist; + return saturate(dot(normal, lightDir)) * falloff; + +} + +float GetAttenSpot(float3 normal, float3 worldPos, out float3 lightDir) +{ + float3 lightVec = (cLightPosPS.xyz - worldPos) * cLightPosPS.w; + float lightDist = length(lightVec); + float falloff = pow(saturate(1.0 - pow(lightDist / 1.0, 4.0)), 2.0) / (pow(lightDist, 2.0) + 1.0); + + lightDir = lightVec / lightDist; + return saturate(dot(normal, lightDir)) * falloff; + +} + + float GetDiffuseVolumetric(float3 worldPos) { #ifdef DIRLIGHT @@ -131,15 +195,55 @@ float GetIntensity(float3 color) #define NUMCASCADES 1 #endif +#ifdef VSM_SHADOW +float ReduceLightBleeding(float min, float p_max) +{ + return clamp((p_max - min) / (1.0 - min), 0.0, 1.0); +} + +float Chebyshev(float2 Moments, float depth) +{ + //One-tailed inequality valid if depth > Moments.x + float p = float(depth <= Moments.x); + //Compute variance. + float Variance = Moments.y - (Moments.x * Moments.x); + + float minVariance = cVSMShadowParams.x; + Variance = max(Variance, minVariance); + //Compute probabilistic upper bound. + float d = depth - Moments.x; + float p_max = Variance / (Variance + d*d); + // Prevent light bleeding + p_max = ReduceLightBleeding(cVSMShadowParams.y, p_max); + + return max(p, p_max); +} +#endif + float GetShadow(float4 shadowPos) { - #ifdef D3D11 - shadowPos.xyz /= shadowPos.w; - #endif - - #ifndef LQSHADOW + #if defined(SIMPLE_SHADOW) + // Take one sample + #ifdef D3D11 + shadowPos.xyz /= shadowPos.w; + #endif + float inLight = SampleShadow(ShadowMap, shadowPos).r; + #ifndef SHADOWCMP + return cShadowIntensity.y + cShadowIntensity.x * inLight; + #else + #ifndef POINTLIGHT + return cShadowIntensity.y + cShadowIntensity.x * (inLight * shadowPos.w > shadowPos.z); + #else + return cShadowIntensity.y + cShadowIntensity.x * (inLight > shadowPos.z); + #endif + #endif + + #elif defined(PCF_SHADOW) // Take four samples and average them // Note: in case of sampling a point light cube shadow, we optimize out the w divide as it has already been performed + #ifdef D3D11 + shadowPos.xyz /= shadowPos.w; + #endif #if !defined(POINTLIGHT) && !defined(D3D11) float2 offsets = cShadowMapInvSize * shadowPos.w; #else @@ -164,18 +268,10 @@ float GetShadow(float4 shadowPos) return cShadowIntensity.y + dot(inLight > shadowPos.z, cShadowIntensity.x); #endif #endif - #else - // Take one sample - float inLight = SampleShadow(ShadowMap, shadowPos).r; - #ifndef SHADOWCMP - return cShadowIntensity.y + cShadowIntensity.x * inLight; - #else - #ifndef POINTLIGHT - return cShadowIntensity.y + cShadowIntensity.x * (inLight * shadowPos.w > shadowPos.z); - #else - return cShadowIntensity.y + cShadowIntensity.x * (inLight > shadowPos.z); - #endif - #endif + + #elif defined(VSM_SHADOW) + float2 samples = Sample2D(ShadowMap, shadowPos.xy / shadowPos.w).rg; + return cShadowIntensity.y + cShadowIntensity.x * Chebyshev(samples, shadowPos.z/shadowPos.w); #endif } @@ -223,19 +319,31 @@ float GetDirShadow(const float4 iShadowPos[NUMCASCADES], float depth) return GetDirShadowFade(GetShadow(shadowPos), depth); } -float GetDirShadowDeferred(float4 projWorldPos, float depth) +float GetDirShadowDeferred(float4 projWorldPos, float3 normal, float depth) { float4 shadowPos; - if (depth < cShadowSplits.x) - shadowPos = mul(projWorldPos, cLightMatricesPS[0]); - else if (depth < cShadowSplits.y) - shadowPos = mul(projWorldPos, cLightMatricesPS[1]); - else if (depth < cShadowSplits.z) - shadowPos = mul(projWorldPos, cLightMatricesPS[2]); - else - shadowPos = mul(projWorldPos, cLightMatricesPS[3]); - + #ifdef NORMALOFFSET + float cosAngle = saturate(1.0 - dot(normal, cLightDirPS)); + if (depth < cShadowSplits.x) + shadowPos = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.x * normal, 1.0), cLightMatricesPS[0]); + else if (depth < cShadowSplits.y) + shadowPos = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.y * normal, 1.0), cLightMatricesPS[1]); + else if (depth < cShadowSplits.z) + shadowPos = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.z * normal, 1.0), cLightMatricesPS[2]); + else + shadowPos = mul(float4(projWorldPos.xyz + cosAngle * cNormalOffsetScalePS.w * normal, 1.0), cLightMatricesPS[3]); + #else + if (depth < cShadowSplits.x) + shadowPos = mul(projWorldPos, cLightMatricesPS[0]); + else if (depth < cShadowSplits.y) + shadowPos = mul(projWorldPos, cLightMatricesPS[1]); + else if (depth < cShadowSplits.z) + shadowPos = mul(projWorldPos, cLightMatricesPS[2]); + else + shadowPos = mul(projWorldPos, cLightMatricesPS[3]); + #endif + return GetDirShadowFade(GetShadow(shadowPos), depth); } #endif @@ -251,16 +359,23 @@ float GetShadow(float4 iShadowPos[NUMCASCADES], float depth) #endif } -float GetShadowDeferred(float4 projWorldPos, float depth) +float GetShadowDeferred(float4 projWorldPos, float3 normal, float depth) { - #if defined(DIRLIGHT) - return GetDirShadowDeferred(projWorldPos, depth); - #elif defined(SPOTLIGHT) - float4 shadowPos = mul(projWorldPos, cLightMatricesPS[1]); - return GetShadow(shadowPos); + #ifdef DIRLIGHT + return GetDirShadowDeferred(projWorldPos, normal, depth); #else - float3 shadowPos = projWorldPos.xyz - cLightPosPS.xyz; - return GetPointShadow(shadowPos); + #ifdef NORMALOFFSET + float cosAngle = saturate(1.0 - dot(normal, normalize(cLightPosPS.xyz - projWorldPos.xyz))); + projWorldPos.xyz += cosAngle * cNormalOffsetScalePS.x * normal; + #endif + + #ifdef SPOTLIGHT + float4 shadowPos = mul(projWorldPos, cLightMatricesPS[1]); + return GetShadow(shadowPos); + #else + float3 shadowPos = projWorldPos.xyz - cLightPosPS.xyz; + return GetPointShadow(shadowPos); + #endif #endif } #endif diff --git a/res/coreData/Shaders/HLSL/LitParticle.hlsl b/res/coreData/Shaders/HLSL/LitParticle.hlsl index 5faa0fd..bcf0c34 100644 --- a/res/coreData/Shaders/HLSL/LitParticle.hlsl +++ b/res/coreData/Shaders/HLSL/LitParticle.hlsl @@ -2,10 +2,24 @@ #include "Samplers.hlsl" #include "Transform.hlsl" #include "Lighting.hlsl" +#include "ScreenPos.hlsl" #include "Fog.hlsl" +#if defined(COMPILEPS) && defined(SOFTPARTICLES) +#ifndef D3D11 +// D3D9 uniform +uniform float cSoftParticleFadeScale; +#else +// D3D11 constant buffer +cbuffer CustomPS : register(b6) +{ + float cSoftParticleFadeScale; +} +#endif +#endif + void VS(float4 iPos : POSITION, - #ifndef BILLBOARD + #if !defined(BILLBOARD) && !defined(TRAILFACECAM) float3 iNormal : NORMAL, #endif #ifndef NOUV @@ -19,12 +33,18 @@ void VS(float4 iPos : POSITION, int4 iBlendIndices : BLENDINDICES, #endif #ifdef INSTANCED - float4x3 iModelInstance : TEXCOORD2, + float4x3 iModelInstance : TEXCOORD4, #endif - #ifdef BILLBOARD + #if defined(BILLBOARD) || defined(DIRBILLBOARD) float2 iSize : TEXCOORD1, #endif + #if defined(TRAILFACECAM) || defined(TRAILBONE) + float4 iTangent : TANGENT, + #endif out float2 oTexCoord : TEXCOORD0, + #ifdef SOFTPARTICLES + out float4 oScreenPos : TEXCOORD1, + #endif out float4 oWorldPos : TEXCOORD3, #if PERPIXEL #ifdef SHADOW @@ -62,6 +82,10 @@ void VS(float4 iPos : POSITION, oClip = dot(oPos, cClipPlane); #endif + #ifdef SOFTPARTICLES + oScreenPos = GetScreenPos(oPos); + #endif + #ifdef VERTEXCOLOR oColor = iColor; #endif @@ -72,7 +96,7 @@ void VS(float4 iPos : POSITION, #ifdef SHADOW // Shadow projection: transform from world space to shadow space - GetShadowPos(projWorldPos, oShadowPos); + GetShadowPos(projWorldPos, float3(0, 0, 0), oShadowPos); #endif #ifdef SPOTLIGHT @@ -95,6 +119,9 @@ void VS(float4 iPos : POSITION, } void PS(float2 iTexCoord : TEXCOORD0, + #ifdef SOFTPARTICLES + float4 iScreenPos: TEXCOORD1, + #endif float4 iWorldPos : TEXCOORD3, #ifdef PERPIXEL #ifdef SHADOW @@ -103,7 +130,7 @@ void PS(float2 iTexCoord : TEXCOORD0, #ifdef SPOTLIGHT float4 iSpotPos : TEXCOORD5, #endif - #ifdef CUBEMASK + #ifdef POINTLIGHT float3 iCubeMaskVec : TEXCOORD5, #endif #else @@ -140,6 +167,31 @@ void PS(float2 iTexCoord : TEXCOORD0, float fogFactor = GetFogFactor(iWorldPos.w); #endif + // Soft particle fade + // In expand mode depth test should be off. In that case do manual alpha discard test first to reduce fill rate + #ifdef SOFTPARTICLES + #ifdef EXPAND + if (diffColor.a < 0.01) + discard; + #endif + + float particleDepth = iWorldPos.w; + float depth = Sample2DProj(DepthBuffer, iScreenPos).r; + #ifdef HWDEPTH + depth = ReconstructDepth(depth); + #endif + + #ifdef EXPAND + float diffZ = max(particleDepth - depth, 0.0) * (cFarClipPS - cNearClipPS); + float fade = saturate(diffZ * cSoftParticleFadeScale); + #else + float diffZ = (depth - particleDepth) * (cFarClipPS - cNearClipPS); + float fade = saturate(1.0 - diffZ * cSoftParticleFadeScale); + #endif + + diffColor.a = max(diffColor.a - fade, 0.0); + #endif + #ifdef PERPIXEL // Per-pixel forward lighting float3 lightColor; diff --git a/res/coreData/Shaders/HLSL/LitSolid.hlsl b/res/coreData/Shaders/HLSL/LitSolid.hlsl index 9db278a..514b741 100644 --- a/res/coreData/Shaders/HLSL/LitSolid.hlsl +++ b/res/coreData/Shaders/HLSL/LitSolid.hlsl @@ -6,7 +6,7 @@ #include "Fog.hlsl" void VS(float4 iPos : POSITION, - #ifndef BILLBOARD + #if !defined(BILLBOARD) && !defined(TRAILFACECAM) float3 iNormal : NORMAL, #endif #ifndef NOUV @@ -18,7 +18,7 @@ void VS(float4 iPos : POSITION, #if defined(LIGHTMAP) || defined(AO) float2 iTexCoord2 : TEXCOORD1, #endif - #ifdef NORMALMAP + #if (defined(NORMALMAP) || defined(TRAILFACECAM) || defined(TRAILBONE)) && !defined(BILLBOARD) && !defined(DIRBILLBOARD) float4 iTangent : TANGENT, #endif #ifdef SKINNED @@ -26,9 +26,9 @@ void VS(float4 iPos : POSITION, int4 iBlendIndices : BLENDINDICES, #endif #ifdef INSTANCED - float4x3 iModelInstance : TEXCOORD2, + float4x3 iModelInstance : TEXCOORD4, #endif - #ifdef BILLBOARD + #if defined(BILLBOARD) || defined(DIRBILLBOARD) float2 iSize : TEXCOORD1, #endif #ifndef NORMALMAP @@ -87,10 +87,10 @@ void VS(float4 iPos : POSITION, #endif #ifdef NORMALMAP - float3 tangent = GetWorldTangent(modelMatrix); - float3 bitangent = cross(tangent, oNormal) * iTangent.w; + float4 tangent = GetWorldTangent(modelMatrix); + float3 bitangent = cross(tangent.xyz, oNormal) * tangent.w; oTexCoord = float4(GetTexCoord(iTexCoord), bitangent.xy); - oTangent = float4(tangent, bitangent.z); + oTangent = float4(tangent.xyz, bitangent.z); #else oTexCoord = GetTexCoord(iTexCoord); #endif @@ -101,7 +101,7 @@ void VS(float4 iPos : POSITION, #ifdef SHADOW // Shadow projection: transform from world space to shadow space - GetShadowPos(projWorldPos, oShadowPos); + GetShadowPos(projWorldPos, oNormal, oShadowPos); #endif #ifdef SPOTLIGHT @@ -152,7 +152,7 @@ void PS( #ifdef SPOTLIGHT float4 iSpotPos : TEXCOORD5, #endif - #ifdef CUBEMASK + #ifdef POINTLIGHT float3 iCubeMaskVec : TEXCOORD5, #endif #else @@ -247,7 +247,7 @@ void PS( #endif #ifdef AMBIENT - finalColor += cAmbientColor * diffColor.rgb; + finalColor += cAmbientColor.rgb * diffColor.rgb; finalColor += cMatEmissiveColor; oColor = float4(GetFog(finalColor, fogFactor), diffColor.a); #else @@ -267,7 +267,7 @@ void PS( float3 finalColor = iVertexLight * diffColor.rgb; #ifdef AO // If using AO, the vertex light ambient is black, calculate occluded ambient here - finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * cAmbientColor * diffColor.rgb; + finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * cAmbientColor.rgb * diffColor.rgb; #endif #ifdef ENVCUBEMAP finalColor += cMatEnvMapColor * SampleCube(EnvCubeMap, reflect(iReflectionVec, normal)).rgb; @@ -290,7 +290,7 @@ void PS( float3 finalColor = iVertexLight * diffColor.rgb; #ifdef AO // If using AO, the vertex light ambient is black, calculate occluded ambient here - finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * cAmbientColor * diffColor.rgb; + finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * cAmbientColor.rgb * diffColor.rgb; #endif #ifdef MATERIAL diff --git a/res/coreData/Shaders/HLSL/PBR.hlsl b/res/coreData/Shaders/HLSL/PBR.hlsl new file mode 100644 index 0000000..4f95434 --- /dev/null +++ b/res/coreData/Shaders/HLSL/PBR.hlsl @@ -0,0 +1,127 @@ +#include "BRDF.hlsl" +#ifdef COMPILEPS + + + + float3 SphereLight(float3 worldPos, float3 lightVec, float3 normal, float3 toCamera, float roughness, float3 specColor, out float ndl) + { + float3 pos = (cLightPosPS.xyz - worldPos); + float radius = cLightRad; + + float3 reflectVec = reflect(-toCamera, normal); + float3 centreToRay = dot(pos, reflectVec) * reflectVec - pos; + float3 closestPoint = pos + centreToRay * saturate(radius / length(centreToRay)); + + float3 l = normalize(closestPoint); + float3 h = normalize(toCamera + l); + + ndl = saturate(dot(normal, l)); + float hdn = saturate(dot(h, normal)); + float hdv = dot(h, toCamera); + float ndv = saturate(dot(normal, toCamera)); + + float distL = length(pos); + float alpha = roughness * roughness; + float alphaPrime = saturate(radius / (distL * 2.0) + alpha); + + const float3 fresnelTerm = Fresnel(specColor, hdv) ; + const float distTerm = Distribution(hdn, alphaPrime); + const float visTerm = Visibility(ndl, ndv, roughness); + + return distTerm * visTerm * fresnelTerm ; + } + + float3 TubeLight(float3 worldPos, float3 lightVec, float3 normal, float3 toCamera, float roughness, float3 specColor, out float ndl) + { + float radius = cLightRad; + float len = cLightLength; + float3 pos = (cLightPosPS.xyz - worldPos); + float3 reflectVec = reflect(-toCamera, normal); + + float3 L01 = cLightDirPS * len; + float3 L0 = pos - 0.5 * L01; + float3 L1 = pos + 0.5 * L01; + float3 ld = L1 - L0; + + float distL0 = length( L0 ); + float distL1 = length( L1 ); + + float NoL0 = dot( L0, normal ) / ( 2.0 * distL0 ); + float NoL1 = dot( L1, normal ) / ( 2.0 * distL1 ); + ndl = ( 2.0 * clamp( NoL0 + NoL1, 0.0, 1.0 ) ) + / ( distL0 * distL1 + dot( L0, L1 ) + 2.0 ); + + float a = len * len; + float b = dot( reflectVec, L01 ); + float t = saturate( dot( L0, b * reflectVec - L01 ) / (a - b*b) ); + + float3 closestPoint = L0 + ld * saturate( t); + float3 centreToRay = dot( closestPoint, reflectVec ) * reflectVec - closestPoint; + closestPoint = closestPoint + centreToRay * saturate(radius / length(centreToRay)); + + float3 l = normalize(closestPoint); + float3 h = normalize(toCamera + l); + + ndl = saturate(dot(normal, lightVec)); + float hdn = saturate(dot(h, normal)); + float hdv = dot(h, toCamera); + float ndv = saturate(dot(normal, toCamera)); + + float distL = length(closestPoint); + float alpha = roughness * roughness; + float alphaPrime = saturate(radius / (distL * 2.0) + alpha); + + const float3 fresnelTerm = Fresnel(specColor, hdv) ; + const float distTerm = Distribution(hdn, alphaPrime); + const float visTerm = Visibility(ndl, ndv, roughness); + + return distTerm * visTerm * fresnelTerm ; + } + + //Return the PBR BRDF value + // lightDir = the vector to the light + // lightVec = normalised lightDir + // toCamera = vector to the camera + // normal = surface normal of the pixel + // roughness = roughness of the pixel + // diffColor = the rgb color of the pixel + // specColor = the rgb specular color of the pixel + float3 GetBRDF(float3 worldPos, float3 lightDir, float3 lightVec, float3 toCamera, float3 normal, float roughness, float3 diffColor, float3 specColor) + { + + const float3 Hn = normalize(toCamera + lightDir); + const float vdh = clamp((dot(toCamera, Hn)), M_EPSILON, 1.0); + const float ndh = clamp((dot(normal, Hn)), M_EPSILON, 1.0); + float ndl = clamp((dot(normal, lightVec)), M_EPSILON, 1.0); + const float ndv = clamp((dot(normal, toCamera)), M_EPSILON, 1.0); + + const float3 diffuseFactor = Diffuse(diffColor, roughness, ndv, ndl, vdh) * ndl; + float3 specularFactor = 0; + + #ifdef SPECULAR + if(cLightRad > 0.0) + { + if(cLightLength > 0.0) + { + specularFactor = TubeLight(worldPos, lightVec, normal, toCamera, roughness, specColor, ndl); + specularFactor *= ndl; + } + else + { + specularFactor = SphereLight(worldPos, lightVec, normal, toCamera, roughness, specColor, ndl); + specularFactor *= ndl; + } + } + else + { + const float3 fresnelTerm = Fresnel(specColor, vdh) ; + const float distTerm = Distribution(ndh, roughness); + const float visTerm = Visibility(ndl, ndv, roughness); + specularFactor = distTerm * visTerm * fresnelTerm * ndl/ M_PI; + } + + #endif + + return diffuseFactor + specularFactor; + } +#endif diff --git a/res/coreData/Shaders/HLSL/PBRDeferred.hlsl b/res/coreData/Shaders/HLSL/PBRDeferred.hlsl new file mode 100644 index 0000000..9422f0e --- /dev/null +++ b/res/coreData/Shaders/HLSL/PBRDeferred.hlsl @@ -0,0 +1,128 @@ +#include "Uniforms.hlsl" +#include "Samplers.hlsl" +#include "Transform.hlsl" +#include "ScreenPos.hlsl" +#include "Lighting.hlsl" +#include "Constants.hlsl" +#include "PBR.hlsl" +#line 9 + +void VS(float4 iPos : POSITION, + #ifdef DIRLIGHT + out float2 oScreenPos : TEXCOORD0, + #else + out float4 oScreenPos : TEXCOORD0, + #endif + out float3 oFarRay : TEXCOORD1, + #ifdef ORTHO + out float3 oNearRay : TEXCOORD2, + #endif + out float4 oPos : OUTPOSITION) +{ + float4x3 modelMatrix = iModelMatrix; + float3 worldPos = GetWorldPos(modelMatrix); + oPos = GetClipPos(worldPos); + #ifdef DIRLIGHT + oScreenPos = GetScreenPosPreDiv(oPos); + oFarRay = GetFarRay(oPos); + #ifdef ORTHO + oNearRay = GetNearRay(oPos); + #endif + #else + oScreenPos = GetScreenPos(oPos); + oFarRay = GetFarRay(oPos) * oPos.w; + #ifdef ORTHO + oNearRay = GetNearRay(oPos) * oPos.w; + #endif + #endif +} + +void PS( + #ifdef DIRLIGHT + float2 iScreenPos : TEXCOORD0, + #else + float4 iScreenPos : TEXCOORD0, + #endif + float3 iFarRay : TEXCOORD1, + #ifdef ORTHO + float3 iNearRay : TEXCOORD2, + #endif + + float2 iFragPos : VPOS, + out float4 oColor : OUTCOLOR0) +{ + // If rendering a directional light quad, optimize out the w divide + #ifdef DIRLIGHT + float3 depth = Sample2DLod0(DepthBuffer, iScreenPos).r; + #ifdef HWDEPTH + depth = ReconstructDepth(depth); + #endif + #ifdef ORTHO + float3 worldPos = lerp(iNearRay, iFarRay, depth); + #else + float3 worldPos = iFarRay * depth; + #endif + const float4 albedoInput = Sample2DLod0(AlbedoBuffer, iScreenPos); + const float4 normalInput = Sample2DLod0(NormalBuffer, iScreenPos); + const float4 specularInput = Sample2DLod0(SpecMap, iScreenPos); + #else + float depth = Sample2DProj(DepthBuffer, iScreenPos).r; + #ifdef HWDEPTH + depth = ReconstructDepth(depth); + #endif + #ifdef ORTHO + float3 worldPos = lerp(iNearRay, iFarRay, depth) / iScreenPos.w; + #else + float3 worldPos = iFarRay * depth / iScreenPos.w; + #endif + const float4 albedoInput = Sample2DProj(AlbedoBuffer, iScreenPos); + const float4 normalInput = Sample2DProj(NormalBuffer, iScreenPos); + const float4 specularInput = Sample2DProj(SpecMap, iScreenPos); + #endif + + // Position acquired via near/far ray is relative to camera. Bring position to world space + float3 eyeVec = -worldPos; + worldPos += cCameraPosPS; + + float3 normal = normalInput.rgb; + const float roughness = length(normal); + normal = normalize(normal); + + const float3 specColor = specularInput.rgb; + + const float4 projWorldPos = float4(worldPos, 1.0); + + float3 lightDir; + float atten = 1; + + #if defined(DIRLIGHT) + atten = GetAtten(normal, worldPos, lightDir); + #elif defined(SPOTLIGHT) + atten = GetAttenSpot(normal, worldPos, lightDir); + #else + atten = GetAttenPoint(normal, worldPos, lightDir); + #endif + + float shadow = 1; + #ifdef SHADOW + shadow *= GetShadowDeferred(projWorldPos, normal, depth); + #endif + + #if defined(SPOTLIGHT) + const float4 spotPos = mul(projWorldPos, cLightMatricesPS[0]); + const float3 lightColor = spotPos.w > 0.0 ? Sample2DProj(LightSpotMap, spotPos).rgb * cLightColor.rgb : 0.0; + #elif defined(CUBEMASK) + const float3 lightColor = texCUBE(sLightCubeMap, mul(worldPos - cLightPosPS.xyz, (float3x3)cLightMatricesPS[0])).rgb * cLightColor.rgb; + #else + const float3 lightColor = cLightColor.rgb; + #endif + + const float3 toCamera = normalize(eyeVec); + const float3 lightVec = normalize(lightDir); + const float ndl = clamp(abs(dot(normal, lightVec)), M_EPSILON, 1.0); + + float3 BRDF = GetBRDF(worldPos, lightDir, lightVec, toCamera, normal, roughness, albedoInput.rgb, specColor); + + oColor.a = 1; + oColor.rgb = BRDF * lightColor * shadow * atten / M_PI; +} diff --git a/res/coreData/Shaders/HLSL/PBRLitSolid.hlsl b/res/coreData/Shaders/HLSL/PBRLitSolid.hlsl new file mode 100644 index 0000000..6c4835a --- /dev/null +++ b/res/coreData/Shaders/HLSL/PBRLitSolid.hlsl @@ -0,0 +1,344 @@ +#include "Uniforms.hlsl" +#include "Samplers.hlsl" +#include "Constants.hlsl" +#include "Transform.hlsl" +#include "ScreenPos.hlsl" +#include "Lighting.hlsl" +#include "Fog.hlsl" +#include "PBR.hlsl" +#include "IBL.hlsl" + +void VS(float4 iPos : POSITION, + #if !defined(BILLBOARD) && !defined(TRAILFACECAM) + float3 iNormal : NORMAL, + #endif + #ifndef NOUV + float2 iTexCoord : TEXCOORD0, + #endif + #ifdef VERTEXCOLOR + float4 iColor : COLOR0, + #endif + #if defined(LIGHTMAP) || defined(AO) + float2 iTexCoord2 : TEXCOORD1, + #endif + #if (defined(NORMALMAP)|| defined(IBL) || defined(TRAILFACECAM) || defined(TRAILBONE)) && !defined(BILLBOARD) && !defined(DIRBILLBOARD) + float4 iTangent : TANGENT, + #endif + #ifdef SKINNED + float4 iBlendWeights : BLENDWEIGHT, + int4 iBlendIndices : BLENDINDICES, + #endif + #ifdef INSTANCED + float4x3 iModelInstance : TEXCOORD4, + #endif + #if defined(BILLBOARD) || defined(DIRBILLBOARD) + float2 iSize : TEXCOORD1, + #endif + #if defined(NORMALMAP) || defined(IBL) + out float4 oTexCoord : TEXCOORD0, + out float4 oTangent : TEXCOORD3, + #else + out float2 oTexCoord : TEXCOORD0, + #endif + out float3 oNormal : TEXCOORD1, + out float4 oWorldPos : TEXCOORD2, + #ifdef PERPIXEL + #ifdef SHADOW + out float4 oShadowPos[NUMCASCADES] : TEXCOORD4, + #endif + #ifdef SPOTLIGHT + out float4 oSpotPos : TEXCOORD5, + #endif + #ifdef POINTLIGHT + out float3 oCubeMaskVec : TEXCOORD5, + #endif + #else + out float3 oVertexLight : TEXCOORD4, + out float4 oScreenPos : TEXCOORD5, + #ifdef ENVCUBEMAP + out float3 oReflectionVec : TEXCOORD6, + #endif + #if defined(LIGHTMAP) || defined(AO) + out float2 oTexCoord2 : TEXCOORD7, + #endif + #endif + #ifdef VERTEXCOLOR + out float4 oColor : COLOR0, + #endif + #if defined(D3D11) && defined(CLIPPLANE) + out float oClip : SV_CLIPDISTANCE0, + #endif + out float4 oPos : OUTPOSITION) +{ + // Define a 0,0 UV coord if not expected from the vertex data + #ifdef NOUV + const float2 iTexCoord = float2(0.0, 0.0); + #endif + + const float4x3 modelMatrix = iModelMatrix; + const float3 worldPos = GetWorldPos(modelMatrix); + oPos = GetClipPos(worldPos); + oNormal = GetWorldNormal(modelMatrix); + oWorldPos = float4(worldPos, GetDepth(oPos)); + + #if defined(D3D11) && defined(CLIPPLANE) + oClip = dot(oPos, cClipPlane); + #endif + + #ifdef VERTEXCOLOR + oColor = iColor; + #endif + + #if defined(NORMALMAP) || defined(IBL) + const float4 tangent = GetWorldTangent(modelMatrix); + const float3 bitangent = cross(tangent.xyz, oNormal) * tangent.w; + oTexCoord = float4(GetTexCoord(iTexCoord), bitangent.xy); + oTangent = float4(tangent.xyz, bitangent.z); + #else + oTexCoord = GetTexCoord(iTexCoord); + #endif + + #ifdef PERPIXEL + // Per-pixel forward lighting + const float4 projWorldPos = float4(worldPos.xyz, 1.0); + + #ifdef SHADOW + // Shadow projection: transform from world space to shadow space + GetShadowPos(projWorldPos, oNormal, oShadowPos); + #endif + + #ifdef SPOTLIGHT + // Spotlight projection: transform from world space to projector texture coordinates + oSpotPos = mul(projWorldPos, cLightMatrices[0]); + #endif + + #ifdef POINTLIGHT + oCubeMaskVec = mul(worldPos - cLightPos.xyz, (float3x3)cLightMatrices[0]); + #endif + #else + // Ambient & per-vertex lighting + #if defined(LIGHTMAP) || defined(AO) + // If using lightmap, disregard zone ambient light + // If using AO, calculate ambient in the PS + oVertexLight = float3(0.0, 0.0, 0.0); + oTexCoord2 = iTexCoord2; + #else + oVertexLight = GetAmbient(GetZonePos(worldPos)); + #endif + + #ifdef NUMVERTEXLIGHTS + for (int i = 0; i < NUMVERTEXLIGHTS; ++i) + oVertexLight += GetVertexLight(i, worldPos, oNormal) * cVertexLights[i * 3].rgb; + #endif + + oScreenPos = GetScreenPos(oPos); + + #ifdef ENVCUBEMAP + oReflectionVec = worldPos - cCameraPos; + #endif + #endif +} + +void PS( + #if defined(NORMALMAP) || defined(IBL) + float4 iTexCoord : TEXCOORD0, + float4 iTangent : TEXCOORD3, + #else + float2 iTexCoord : TEXCOORD0, + #endif + float3 iNormal : TEXCOORD1, + float4 iWorldPos : TEXCOORD2, + #ifdef PERPIXEL + #ifdef SHADOW + float4 iShadowPos[NUMCASCADES] : TEXCOORD4, + #endif + #ifdef SPOTLIGHT + float4 iSpotPos : TEXCOORD5, + #endif + #ifdef POINTLIGHT + float3 iCubeMaskVec : TEXCOORD5, + #endif + #else + float3 iVertexLight : TEXCOORD4, + float4 iScreenPos : TEXCOORD5, + #ifdef ENVCUBEMAP + float3 iReflectionVec : TEXCOORD6, + #endif + #if defined(LIGHTMAP) || defined(AO) + float2 iTexCoord2 : TEXCOORD7, + #endif + #endif + #ifdef VERTEXCOLOR + float4 iColor : COLOR0, + #endif + #if defined(D3D11) && defined(CLIPPLANE) + float iClip : SV_CLIPDISTANCE0, + #endif + #ifdef PREPASS + out float4 oDepth : OUTCOLOR1, + #endif + #ifdef DEFERRED + out float4 oAlbedo : OUTCOLOR1, + out float4 oNormal : OUTCOLOR2, + out float4 oDepth : OUTCOLOR3, + #ifndef D3D11 + float2 iFragPos : VPOS, + #else + float4 iFragPos : SV_Position, + #endif + #endif + out float4 oColor : OUTCOLOR0) +{ + // Get material diffuse albedo + #ifdef DIFFMAP + const float4 diffInput = Sample2D(DiffMap, iTexCoord.xy); + #ifdef ALPHAMASK + if (diffInput.a < 0.5) + discard; + #endif + float4 diffColor = cMatDiffColor * diffInput; + #else + float4 diffColor = cMatDiffColor; + #endif + + #ifdef VERTEXCOLOR + diffColor *= iColor; + #endif + + // Get material specular albedo + #ifdef METALLIC // METALNESS + float4 roughMetalSrc = Sample2D(RoughMetalFresnel, iTexCoord.xy); + + float roughness = roughMetalSrc.r + cRoughness; + float metalness = roughMetalSrc.g + cMetallic; + #else + float roughness = cRoughness; + float metalness = cMetallic; + #endif + + roughness *= roughness; + + roughness = clamp(roughness, ROUGHNESS_FLOOR, 1.0); + metalness = clamp(metalness, METALNESS_FLOOR, 1.0); + + float3 specColor = lerp(0.08 * cMatSpecColor.rgb, diffColor.rgb, metalness); + specColor *= cMatSpecColor.rgb; + diffColor.rgb = diffColor.rgb - diffColor.rgb * metalness; // Modulate down the diffuse + + // Get normal + #if defined(NORMALMAP) || defined(IBL) + const float3 tangent = normalize(iTangent.xyz); + const float3 bitangent = normalize(float3(iTexCoord.zw, iTangent.w)); + const float3x3 tbn = float3x3(tangent, bitangent, iNormal); + #endif + + #ifdef NORMALMAP + const float3 nn = DecodeNormal(Sample2D(NormalMap, iTexCoord.xy)); + //nn.rg *= 2.0; + const float3 normal = normalize(mul(nn, tbn)); + #else + const float3 normal = normalize(iNormal); + #endif + + // Get fog factor + #ifdef HEIGHTFOG + const float fogFactor = GetHeightFogFactor(iWorldPos.w, iWorldPos.y); + #else + const float fogFactor = GetFogFactor(iWorldPos.w); + #endif + + #if defined(PERPIXEL) + // Per-pixel forward lighting + float3 lightDir; + float3 lightColor; + float3 finalColor; + float atten = 1; + + #if defined(DIRLIGHT) + atten = GetAtten(normal, iWorldPos.xyz, lightDir); + #elif defined(SPOTLIGHT) + atten = GetAttenSpot(normal, iWorldPos.xyz, lightDir); + #else + atten = GetAttenPoint(normal, iWorldPos.xyz, lightDir); + #endif + + float shadow = 1.0; + + #ifdef SHADOW + shadow *= GetShadow(iShadowPos, iWorldPos.w); + #endif + + #if defined(SPOTLIGHT) + lightColor = iSpotPos.w > 0.0 ? Sample2DProj(LightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0; + #elif defined(CUBEMASK) + lightColor = SampleCube(LightCubeMap, iCubeMaskVec).rgb * cLightColor.rgb; + #else + lightColor = cLightColor.rgb; + #endif + + const float3 toCamera = normalize(cCameraPosPS - iWorldPos.xyz); + + const float3 lightVec = normalize(lightDir); + const float ndl = clamp((dot(normal, lightVec)), M_EPSILON, 1.0); + + + float3 BRDF = GetBRDF(iWorldPos.xyz, lightDir, lightVec, toCamera, normal, roughness, diffColor.rgb, specColor); + finalColor.rgb = BRDF * lightColor * (atten * shadow) / M_PI; + + #ifdef AMBIENT + finalColor += cAmbientColor.rgb * diffColor.rgb; + finalColor += cMatEmissiveColor; + oColor = float4(GetFog(finalColor, fogFactor), diffColor.a); + #else + oColor = float4(GetLitFog(finalColor, fogFactor), diffColor.a); + #endif + #elif defined(DEFERRED) + // Fill deferred G-buffer + const float3 spareData = 0; // Can be used to pass more data to deferred renderer + oColor = float4(specColor, spareData.r); + oAlbedo = float4(diffColor.rgb, spareData.g); + oNormal = float4(normalize(normal) * roughness, spareData.b); + oDepth = iWorldPos.w; + #else + // Ambient & per-vertex lighting + float3 finalColor = iVertexLight * diffColor.rgb; + #ifdef AO + // If using AO, the vertex light ambient is black, calculate occluded ambient here + finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * cAmbientColor.rgb * diffColor.rgb; + #endif + + #ifdef MATERIAL + // Add light pre-pass accumulation result + // Lights are accumulated at half intensity. Bring back to full intensity now + float4 lightInput = 2.0 * Sample2DProj(LightBuffer, iScreenPos); + float3 lightSpecColor = lightInput.a * lightInput.rgb / max(GetIntensity(lightInput.rgb), 0.001); + + finalColor += lightInput.rgb * diffColor.rgb + lightSpecColor * specColor; + #endif + + const float3 toCamera = normalize(iWorldPos.xyz - cCameraPosPS); + + const float3 reflection = normalize(reflect(toCamera, normal)); + float3 cubeColor = iVertexLight.rgb; + + #ifdef IBL + const float3 iblColor = ImageBasedLighting(reflection, tangent, bitangent, normal, toCamera, diffColor, specColor, roughness, cubeColor); + const float gamma = 0; + finalColor += iblColor; + #endif + + #ifdef ENVCUBEMAP + finalColor += cMatEnvMapColor * SampleCube(EnvCubeMap, reflect(iReflectionVec, normal)).rgb; + #endif + #ifdef LIGHTMAP + finalColor += Sample2D(EmissiveMap, iTexCoord2).rgb * diffColor.rgb; + #endif + #ifdef EMISSIVEMAP + finalColor += cMatEmissiveColor * Sample2D(EmissiveMap, iTexCoord.xy).rgb; + #else + finalColor += cMatEmissiveColor; + #endif + + oColor = float4(GetFog(finalColor, fogFactor), diffColor.a); + #endif +} diff --git a/res/coreData/Shaders/HLSL/PrepassLight.hlsl b/res/coreData/Shaders/HLSL/PrepassLight.hlsl index 6f06f0e..57b0f08 100644 --- a/res/coreData/Shaders/HLSL/PrepassLight.hlsl +++ b/res/coreData/Shaders/HLSL/PrepassLight.hlsl @@ -71,6 +71,10 @@ void PS( float4 normalInput = Sample2DProj(NormalBuffer, iScreenPos); #endif + // Position acquired via near/far ray is relative to camera. Bring position to world space + float3 eyeVec = -worldPos; + worldPos += cCameraPosPS; + float3 normal = normalize(normalInput.rgb * 2.0 - 1.0); float4 projWorldPos = float4(worldPos, 1.0); float3 lightColor; @@ -80,7 +84,7 @@ void PS( float diff = 0.5 * GetDiffuse(normal, worldPos, lightDir); #ifdef SHADOW - diff *= GetShadowDeferred(projWorldPos, depth); + diff *= GetShadowDeferred(projWorldPos, normal, depth); #endif #if defined(SPOTLIGHT) @@ -93,7 +97,7 @@ void PS( #endif #ifdef SPECULAR - float spec = lightColor.g * GetSpecular(normal, -worldPos, lightDir, normalInput.a * 255.0); + float spec = lightColor.g * GetSpecular(normal, eyeVec, lightDir, normalInput.a * 255.0); oColor = diff * float4(lightColor, spec * cLightColor.a); #else oColor = diff * float4(lightColor, 0.0); diff --git a/res/coreData/Shaders/HLSL/Samplers.hlsl b/res/coreData/Shaders/HLSL/Samplers.hlsl index 63d4f74..c7efb7e 100644 --- a/res/coreData/Shaders/HLSL/Samplers.hlsl +++ b/res/coreData/Shaders/HLSL/Samplers.hlsl @@ -4,6 +4,7 @@ #define Sample2DProj(tex, uv) t##tex.Sample(s##tex, uv.xy / uv.w) #define Sample2DLod0(tex, uv) t##tex.SampleLevel(s##tex, uv, 0.0) #define SampleCube(tex, uv) t##tex.Sample(s##tex, uv) +#define SampleCubeLOD(tex, uv) t##tex.SampleLevel(s##tex, uv.xyz, uv.w) #define SampleShadow(tex, uv) t##tex.SampleCmpLevelZero(s##tex, uv.xy, uv.z) #endif @@ -18,6 +19,7 @@ sampler2D sAlbedoBuffer : register(s0); sampler2D sNormalMap : register(s1); sampler2D sNormalBuffer : register(s1); sampler2D sSpecMap : register(s2); +sampler2D sRoughMetalFresnel : register(s2); //R: Roughness, G: Metal sampler2D sEmissiveMap : register(s3); sampler2D sEnvMap : register(s4); sampler3D sVolumeMap : register(s5); @@ -37,6 +39,7 @@ sampler3D sZoneVolumeMap : register(s15); #define Sample2DProj(tex, uv) tex2Dproj(s##tex, uv) #define Sample2DLod0(tex, uv) tex2Dlod(s##tex, float4(uv, 0.0, 0.0)) #define SampleCube(tex, uv) texCUBE(s##tex, uv) +#define SampleCubeLOD(tex, uv) texCUBElod(s##tex, uv) #define SampleShadow(tex, uv) tex2Dproj(s##tex, uv) #else @@ -49,6 +52,7 @@ Texture2D tAlbedoBuffer : register(t0); Texture2D tNormalMap : register(t1); Texture2D tNormalBuffer : register(t1); Texture2D tSpecMap : register(t2); +Texture2D tRoughMetalFresnel : register(t2); //R: Roughness, G: Metal Texture2D tEmissiveMap : register(t3); Texture2D tEnvMap : register(t4); Texture3D tVolumeMap : register(t5); @@ -70,6 +74,7 @@ SamplerState sAlbedoBuffer : register(s0); SamplerState sNormalMap : register(s1); SamplerState sNormalBuffer : register(s1); SamplerState sSpecMap : register(s2); +SamplerState sRoughMetalFresnel : register(s2); //R: Roughness, G: Metal SamplerState sEmissiveMap : register(s3); SamplerState sEnvMap : register(s4); SamplerState sVolumeMap : register(s5); @@ -77,7 +82,11 @@ SamplerState sEnvCubeMap : register(s4); SamplerState sLightRampMap : register(s8); SamplerState sLightSpotMap : register(s9); SamplerState sLightCubeMap : register(s9); -SamplerComparisonState sShadowMap : register(s10); +#ifdef VSM_SHADOW + SamplerState sShadowMap : register(s10); +#else + SamplerComparisonState sShadowMap : register(s10); +#endif SamplerState sFaceSelectCubeMap : register(s11); SamplerState sIndirectionCubeMap : register(s12); SamplerState sDepthBuffer : register(s13); diff --git a/res/coreData/Shaders/HLSL/ScreenPos.hlsl b/res/coreData/Shaders/HLSL/ScreenPos.hlsl index bff2e71..8c0c98a 100644 --- a/res/coreData/Shaders/HLSL/ScreenPos.hlsl +++ b/res/coreData/Shaders/HLSL/ScreenPos.hlsl @@ -1,4 +1,11 @@ #ifdef COMPILEVS +float3x3 GetCameraRot() +{ + return float3x3(cViewInv[0][0], cViewInv[0][1], cViewInv[0][2], + cViewInv[1][0], cViewInv[1][1], cViewInv[1][2], + cViewInv[2][0], cViewInv[2][1], cViewInv[2][2]); +} + float4 GetScreenPos(float4 clipPos) { return float4( @@ -36,7 +43,7 @@ float3 GetFarRay(float4 clipPos) clipPos.y / clipPos.w * cFrustumSize.y, cFrustumSize.z); - return mul(viewRay, cCameraRot); + return mul(viewRay, GetCameraRot()); } float3 GetNearRay(float4 clipPos) @@ -46,6 +53,6 @@ float3 GetNearRay(float4 clipPos) clipPos.y / clipPos.w * cFrustumSize.y, 0.0); - return mul(viewRay, cCameraRot) * cDepthMode.z; + return mul(viewRay, GetCameraRot()) * cDepthMode.z; } #endif diff --git a/res/coreData/Shaders/HLSL/Shadow.hlsl b/res/coreData/Shaders/HLSL/Shadow.hlsl index 0834689..88d7972 100644 --- a/res/coreData/Shaders/HLSL/Shadow.hlsl +++ b/res/coreData/Shaders/HLSL/Shadow.hlsl @@ -3,32 +3,59 @@ #include "Transform.hlsl" void VS(float4 iPos : POSITION, + #ifndef NOUV + float2 iTexCoord : TEXCOORD0, + #endif #ifdef SKINNED float4 iBlendWeights : BLENDWEIGHT, int4 iBlendIndices : BLENDINDICES, #endif #ifdef INSTANCED - float4x3 iModelInstance : TEXCOORD2, + float4x3 iModelInstance : TEXCOORD4, + #endif + #if defined(BILLBOARD) || defined(DIRBILLBOARD) + float2 iSize : TEXCOORD1, + #endif + #ifdef VSM_SHADOW + out float4 oTexCoord : TEXCOORD0, + #else + out float2 oTexCoord : TEXCOORD0, #endif - float2 iTexCoord : TEXCOORD0, - out float2 oTexCoord : TEXCOORD0, out float4 oPos : OUTPOSITION) { + // Define a 0,0 UV coord if not expected from the vertex data + #ifdef NOUV + float2 iTexCoord = float2(0.0, 0.0); + #endif + float4x3 modelMatrix = iModelMatrix; float3 worldPos = GetWorldPos(modelMatrix); oPos = GetClipPos(worldPos); - oTexCoord = GetTexCoord(iTexCoord); + #ifdef VSM_SHADOW + oTexCoord = float4(GetTexCoord(iTexCoord), oPos.z, oPos.w); + #else + oTexCoord = GetTexCoord(iTexCoord); + #endif } void PS( - float2 iTexCoord : TEXCOORD0, + #ifdef VSM_SHADOW + float4 iTexCoord : TEXCOORD0, + #else + float2 iTexCoord : TEXCOORD0, + #endif out float4 oColor : OUTCOLOR0) { #ifdef ALPHAMASK - float alpha = Sample2D(DiffMap, iTexCoord).a; + float alpha = Sample2D(DiffMap, iTexCoord.xy).a; if (alpha < 0.5) discard; #endif - oColor = 1.0; + #ifdef VSM_SHADOW + float depth = iTexCoord.z / iTexCoord.w; + oColor = float4(depth, depth * depth, 1.0, 1.0); + #else + oColor = 1.0; + #endif } diff --git a/res/coreData/Shaders/HLSL/ShadowBlur.hlsl b/res/coreData/Shaders/HLSL/ShadowBlur.hlsl new file mode 100644 index 0000000..fbcd919 --- /dev/null +++ b/res/coreData/Shaders/HLSL/ShadowBlur.hlsl @@ -0,0 +1,48 @@ +#include "Uniforms.hlsl" +#include "Samplers.hlsl" +#include "Transform.hlsl" +#include "ScreenPos.hlsl" + +#ifndef D3D11 + +// D3D9 uniforms +uniform float2 cBlurOffsets; + +#else + +#ifdef COMPILEPS +// D3D11 constant buffers +cbuffer CustomPS : register(b6) +{ + float2 cBlurOffsets; +} +#endif + +#endif + +void VS(float4 iPos : POSITION, + out float2 oScreenPos : TEXCOORD0, + out float4 oPos : OUTPOSITION) +{ + float4x3 modelMatrix = iModelMatrix; + float3 worldPos = GetWorldPos(modelMatrix); + oPos = GetClipPos(worldPos); + oScreenPos = GetScreenPosPreDiv(oPos); +} + +void PS(float2 iScreenPos : TEXCOORD0, + out float4 oColor : OUTCOLOR0) +{ + float2 color = 0.0; + + color += 0.015625 * Sample2D(DiffMap, iScreenPos - 3.0 * cBlurOffsets).rg; + color += 0.09375 * Sample2D(DiffMap, iScreenPos - 2.0 * cBlurOffsets).rg; + color += 0.234375 * Sample2D(DiffMap, iScreenPos - cBlurOffsets).rg; + color += 0.3125 * Sample2D(DiffMap, iScreenPos).rg; + color += 0.234375 * Sample2D(DiffMap, iScreenPos + cBlurOffsets).rg; + color += 0.09375 * Sample2D(DiffMap, iScreenPos + 2.0 * cBlurOffsets).rg; + color += 0.015625 * Sample2D(DiffMap, iScreenPos + 3.0 * cBlurOffsets).rg; + + oColor = float4(color, 0.0, 0.0); +} + diff --git a/res/coreData/Shaders/HLSL/Skybox.hlsl b/res/coreData/Shaders/HLSL/Skybox.hlsl index 6af0fe7..cf99553 100644 --- a/res/coreData/Shaders/HLSL/Skybox.hlsl +++ b/res/coreData/Shaders/HLSL/Skybox.hlsl @@ -3,13 +3,16 @@ #include "Transform.hlsl" void VS(float4 iPos : POSITION, + #ifdef INSTANCED + float4x3 iModelInstance : TEXCOORD4, + #endif out float3 oTexCoord : TEXCOORD0, out float4 oPos : OUTPOSITION) { float4x3 modelMatrix = iModelMatrix; float3 worldPos = GetWorldPos(modelMatrix); oPos = GetClipPos(worldPos); - + oPos.z = oPos.w; oTexCoord = iPos.xyz; } @@ -17,5 +20,9 @@ void VS(float4 iPos : POSITION, void PS(float3 iTexCoord : TEXCOORD0, out float4 oColor : OUTCOLOR0) { - oColor = cMatDiffColor * SampleCube(DiffCubeMap, iTexCoord); + float4 sky = cMatDiffColor * SampleCube(DiffCubeMap, iTexCoord); + #ifdef HDRSCALE + sky = pow(sky + clamp((cAmbientColor.a - 1.0) * 0.1, 0.0, 0.25), max(cAmbientColor.a, 1.0)) * clamp(cAmbientColor.a, 0.0, 1.0); + #endif + oColor = sky; } diff --git a/res/coreData/Shaders/HLSL/Skydome.hlsl b/res/coreData/Shaders/HLSL/Skydome.hlsl new file mode 100644 index 0000000..86533f3 --- /dev/null +++ b/res/coreData/Shaders/HLSL/Skydome.hlsl @@ -0,0 +1,22 @@ +#include "Uniforms.hlsl" +#include "Samplers.hlsl" +#include "Transform.hlsl" + +void VS(float4 iPos : POSITION, + float2 iTexCoord: TEXCOORD0, + out float2 oTexCoord : TEXCOORD0, + out float4 oPos : OUTPOSITION) +{ + float4x3 modelMatrix = iModelMatrix; + float3 worldPos = GetWorldPos(modelMatrix); + oPos = GetClipPos(worldPos); + + oPos.z = oPos.w; + oTexCoord = iTexCoord; +} + +void PS(float2 iTexCoord : TEXCOORD0, + out float4 oColor : OUTCOLOR0) +{ + oColor = cMatDiffColor * Sample2D(DiffMap, iTexCoord); +} diff --git a/res/coreData/Shaders/HLSL/TerrainBlend.hlsl b/res/coreData/Shaders/HLSL/TerrainBlend.hlsl index 07d1573..a3960a6 100644 --- a/res/coreData/Shaders/HLSL/TerrainBlend.hlsl +++ b/res/coreData/Shaders/HLSL/TerrainBlend.hlsl @@ -46,11 +46,14 @@ void VS(float4 iPos : POSITION, int4 iBlendIndices : BLENDINDICES, #endif #ifdef INSTANCED - float4x3 iModelInstance : TEXCOORD2, + float4x3 iModelInstance : TEXCOORD4, #endif - #ifdef BILLBOARD + #if defined(BILLBOARD) || defined(DIRBILLBOARD) float2 iSize : TEXCOORD1, #endif + #if defined(TRAILFACECAM) || defined(TRAILBONE) + float4 iTangent : TANGENT, + #endif out float2 oTexCoord : TEXCOORD0, out float3 oNormal : TEXCOORD1, out float4 oWorldPos : TEXCOORD2, @@ -92,7 +95,7 @@ void VS(float4 iPos : POSITION, #ifdef SHADOW // Shadow projection: transform from world space to shadow space - GetShadowPos(projWorldPos, oShadowPos); + GetShadowPos(projWorldPos, oNormal, oShadowPos); #endif #ifdef SPOTLIGHT @@ -127,7 +130,7 @@ void PS(float2 iTexCoord : TEXCOORD0, #ifdef SPOTLIGHT float4 iSpotPos : TEXCOORD5, #endif - #ifdef CUBEMASK + #ifdef POINTLIGHT float3 iCubeMaskVec : TEXCOORD5, #endif #else @@ -198,7 +201,7 @@ void PS(float2 iTexCoord : TEXCOORD0, #endif #ifdef AMBIENT - finalColor += cAmbientColor * diffColor.rgb; + finalColor += cAmbientColor.rgb * diffColor.rgb; finalColor += cMatEmissiveColor; oColor = float4(GetFog(finalColor, fogFactor), diffColor.a); #else diff --git a/res/coreData/Shaders/HLSL/Text.hlsl b/res/coreData/Shaders/HLSL/Text.hlsl index 3e3f23e..c944309 100644 --- a/res/coreData/Shaders/HLSL/Text.hlsl +++ b/res/coreData/Shaders/HLSL/Text.hlsl @@ -37,38 +37,76 @@ void VS(float4 iPos : POSITION, oTexCoord = iTexCoord; } +// See notes in GLSL shader +#if defined(COMPILEPS) && defined(SIGNED_DISTANCE_FIELD) + float GetAlpha(float distance, float width) + { + return smoothstep(0.5 - width, 0.5 + width, distance); + } + + // Comment this define to turn off supersampling + #define SUPERSAMPLING +#endif + + void PS(float2 iTexCoord : TEXCOORD0, float4 iColor : COLOR0, out float4 oColor : OUTCOLOR0) { - oColor.rgb = iColor.rgb; - #ifdef SIGNED_DISTANCE_FIELD + oColor.rgb = iColor.rgb; float distance = Sample2D(DiffMap, iTexCoord).a; - if (distance < 0.5f) - { - #ifdef TEXT_EFFECT_SHADOW - if (Sample2D(DiffMap, iTexCoord - cShadowOffset).a > 0.5f) - oColor = cShadowColor; - else - #endif - oColor.a = 0.0f; - } - else - { + #ifdef TEXT_EFFECT_STROKE - if (distance < 0.525f) - oColor.rgb = cStrokeColor.rgb; + #ifdef SUPERSAMPLING + float outlineFactor = smoothstep(0.5, 0.525, distance); // Border of glyph + oColor.rgb = lerp(cStrokeColor.rgb, iColor.rgb, outlineFactor); + #else + if (distance < 0.525) + oColor.rgb = cStrokeColor.rgb; + #endif #endif #ifdef TEXT_EFFECT_SHADOW - if (Sample2D(DiffMap, iTexCoord + cShadowOffset).a < 0.5f) - oColor.a = iColor.a; + if (Sample2D(DiffMap, iTexCoord - cShadowOffset).a > 0.5 && distance <= 0.5) + oColor = cShadowColor; + #ifndef SUPERSAMPLING + else if (distance <= 0.5) + oColor.a = 0.0; + #endif else #endif - oColor.a = iColor.a * smoothstep(0.5f, 0.505f, distance); - } + { + float width = fwidth(distance); + float alpha = GetAlpha(distance, width); + + #ifdef SUPERSAMPLING + float2 deltaUV = 0.354 * fwidth(iTexCoord); // (1.0 / sqrt(2.0)) / 2.0 = 0.354 + float4 square = float4(iTexCoord - deltaUV, iTexCoord + deltaUV); + + float distance2 = Sample2D(DiffMap, square.xy).a; + float distance3 = Sample2D(DiffMap, square.zw).a; + float distance4 = Sample2D(DiffMap, square.xw).a; + float distance5 = Sample2D(DiffMap, square.zy).a; + + alpha += GetAlpha(distance2, width) + + GetAlpha(distance3, width) + + GetAlpha(distance4, width) + + GetAlpha(distance5, width); + + // For calculating of average correct would be dividing by 5. + // But when text is blurred, its brightness is lost. Therefore divide by 4. + alpha = alpha * 0.25; + #endif + + oColor.a = alpha; + } #else - oColor.a = iColor.a * Sample2D(DiffMap, iTexCoord).a; + #ifdef ALPHAMAP + oColor.rgb = iColor.rgb; + oColor.a = iColor.a * Sample2D(DiffMap, iTexCoord).a; + #else + oColor = iColor* Sample2D(DiffMap, iTexCoord); + #endif #endif -} \ No newline at end of file +} diff --git a/res/coreData/Shaders/HLSL/Transform.hlsl b/res/coreData/Shaders/HLSL/Transform.hlsl index bb1f87a..94c4439 100644 --- a/res/coreData/Shaders/HLSL/Transform.hlsl +++ b/res/coreData/Shaders/HLSL/Transform.hlsl @@ -48,27 +48,103 @@ float3 GetBillboardNormal() } #endif +#ifdef DIRBILLBOARD +float3x3 GetFaceCameraRotation(float3 position, float3 direction) +{ + float3 cameraDir = normalize(position - cCameraPos); + float3 front = normalize(direction); + float3 right = normalize(cross(front, cameraDir)); + float3 up = normalize(cross(front, right)); + + return float3x3( + right.x, right.y, right.z, + up.x, up.y, up.z, + front.x, front.y, front.z + ); +} + +float3 GetBillboardPos(float4 iPos, float2 iSize, float3 iDirection, float4x3 modelMatrix) +{ + float3 worldPos = mul(iPos, modelMatrix); + return worldPos + mul(float3(iSize.x, 0.0, iSize.y), GetFaceCameraRotation(worldPos, iDirection)); +} + +float3 GetBillboardNormal(float4 iPos, float3 iDirection, float4x3 modelMatrix) +{ + float3 worldPos = mul(iPos, modelMatrix); + return mul(float3(0.0, 1.0, 0.0), GetFaceCameraRotation(worldPos, iDirection)); +} +#endif + +#ifdef TRAILFACECAM +float3 GetTrailPos(float4 iPos, float3 iFront, float iScale, float4x3 modelMatrix) +{ + float3 up = normalize(cCameraPos - iPos.xyz); + float3 left = normalize(cross(iFront, up)); + return (mul(float4((iPos.xyz + left * iScale), 1.0), modelMatrix)).xyz; +} + +float3 GetTrailNormal(float4 iPos) +{ + return normalize(cCameraPos - iPos.xyz); +} +#endif + +#ifdef TRAILBONE +float3 GetTrailPos(float4 iPos, float3 iParentPos, float iScale, float4x3 modelMatrix) +{ + float3 right = iParentPos - iPos.xyz; + return (mul(float4((iPos.xyz + right * iScale), 1.0), modelMatrix)).xyz; +} + +float3 GetTrailNormal(float4 iPos, float3 iParentPos, float3 iForward) +{ + float3 left = normalize(iPos.xyz - iParentPos); + float3 up = -normalize(cross(normalize(iForward), left)); + return up; +} +#endif + #if defined(SKINNED) - #define iModelMatrix GetSkinMatrix(iBlendWeights, iBlendIndices); + #define iModelMatrix GetSkinMatrix(iBlendWeights, iBlendIndices) #elif defined(INSTANCED) #define iModelMatrix iModelInstance #else #define iModelMatrix cModel #endif -#ifdef BILLBOARD +#if defined(BILLBOARD) #define GetWorldPos(modelMatrix) GetBillboardPos(iPos, iSize, modelMatrix) +#elif defined(DIRBILLBOARD) + #define GetWorldPos(modelMatrix) GetBillboardPos(iPos, iSize, iNormal, modelMatrix) +#elif defined(TRAILFACECAM) + #define GetWorldPos(modelMatrix) GetTrailPos(iPos, iTangent.xyz, iTangent.w, modelMatrix) +#elif defined(TRAILBONE) + #define GetWorldPos(modelMatrix) GetTrailPos(iPos, iTangent.xyz, iTangent.w, modelMatrix) #else #define GetWorldPos(modelMatrix) mul(iPos, modelMatrix) #endif -#ifdef BILLBOARD +#if defined(BILLBOARD) #define GetWorldNormal(modelMatrix) GetBillboardNormal() +#elif defined(DIRBILLBOARD) + #define GetWorldNormal(modelMatrix) GetBillboardNormal(iPos, iNormal, modelMatrix) +#elif defined(TRAILFACECAM) + #define GetWorldNormal(modelMatrix) GetTrailNormal(iPos) +#elif defined(TRAILBONE) + #define GetWorldNormal(modelMatrix) GetTrailNormal(iPos, iTangent.xyz, iNormal) #else #define GetWorldNormal(modelMatrix) normalize(mul(iNormal, (float3x3)modelMatrix)) #endif -#define GetWorldTangent(modelMatrix) normalize(mul(iTangent.xyz, (float3x3)modelMatrix)) +#if defined(BILLBOARD) + #define GetWorldTangent(modelMatrix) float4(normalize(mul(float3(1.0, 0.0, 0.0), cBillboardRot)), 1.0) +#elif defined(DIRBILLBOARD) + #define GetWorldTangent(modelMatrix) float4(normalize(mul(float3(1.0, 0.0, 0.0), (float3x3)modelMatrix)), 1.0) +#else + #define GetWorldTangent(modelMatrix) float4(normalize(mul(iTangent.xyz, (float3x3)modelMatrix)), iTangent.w) +#endif + #endif #ifdef COMPILEPS diff --git a/res/coreData/Shaders/HLSL/Uniforms.hlsl b/res/coreData/Shaders/HLSL/Uniforms.hlsl index 94a7cb4..4d211b6 100644 --- a/res/coreData/Shaders/HLSL/Uniforms.hlsl +++ b/res/coreData/Shaders/HLSL/Uniforms.hlsl @@ -11,7 +11,6 @@ uniform float3 cAmbientEndColor; uniform float3x3 cBillboardRot; #endif uniform float3 cCameraPos; -uniform float3x3 cCameraRot; uniform float cNearClip; uniform float cFarClip; uniform float4 cDepthMode; @@ -19,9 +18,12 @@ uniform float cDeltaTime; uniform float cElapsedTime; uniform float3 cFrustumSize; uniform float4 cGBufferOffsets; -uniform float3 cLightDir; uniform float4 cLightPos; +uniform float3 cLightDir; +uniform float4 cNormalOffsetScale; uniform float4x3 cModel; +uniform float4x3 cView; +uniform float4x3 cViewInv; uniform float4x4 cViewProj; uniform float4 cUOffset; uniform float4 cVOffset; @@ -39,7 +41,7 @@ uniform float4x3 cZone; #ifdef COMPILEPS // Pixel shader uniforms -uniform float3 cAmbientColor; +uniform float4 cAmbientColor; uniform float3 cCameraPosPS; uniform float cDeltaTimePS; uniform float4 cDepthReconstruct; @@ -50,10 +52,19 @@ uniform float2 cGBufferInvSize; uniform float4 cLightColor; uniform float4 cLightPosPS; uniform float3 cLightDirPS; +uniform float4 cNormalOffsetScalePS; uniform float4 cMatDiffColor; uniform float3 cMatEmissiveColor; uniform float3 cMatEnvMapColor; uniform float4 cMatSpecColor; +#ifdef PBR + uniform float cRoughness; + uniform float cMetallic; + uniform float cLightRad; + uniform float cLightLength; +#endif +uniform float3 cZoneMin; +uniform float3 cZoneMax; uniform float cNearClipPS; uniform float cFarClipPS; uniform float4 cShadowCubeAdjust; @@ -62,6 +73,9 @@ uniform float2 cShadowIntensity; uniform float2 cShadowMapInvSize; uniform float4 cShadowSplits; uniform float4x4 cLightMatricesPS[4]; +#ifdef VSM_SHADOW +uniform float2 cVSMShadowParams; +#endif #endif #else @@ -80,12 +94,13 @@ cbuffer FrameVS : register(b0) cbuffer CameraVS : register(b1) { float3 cCameraPos; - float3x3 cCameraRot; float cNearClip; float cFarClip; float4 cDepthMode; float3 cFrustumSize; float4 cGBufferOffsets; + float4x3 cView; + float4x3 cViewInv; float4x4 cViewProj; float4 cClipPlane; } @@ -99,8 +114,9 @@ cbuffer ZoneVS : register(b2) cbuffer LightVS : register(b3) { - float3 cLightDir; float4 cLightPos; + float3 cLightDir; + float4 cNormalOffsetScale; #ifdef NUMVERTEXLIGHTS float4 cVertexLights[4 * 3]; #else @@ -148,9 +164,11 @@ cbuffer CameraPS : register(b1) cbuffer ZonePS : register(b2) { - float3 cAmbientColor; + float4 cAmbientColor; float4 cFogParams; float3 cFogColor; + float3 cZoneMin; + float3 cZoneMax; } cbuffer LightPS : register(b3) @@ -158,12 +176,18 @@ cbuffer LightPS : register(b3) float4 cLightColor; float4 cLightPosPS; float3 cLightDirPS; + float4 cNormalOffsetScalePS; float4 cShadowCubeAdjust; float4 cShadowDepthFade; float2 cShadowIntensity; float2 cShadowMapInvSize; float4 cShadowSplits; + float2 cVSMShadowParams; float4x4 cLightMatricesPS[4]; + #ifdef PBR + float cLightRad; + float cLightLength; + #endif } #ifndef CUSTOM_MATERIAL_CBUFFER @@ -173,6 +197,10 @@ cbuffer MaterialPS : register(b4) float3 cMatEmissiveColor; float3 cMatEnvMapColor; float4 cMatSpecColor; + #ifdef PBR + float cRoughness; + float cMetallic; + #endif } #endif diff --git a/res/coreData/Shaders/HLSL/Unlit.hlsl b/res/coreData/Shaders/HLSL/Unlit.hlsl index 5fb83f9..4dec226 100644 --- a/res/coreData/Shaders/HLSL/Unlit.hlsl +++ b/res/coreData/Shaders/HLSL/Unlit.hlsl @@ -15,11 +15,17 @@ void VS(float4 iPos : POSITION, int4 iBlendIndices : BLENDINDICES, #endif #ifdef INSTANCED - float4x3 iModelInstance : TEXCOORD2, + float4x3 iModelInstance : TEXCOORD4, #endif - #ifdef BILLBOARD + #if defined(BILLBOARD) || defined(DIRBILLBOARD) float2 iSize : TEXCOORD1, #endif + #if defined(DIRBILLBOARD) || defined(TRAILBONE) + float3 iNormal : NORMAL, + #endif + #if defined(TRAILFACECAM) || defined(TRAILBONE) + float4 iTangent : TANGENT, + #endif out float2 oTexCoord : TEXCOORD0, out float4 oWorldPos : TEXCOORD2, #ifdef VERTEXCOLOR @@ -103,4 +109,4 @@ void PS(float2 iTexCoord : TEXCOORD0, #else oColor = float4(GetFog(diffColor.rgb, fogFactor), diffColor.a); #endif -} \ No newline at end of file +} diff --git a/res/coreData/Shaders/HLSL/UnlitParticle.hlsl b/res/coreData/Shaders/HLSL/UnlitParticle.hlsl new file mode 100644 index 0000000..a5c75d7 --- /dev/null +++ b/res/coreData/Shaders/HLSL/UnlitParticle.hlsl @@ -0,0 +1,145 @@ +#include "Uniforms.hlsl" +#include "Samplers.hlsl" +#include "Transform.hlsl" +#include "ScreenPos.hlsl" +#include "Fog.hlsl" + +#if defined(COMPILEPS) && defined(SOFTPARTICLES) +#ifndef D3D11 +// D3D9 uniform +uniform float cSoftParticleFadeScale; +#else +// D3D11 constant buffer +cbuffer CustomPS : register(b6) +{ + float cSoftParticleFadeScale; +} +#endif +#endif + +void VS(float4 iPos : POSITION, + #ifndef NOUV + float2 iTexCoord : TEXCOORD0, + #endif + #ifdef VERTEXCOLOR + float4 iColor : COLOR0, + #endif + #ifdef SKINNED + float4 iBlendWeights : BLENDWEIGHT, + int4 iBlendIndices : BLENDINDICES, + #endif + #ifdef INSTANCED + float4x3 iModelInstance : TEXCOORD4, + #endif + #if defined(BILLBOARD) || defined(DIRBILLBOARD) + float2 iSize : TEXCOORD1, + #endif + #if defined(DIRBILLBOARD) || defined(TRAILBONE) + float3 iNormal : NORMAL, + #endif + #if defined(TRAILFACECAM) || defined(TRAILBONE) + float4 iTangent : TANGENT, + #endif + out float2 oTexCoord : TEXCOORD0, + #ifdef SOFTPARTICLES + out float4 oScreenPos : TEXCOORD1, + #endif + out float4 oWorldPos : TEXCOORD2, + #ifdef VERTEXCOLOR + out float4 oColor : COLOR0, + #endif + #if defined(D3D11) && defined(CLIPPLANE) + out float oClip : SV_CLIPDISTANCE0, + #endif + out float4 oPos : OUTPOSITION) +{ + // Define a 0,0 UV coord if not expected from the vertex data + #ifdef NOUV + float2 iTexCoord = float2(0.0, 0.0); + #endif + + float4x3 modelMatrix = iModelMatrix; + float3 worldPos = GetWorldPos(modelMatrix); + oPos = GetClipPos(worldPos); + oTexCoord = GetTexCoord(iTexCoord); + oWorldPos = float4(worldPos, GetDepth(oPos)); + + #if defined(D3D11) && defined(CLIPPLANE) + oClip = dot(oPos, cClipPlane); + #endif + + #ifdef SOFTPARTICLES + oScreenPos = GetScreenPos(oPos); + #endif + + #ifdef VERTEXCOLOR + oColor = iColor; + #endif +} + +void PS(float2 iTexCoord : TEXCOORD0, + #ifdef SOFTPARTICLES + float4 iScreenPos: TEXCOORD1, + #endif + float4 iWorldPos: TEXCOORD2, + #ifdef VERTEXCOLOR + float4 iColor : COLOR0, + #endif + #if defined(D3D11) && defined(CLIPPLANE) + float iClip : SV_CLIPDISTANCE0, + #endif + out float4 oColor : OUTCOLOR0) +{ + // Get material diffuse albedo + #ifdef DIFFMAP + float4 diffColor = cMatDiffColor * Sample2D(DiffMap, iTexCoord); + #ifdef ALPHAMASK + if (diffColor.a < 0.5) + discard; + #endif + #else + float4 diffColor = cMatDiffColor; + #endif + + #ifdef VERTEXCOLOR + diffColor *= iColor; + #endif + + // Get fog factor + #ifdef HEIGHTFOG + float fogFactor = GetHeightFogFactor(iWorldPos.w, iWorldPos.y); + #else + float fogFactor = GetFogFactor(iWorldPos.w); + #endif + + // Soft particle fade + // In expand mode depth test should be off. In that case do manual alpha discard test first to reduce fill rate + #ifdef SOFTPARTICLES + #if defined(EXPAND) && !defined(ADDITIVE) + if (diffColor.a < 0.01) + discard; + #endif + + float particleDepth = iWorldPos.w; + float depth = Sample2DProj(DepthBuffer, iScreenPos).r; + #ifdef HWDEPTH + depth = ReconstructDepth(depth); + #endif + + #ifdef EXPAND + float diffZ = max(particleDepth - depth, 0.0) * (cFarClipPS - cNearClipPS); + float fade = saturate(diffZ * cSoftParticleFadeScale); + #else + float diffZ = (depth - particleDepth) * (cFarClipPS - cNearClipPS); + float fade = saturate(1.0 - diffZ * cSoftParticleFadeScale); + #endif + + #ifndef ADDITIVE + diffColor.a = max(diffColor.a - fade, 0.0); + #else + diffColor.rgb = max(diffColor.rgb - fade, float3(0.0, 0.0, 0.0)); + #endif + #endif + + oColor = float4(GetFog(diffColor.rgb, fogFactor), diffColor.a); +} diff --git a/res/coreData/Shaders/HLSL/Vegetation.hlsl b/res/coreData/Shaders/HLSL/Vegetation.hlsl index e3aaf26..261ee11 100644 --- a/res/coreData/Shaders/HLSL/Vegetation.hlsl +++ b/res/coreData/Shaders/HLSL/Vegetation.hlsl @@ -5,18 +5,41 @@ #include "Lighting.hlsl" #include "Fog.hlsl" +#ifndef D3D11 + +// D3D9 uniforms uniform float cWindHeightFactor; uniform float cWindHeightPivot; uniform float cWindPeriod; uniform float2 cWindWorldSpacing; +#else + +// D3D11 constant buffer +cbuffer CustomVS : register(b6) +{ + float cWindHeightFactor; + float cWindHeightPivot; + float cWindPeriod; + float2 cWindWorldSpacing; +} + +#endif + void VS(float4 iPos : POSITION, - float3 iNormal : NORMAL, - float2 iTexCoord : TEXCOORD0, + #if !defined(BILLBOARD) && !defined(TRAILFACECAM) + float3 iNormal : NORMAL, + #endif + #ifndef NOUV + float2 iTexCoord : TEXCOORD0, + #endif + #ifdef VERTEXCOLOR + float4 iColor : COLOR0, + #endif #if defined(LIGHTMAP) || defined(AO) float2 iTexCoord2 : TEXCOORD1, #endif - #ifdef NORMALMAP + #if (defined(NORMALMAP) || defined(TRAILFACECAM) || defined(TRAILBONE)) && !defined(BILLBOARD) && !defined(DIRBILLBOARD) float4 iTangent : TANGENT, #endif #ifdef SKINNED @@ -24,9 +47,9 @@ void VS(float4 iPos : POSITION, int4 iBlendIndices : BLENDINDICES, #endif #ifdef INSTANCED - float4x3 iModelInstance : TEXCOORD2, + float4x3 iModelInstance : TEXCOORD4, #endif - #ifdef BILLBOARD + #if defined(BILLBOARD) || defined(DIRBILLBOARD) float2 iSize : TEXCOORD1, #endif #ifndef NORMALMAP @@ -57,14 +80,22 @@ void VS(float4 iPos : POSITION, out float2 oTexCoord2 : TEXCOORD7, #endif #endif + #ifdef VERTEXCOLOR + out float4 oColor : COLOR0, + #endif #if defined(D3D11) && defined(CLIPPLANE) out float oClip : SV_CLIPDISTANCE0, #endif out float4 oPos : OUTPOSITION) { + // Define a 0,0 UV coord if not expected from the vertex data + #ifdef NOUV + float2 iTexCoord = float2(0.0, 0.0); + #endif + float4x3 modelMatrix = iModelMatrix; float3 worldPos = GetWorldPos(modelMatrix); - float height = worldPos.y - cModel._m31; + float height = worldPos.y - modelMatrix._m31; float windStrength = max(height - cWindHeightPivot, 0.0) * cWindHeightFactor; float windPeriod = cElapsedTime * cWindPeriod + dot(worldPos.xz, cWindWorldSpacing); @@ -78,12 +109,16 @@ void VS(float4 iPos : POSITION, #if defined(D3D11) && defined(CLIPPLANE) oClip = dot(oPos, cClipPlane); #endif - + + #ifdef VERTEXCOLOR + oColor = iColor; + #endif + #ifdef NORMALMAP - float3 tangent = GetWorldTangent(modelMatrix); - float3 bitangent = cross(tangent, oNormal) * iTangent.w; + float4 tangent = GetWorldTangent(modelMatrix); + float3 bitangent = cross(tangent.xyz, oNormal) * tangent.w; oTexCoord = float4(GetTexCoord(iTexCoord), bitangent.xy); - oTangent = float4(tangent, bitangent.z); + oTangent = float4(tangent.xyz, bitangent.z); #else oTexCoord = GetTexCoord(iTexCoord); #endif @@ -94,7 +129,7 @@ void VS(float4 iPos : POSITION, #ifdef SHADOW // Shadow projection: transform from world space to shadow space - GetShadowPos(projWorldPos, oShadowPos); + GetShadowPos(projWorldPos, oNormal, oShadowPos); #endif #ifdef SPOTLIGHT @@ -103,7 +138,7 @@ void VS(float4 iPos : POSITION, #endif #ifdef POINTLIGHT - oCubeMaskVec = mul(cLightPos.xyz - worldPos, (float3x3)cLightMatrices[0]); + oCubeMaskVec = mul(worldPos - cLightPos.xyz, (float3x3)cLightMatrices[0]); #endif #else // Ambient & per-vertex lighting @@ -120,7 +155,7 @@ void VS(float4 iPos : POSITION, for (int i = 0; i < NUMVERTEXLIGHTS; ++i) oVertexLight += GetVertexLight(i, worldPos, oNormal) * cVertexLights[i * 3].rgb; #endif - + oScreenPos = GetScreenPos(oPos); #ifdef ENVCUBEMAP diff --git a/res/coreData/Shaders/HLSL/VegetationDepth.hlsl b/res/coreData/Shaders/HLSL/VegetationDepth.hlsl index 4754dbf..aa6c05d 100644 --- a/res/coreData/Shaders/HLSL/VegetationDepth.hlsl +++ b/res/coreData/Shaders/HLSL/VegetationDepth.hlsl @@ -2,22 +2,38 @@ #include "Samplers.hlsl" #include "Transform.hlsl" +#ifndef D3D11 + +// D3D9 uniforms uniform float cWindHeightFactor; uniform float cWindHeightPivot; uniform float cWindPeriod; uniform float2 cWindWorldSpacing; +#else + +// D3D11 constant buffer +cbuffer CustomVS : register(b6) +{ + float cWindHeightFactor; + float cWindHeightPivot; + float cWindPeriod; + float2 cWindWorldSpacing; +} + +#endif + void VS(float4 iPos : POSITION, #ifdef SKINNED float4 iBlendWeights : BLENDWEIGHT, int4 iBlendIndices : BLENDINDICES, #endif #ifdef INSTANCED - float4x3 iModelInstance : TEXCOORD2, + float4x3 iModelInstance : TEXCOORD4, #endif float2 iTexCoord : TEXCOORD0, out float3 oTexCoord : TEXCOORD0, - out float4 oPos : POSITION) + out float4 oPos : OUTPOSITION) { float4x3 modelMatrix = iModelMatrix; float3 worldPos = GetWorldPos(modelMatrix); diff --git a/res/coreData/Shaders/HLSL/VegetationShadow.hlsl b/res/coreData/Shaders/HLSL/VegetationShadow.hlsl index 6cf16b0..ddcb780 100644 --- a/res/coreData/Shaders/HLSL/VegetationShadow.hlsl +++ b/res/coreData/Shaders/HLSL/VegetationShadow.hlsl @@ -2,22 +2,38 @@ #include "Samplers.hlsl" #include "Transform.hlsl" +#ifndef D3D11 + +// D3D9 uniforms uniform float cWindHeightFactor; uniform float cWindHeightPivot; uniform float cWindPeriod; uniform float2 cWindWorldSpacing; +#else + +// D3D11 constant buffer +cbuffer CustomVS : register(b6) +{ + float cWindHeightFactor; + float cWindHeightPivot; + float cWindPeriod; + float2 cWindWorldSpacing; +} + +#endif + void VS(float4 iPos : POSITION, #ifdef SKINNED float4 iBlendWeights : BLENDWEIGHT, int4 iBlendIndices : BLENDINDICES, #endif #ifdef INSTANCED - float4x3 iModelInstance : TEXCOORD2, + float4x3 iModelInstance : TEXCOORD4, #endif float2 iTexCoord : TEXCOORD0, out float2 oTexCoord : TEXCOORD0, - out float4 oPos : POSITION) + out float4 oPos : OUTPOSITION) { float4x3 modelMatrix = iModelMatrix; float3 worldPos = GetWorldPos(modelMatrix); diff --git a/res/coreData/Shaders/HLSL/Water.hlsl b/res/coreData/Shaders/HLSL/Water.hlsl index 47d5f03..043ee99 100644 --- a/res/coreData/Shaders/HLSL/Water.hlsl +++ b/res/coreData/Shaders/HLSL/Water.hlsl @@ -36,6 +36,9 @@ cbuffer CustomPS : register(b6) void VS(float4 iPos : POSITION, float3 iNormal: NORMAL, float2 iTexCoord : TEXCOORD0, + #ifdef INSTANCED + float4x3 iModelInstance : TEXCOORD4, + #endif out float4 oScreenPos : TEXCOORD0, out float2 oReflectUV : TEXCOORD1, out float2 oWaterUV : TEXCOORD2, diff --git a/res/coreData/Techniques/DiffAlphaTranslucent.xml b/res/coreData/Techniques/DiffAlphaTranslucent.xml new file mode 100644 index 0000000..1766552 --- /dev/null +++ b/res/coreData/Techniques/DiffAlphaTranslucent.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/res/coreData/Techniques/DiffLitParticleAlphaSoft.xml b/res/coreData/Techniques/DiffLitParticleAlphaSoft.xml new file mode 100644 index 0000000..54c6e63 --- /dev/null +++ b/res/coreData/Techniques/DiffLitParticleAlphaSoft.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/res/coreData/Techniques/DiffLitParticleAlphaSoftExpand.xml b/res/coreData/Techniques/DiffLitParticleAlphaSoftExpand.xml new file mode 100644 index 0000000..c58f1df --- /dev/null +++ b/res/coreData/Techniques/DiffLitParticleAlphaSoftExpand.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/res/coreData/Techniques/DiffNormal.xml b/res/coreData/Techniques/DiffNormal.xml index ee5cb19..ea8e870 100644 --- a/res/coreData/Techniques/DiffNormal.xml +++ b/res/coreData/Techniques/DiffNormal.xml @@ -5,6 +5,6 @@ - - + + diff --git a/res/coreData/Techniques/DiffNormalAO.xml b/res/coreData/Techniques/DiffNormalAO.xml index 3881808..cb5cca6 100644 --- a/res/coreData/Techniques/DiffNormalAO.xml +++ b/res/coreData/Techniques/DiffNormalAO.xml @@ -4,6 +4,6 @@ - - + + diff --git a/res/coreData/Techniques/DiffNormalAOAlpha.xml b/res/coreData/Techniques/DiffNormalAOAlpha.xml index 12b9081..f857426 100644 --- a/res/coreData/Techniques/DiffNormalAOAlpha.xml +++ b/res/coreData/Techniques/DiffNormalAOAlpha.xml @@ -1,5 +1,5 @@ - + diff --git a/res/coreData/Techniques/DiffNormalAlpha.xml b/res/coreData/Techniques/DiffNormalAlpha.xml index 2e44753..041cd7b 100644 --- a/res/coreData/Techniques/DiffNormalAlpha.xml +++ b/res/coreData/Techniques/DiffNormalAlpha.xml @@ -1,5 +1,5 @@ - + diff --git a/res/coreData/Techniques/DiffNormalAlphaTranslucent.xml b/res/coreData/Techniques/DiffNormalAlphaTranslucent.xml new file mode 100644 index 0000000..d0e49a2 --- /dev/null +++ b/res/coreData/Techniques/DiffNormalAlphaTranslucent.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/res/coreData/Techniques/DiffNormalEmissive.xml b/res/coreData/Techniques/DiffNormalEmissive.xml index 5b1dfe5..a573eb3 100644 --- a/res/coreData/Techniques/DiffNormalEmissive.xml +++ b/res/coreData/Techniques/DiffNormalEmissive.xml @@ -4,6 +4,6 @@ - - + + diff --git a/res/coreData/Techniques/DiffNormalEmissiveAlpha.xml b/res/coreData/Techniques/DiffNormalEmissiveAlpha.xml index d3ab5cf..b83121a 100644 --- a/res/coreData/Techniques/DiffNormalEmissiveAlpha.xml +++ b/res/coreData/Techniques/DiffNormalEmissiveAlpha.xml @@ -1,5 +1,5 @@ - + diff --git a/res/coreData/Techniques/DiffNormalEnvCube.xml b/res/coreData/Techniques/DiffNormalEnvCube.xml index b0519fd..391867d 100644 --- a/res/coreData/Techniques/DiffNormalEnvCube.xml +++ b/res/coreData/Techniques/DiffNormalEnvCube.xml @@ -4,6 +4,6 @@ - - + + diff --git a/res/coreData/Techniques/DiffNormalEnvCubeAlpha.xml b/res/coreData/Techniques/DiffNormalEnvCubeAlpha.xml index 1af4184..13b6b71 100644 --- a/res/coreData/Techniques/DiffNormalEnvCubeAlpha.xml +++ b/res/coreData/Techniques/DiffNormalEnvCubeAlpha.xml @@ -1,5 +1,5 @@ - + diff --git a/res/coreData/Techniques/DiffNormalSpec.xml b/res/coreData/Techniques/DiffNormalSpec.xml index cbf1892..a706300 100644 --- a/res/coreData/Techniques/DiffNormalSpec.xml +++ b/res/coreData/Techniques/DiffNormalSpec.xml @@ -5,6 +5,6 @@ - - + + diff --git a/res/coreData/Techniques/DiffNormalSpecAO.xml b/res/coreData/Techniques/DiffNormalSpecAO.xml index 356f795..96ec0d1 100644 --- a/res/coreData/Techniques/DiffNormalSpecAO.xml +++ b/res/coreData/Techniques/DiffNormalSpecAO.xml @@ -4,6 +4,6 @@ - - + + diff --git a/res/coreData/Techniques/DiffNormalSpecAOAlpha.xml b/res/coreData/Techniques/DiffNormalSpecAOAlpha.xml index fad911a..bdab67a 100644 --- a/res/coreData/Techniques/DiffNormalSpecAOAlpha.xml +++ b/res/coreData/Techniques/DiffNormalSpecAOAlpha.xml @@ -1,5 +1,5 @@ - + diff --git a/res/coreData/Techniques/DiffNormalSpecAlpha.xml b/res/coreData/Techniques/DiffNormalSpecAlpha.xml index 990f2d3..2df9c75 100644 --- a/res/coreData/Techniques/DiffNormalSpecAlpha.xml +++ b/res/coreData/Techniques/DiffNormalSpecAlpha.xml @@ -1,5 +1,5 @@ - + diff --git a/res/coreData/Techniques/DiffNormalSpecEmissive.xml b/res/coreData/Techniques/DiffNormalSpecEmissive.xml index 1c959b9..3d9418d 100644 --- a/res/coreData/Techniques/DiffNormalSpecEmissive.xml +++ b/res/coreData/Techniques/DiffNormalSpecEmissive.xml @@ -4,6 +4,6 @@ - - + + diff --git a/res/coreData/Techniques/DiffNormalSpecEmissiveAlpha.xml b/res/coreData/Techniques/DiffNormalSpecEmissiveAlpha.xml index 3e305a5..8b3c451 100644 --- a/res/coreData/Techniques/DiffNormalSpecEmissiveAlpha.xml +++ b/res/coreData/Techniques/DiffNormalSpecEmissiveAlpha.xml @@ -1,5 +1,5 @@ - + diff --git a/res/coreData/Techniques/DiffSkyboxHDRScale.xml b/res/coreData/Techniques/DiffSkyboxHDRScale.xml new file mode 100644 index 0000000..b9b057c --- /dev/null +++ b/res/coreData/Techniques/DiffSkyboxHDRScale.xml @@ -0,0 +1,3 @@ + + + diff --git a/res/coreData/Techniques/DiffSkydome.xml b/res/coreData/Techniques/DiffSkydome.xml new file mode 100644 index 0000000..d7b8814 --- /dev/null +++ b/res/coreData/Techniques/DiffSkydome.xml @@ -0,0 +1,3 @@ + + + diff --git a/res/coreData/Techniques/DiffUnlitParticleAdd.xml b/res/coreData/Techniques/DiffUnlitParticleAdd.xml new file mode 100644 index 0000000..b79c291 --- /dev/null +++ b/res/coreData/Techniques/DiffUnlitParticleAdd.xml @@ -0,0 +1,3 @@ + + + diff --git a/res/coreData/Techniques/DiffUnlitParticleAddSoft.xml b/res/coreData/Techniques/DiffUnlitParticleAddSoft.xml new file mode 100644 index 0000000..f6c85a8 --- /dev/null +++ b/res/coreData/Techniques/DiffUnlitParticleAddSoft.xml @@ -0,0 +1,3 @@ + + + diff --git a/res/coreData/Techniques/DiffUnlitParticleAddSoftExpand.xml b/res/coreData/Techniques/DiffUnlitParticleAddSoftExpand.xml new file mode 100644 index 0000000..43a4f0b --- /dev/null +++ b/res/coreData/Techniques/DiffUnlitParticleAddSoftExpand.xml @@ -0,0 +1,3 @@ + + + diff --git a/res/coreData/Techniques/DiffUnlitParticleAlpha.xml b/res/coreData/Techniques/DiffUnlitParticleAlpha.xml new file mode 100644 index 0000000..2780261 --- /dev/null +++ b/res/coreData/Techniques/DiffUnlitParticleAlpha.xml @@ -0,0 +1,3 @@ + + + diff --git a/res/coreData/Techniques/DiffUnlitParticleAlphaSoft.xml b/res/coreData/Techniques/DiffUnlitParticleAlphaSoft.xml new file mode 100644 index 0000000..21e04f5 --- /dev/null +++ b/res/coreData/Techniques/DiffUnlitParticleAlphaSoft.xml @@ -0,0 +1,3 @@ + + + diff --git a/res/coreData/Techniques/DiffUnlitParticleAlphaSoftExpand.xml b/res/coreData/Techniques/DiffUnlitParticleAlphaSoftExpand.xml new file mode 100644 index 0000000..2d26ee4 --- /dev/null +++ b/res/coreData/Techniques/DiffUnlitParticleAlphaSoftExpand.xml @@ -0,0 +1,3 @@ + + + diff --git a/res/coreData/Techniques/NoTextureNormal.xml b/res/coreData/Techniques/NoTextureNormal.xml index cfbe06d..cb30ced 100644 --- a/res/coreData/Techniques/NoTextureNormal.xml +++ b/res/coreData/Techniques/NoTextureNormal.xml @@ -5,6 +5,6 @@ - - + + diff --git a/res/coreData/Techniques/NoTextureNormalAlpha.xml b/res/coreData/Techniques/NoTextureNormalAlpha.xml index 0f60e27..c3bfddf 100644 --- a/res/coreData/Techniques/NoTextureNormalAlpha.xml +++ b/res/coreData/Techniques/NoTextureNormalAlpha.xml @@ -1,5 +1,5 @@ - + diff --git a/res/coreData/Techniques/PBR/DiffNormalSpecEmissive.xml b/res/coreData/Techniques/PBR/DiffNormalSpecEmissive.xml new file mode 100644 index 0000000..5acbfe6 --- /dev/null +++ b/res/coreData/Techniques/PBR/DiffNormalSpecEmissive.xml @@ -0,0 +1,8 @@ + + + > + + + + + diff --git a/res/coreData/Techniques/PBR/DiffNormalSpecEmissiveAlpha.xml b/res/coreData/Techniques/PBR/DiffNormalSpecEmissiveAlpha.xml new file mode 100644 index 0000000..2ebadcb --- /dev/null +++ b/res/coreData/Techniques/PBR/DiffNormalSpecEmissiveAlpha.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/res/coreData/Techniques/PBR/PBRDiff.xml b/res/coreData/Techniques/PBR/PBRDiff.xml new file mode 100644 index 0000000..7480dc0 --- /dev/null +++ b/res/coreData/Techniques/PBR/PBRDiff.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/res/coreData/Techniques/PBR/PBRDiffAlpha.xml b/res/coreData/Techniques/PBR/PBRDiffAlpha.xml new file mode 100644 index 0000000..b784db4 --- /dev/null +++ b/res/coreData/Techniques/PBR/PBRDiffAlpha.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/res/coreData/Techniques/PBR/PBRDiffNormal.xml b/res/coreData/Techniques/PBR/PBRDiffNormal.xml new file mode 100644 index 0000000..8032d58 --- /dev/null +++ b/res/coreData/Techniques/PBR/PBRDiffNormal.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/res/coreData/Techniques/PBR/PBRDiffNormalAlpha.xml b/res/coreData/Techniques/PBR/PBRDiffNormalAlpha.xml new file mode 100644 index 0000000..5de01d6 --- /dev/null +++ b/res/coreData/Techniques/PBR/PBRDiffNormalAlpha.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/res/coreData/Techniques/PBR/PBRDiffNormalEmissive.xml b/res/coreData/Techniques/PBR/PBRDiffNormalEmissive.xml new file mode 100644 index 0000000..2d57576 --- /dev/null +++ b/res/coreData/Techniques/PBR/PBRDiffNormalEmissive.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/res/coreData/Techniques/PBR/PBRDiffNormalEmissiveAlpha.xml b/res/coreData/Techniques/PBR/PBRDiffNormalEmissiveAlpha.xml new file mode 100644 index 0000000..6a81f74 --- /dev/null +++ b/res/coreData/Techniques/PBR/PBRDiffNormalEmissiveAlpha.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/res/coreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpec.xml b/res/coreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpec.xml new file mode 100644 index 0000000..f04c412 --- /dev/null +++ b/res/coreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpec.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/res/coreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissive.xml b/res/coreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissive.xml new file mode 100644 index 0000000..97503fb --- /dev/null +++ b/res/coreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissive.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/res/coreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissiveAlpha.xml b/res/coreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissiveAlpha.xml new file mode 100644 index 0000000..54070ca --- /dev/null +++ b/res/coreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissiveAlpha.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/res/coreData/Techniques/PBR/PBRMetallicRoughDiffSpec.xml b/res/coreData/Techniques/PBR/PBRMetallicRoughDiffSpec.xml new file mode 100644 index 0000000..1e1daeb --- /dev/null +++ b/res/coreData/Techniques/PBR/PBRMetallicRoughDiffSpec.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/res/coreData/Techniques/PBR/PBRMetallicRoughDiffSpecAlpha.xml b/res/coreData/Techniques/PBR/PBRMetallicRoughDiffSpecAlpha.xml new file mode 100644 index 0000000..fdf99cf --- /dev/null +++ b/res/coreData/Techniques/PBR/PBRMetallicRoughDiffSpecAlpha.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/res/coreData/Techniques/PBR/PBRNoTexture.xml b/res/coreData/Techniques/PBR/PBRNoTexture.xml new file mode 100644 index 0000000..8d99af4 --- /dev/null +++ b/res/coreData/Techniques/PBR/PBRNoTexture.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/res/coreData/Techniques/PBR/PBRNoTextureAlpha.xml b/res/coreData/Techniques/PBR/PBRNoTextureAlpha.xml new file mode 100644 index 0000000..6597424 --- /dev/null +++ b/res/coreData/Techniques/PBR/PBRNoTextureAlpha.xml @@ -0,0 +1,5 @@ + + + + +