-#version 300 es
// Original Code
// https://github.com/KhronosGroup/glTF-Sample-Viewer/blob/glTF-WebGL-PBR/shaders/pbr-frag.glsl
#ifdef THREE_TEX
#ifdef BASECOLOR_TEX
uniform sampler2D sAlbedoAlpha;
+uniform float uBaseColorTextureTransformAvailable;
+uniform mat3 uBaseColorTextureTransform;
#endif // BASECOLOR_TEX
#ifdef METALLIC_ROUGHNESS_TEX
uniform sampler2D sMetalRoughness;
+uniform float uMetalRoughnessTextureTransformAvailable;
+uniform mat3 uMetalRoughnessTextureTransform;
#endif // METALLIC_ROUGHNESS_TEX
#ifdef NORMAL_TEX
uniform sampler2D sNormal;
+uniform float uNormalTextureTransformAvailable;
+uniform mat3 uNormalTextureTransform;
uniform float uNormalScale;
#endif // NORMAL_TEX
#else // THREE_TEX
uniform sampler2D sAlbedoMetal;
+uniform float uBaseColorTextureTransformAvailable;
+uniform mat3 uBaseColorTextureTransform;
uniform sampler2D sNormalRoughness;
+uniform float uNormalRoughnessTextureTransformAvailable;
+uniform mat3 uNormalRoughnessTextureTransform;
#endif
+
+
#ifdef OCCLUSION
uniform sampler2D sOcclusion;
+uniform float uOcclusionTextureTransformAvailable;
+uniform mat3 uOcclusionTextureTransform;
uniform float uOcclusionStrength;
#endif
#ifdef EMISSIVE_TEXTURE
uniform sampler2D sEmissive;
+uniform float uEmissiveTextureTransformAvailable;
+uniform mat3 uEmissiveTextureTransform;
#endif
uniform vec3 uEmissiveFactor;
uniform mediump vec3 uLightDirection[MAX_LIGHTS];
uniform mediump vec3 uLightColor[MAX_LIGHTS];
+// For Shadow Map
+uniform lowp int uIsShadowEnabled;
+uniform sampler2D sShadowMap;
+#ifdef GLSL_VERSION_1_0
+uniform int uShadowMapWidth;
+uniform int uShadowMapHeight;
+#endif
+INPUT highp vec3 positionFromLightView;
+
//// For IBL
uniform sampler2D sbrdfLUT;
uniform samplerCube sDiffuseEnvSampler;
uniform lowp float uAlphaThreshold;
// TODO: Multiple texture coordinate will be supported.
-in mediump vec2 vUV;
-in lowp mat3 vTBN;
-in lowp vec4 vColor;
-in highp vec3 vPositionToCamera;
-
-out vec4 FragColor;
+INPUT mediump vec2 vUV;
+INPUT lowp mat3 vTBN;
+INPUT lowp vec4 vColor;
+INPUT highp vec3 vPositionToCamera;
const float c_MinRoughness = 0.04;
const float M_PI = 3.141592653589793;
+// These properties can be used for circular sampling for PCF
+
+// Percentage Closer Filtering to mitigate the banding artifacts.
+const int kPcfSampleCount = 9;
+
+const float kPi = 3.141592653589;
+const float kInvSampleCount = 1.0 / float(kPcfSampleCount);
+const float kPcfTheta = 2.0 * kPi * kInvSampleCount;
+const float kSinPcfTheta = sin(kPcfTheta);
+const float kCosPcfTheta = cos(kPcfTheta);
+
+uniform lowp int uEnableShadowSoftFiltering;
+uniform mediump float uShadowIntensity;
+uniform highp float uShadowBias;
+
vec3 linear(vec3 color)
{
return pow(color, vec3(2.2));
}
+vec2 computeTextureTransform(vec2 texCoord, mat3 textureTransform)
+{
+ return vec2(textureTransform * vec3(texCoord, 1.0));
+}
+
void main()
{
// Metallic and Roughness material properties are packed together
lowp float metallic = uMetallicFactor;
lowp float perceptualRoughness = uRoughnessFactor;
// If there isn't normal texture, use surface normal
- mediump vec3 n = normalize(vTBN[2].xyz);
+ highp vec3 n = normalize(vTBN[2].xyz);
#ifdef THREE_TEX
// The albedo may be defined from a base texture or a flat color
#ifdef BASECOLOR_TEX
- lowp vec4 baseColor = texture(sAlbedoAlpha, vUV);
+ mediump vec2 baseColorTexCoords = mix(vUV, computeTextureTransform(vUV, uBaseColorTextureTransform), uBaseColorTextureTransformAvailable);
+ lowp vec4 baseColor = TEXTURE(sAlbedoAlpha, baseColorTexCoords);
baseColor = vColor * vec4(linear(baseColor.rgb), baseColor.w) * uColorFactor;
#else // BASECOLOR_TEX
lowp vec4 baseColor = vColor * uColorFactor;
#endif // BASECOLOR_TEX
#ifdef METALLIC_ROUGHNESS_TEX
- lowp vec4 metrou = texture(sMetalRoughness, vUV);
+ mediump vec2 metalRoughnessTexCoords = mix(vUV, computeTextureTransform(vUV, uMetalRoughnessTextureTransform), uMetalRoughnessTextureTransformAvailable);
+ lowp vec4 metrou = TEXTURE(sMetalRoughness, metalRoughnessTexCoords);
metallic = metrou.METALLIC * metallic;
perceptualRoughness = metrou.ROUGHNESS * perceptualRoughness;
#endif // METALLIC_ROUGHNESS_TEX
#ifdef NORMAL_TEX
- n = texture(sNormal, vUV).rgb;
+ mediump vec2 normalTexCoords = mix(vUV, computeTextureTransform(vUV, uNormalTextureTransform), uNormalTextureTransformAvailable);
+ n = TEXTURE(sNormal, normalTexCoords).rgb;
n = normalize(vTBN * ((2.0 * n - 1.0) * vec3(uNormalScale, uNormalScale, 1.0)));
#endif // NORMAL_TEX
#else // THREE_TEX
- vec4 albedoMetal = texture(sAlbedoMetal, vUV);
+ mediump vec2 baseColorTexCoords = mix(vUV, computeTextureTransform(vUV, uBaseColorTextureTransform), uBaseColorTextureTransformAvailable);
+ vec4 albedoMetal = TEXTURE(sAlbedoMetal, baseColorTexCoords);
lowp vec4 baseColor = vec4(linear(albedoMetal.rgb), 1.0) * vColor * uColorFactor;
metallic = albedoMetal.METALLIC * metallic;
- vec4 normalRoughness = texture(sNormalRoughness, vUV);
+ mediump vec2 normalRoughnessTexCoords = mix(vUV, computeTextureTransform(vUV, uNormalRoughnessTextureTransform), uNormalRoughnessTextureTransformAvailable);
+ vec4 normalRoughness = TEXTURE(sNormalRoughness, normalRoughnessTexCoords);
perceptualRoughness = normalRoughness.ROUGHNESS * perceptualRoughness;
n = normalRoughness.rgb;
float specularWeight = 1.0;
vec4 materialSpecularTexture = vec4(1.0);
#ifdef MATERIAL_SPECULAR_TEXTURE
- materialSpecularTexture.a = texture(sSpecular, vUV).a;
+ materialSpecularTexture.a = TEXTURE(sSpecular, vUV).a;
#endif
#ifdef MATERIAL_SPECULAR_COLOR_TEXTURE
- materialSpecularTexture.rgb = texture(sSpecularColor, vUV).rgb;
+ materialSpecularTexture.rgb = TEXTURE(sSpecularColor, vUV).rgb;
#endif
specularWeight = uSpecularFactor * materialSpecularTexture.a;
f0 = min(f0 * uSpecularColorFactor * materialSpecularTexture.rgb, vec3(1.0));
mediump vec3 v = normalize(vPositionToCamera); // Vector from surface point to camera
mediump float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
mediump vec3 reflection = -normalize(reflect(v, n));
- lowp vec3 brdf = texture(sbrdfLUT, vec2(NdotV, 1.0 - perceptualRoughness)).rgb;
+ lowp vec3 brdf = TEXTURE(sbrdfLUT, vec2(NdotV, 1.0 - perceptualRoughness)).rgb;
vec3 Fr = max(vec3(1.0 - perceptualRoughness), f0) - f0;
vec3 k_S = f0 + Fr * pow(1.0 - NdotV, 5.0);
vec3 FssEss = specularWeight * (k_S * brdf.x + brdf.y);
// Specular Light
// uMaxLOD that means mipmap level of specular texture is used for bluring of reflection of specular following roughness.
float lod = perceptualRoughness * (uMaxLOD - 1.0);
+#ifdef GLSL_VERSION_1_0
+ // glsl 1.0 doesn't support textureLod. Let we just use textureCube instead.
+ lowp vec3 specularLight = linear(textureCube(sSpecularEnvSampler, reflection * uYDirection).rgb);
+#else
lowp vec3 specularLight = linear(textureLod(sSpecularEnvSampler, reflection * uYDirection, lod).rgb);
+#endif
lowp vec3 specular = specularLight * FssEss;
// Diffuse Light
lowp vec3 diffuseColor = mix(baseColor.rgb, vec3(0), metallic);
- lowp vec3 irradiance = linear(texture(sDiffuseEnvSampler, n * uYDirection).rgb);
+#ifdef GLSL_VERSION_1_0
+ lowp vec3 irradiance = linear(textureCube(sDiffuseEnvSampler, n * uYDirection).rgb);
+#else
+ lowp vec3 irradiance = linear(TEXTURE(sDiffuseEnvSampler, n * uYDirection).rgb);
+#endif
float Ems = (1.0 - (brdf.x + brdf.y));
vec3 F_avg = specularWeight * (f0 + (1.0 - f0) / 21.0);
vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems);
for(int i = 0; i < uLightCount; ++i)
{
- mediump vec3 l = normalize(-uLightDirection[i]); // Vector from surface point to light
- mediump vec3 h = normalize(l+v); // Half vector between both l and v
+ highp vec3 l = normalize(-uLightDirection[i]); // Vector from surface point to light
+ mediump vec3 h = normalize(l+v); // Half vector between both l and v
mediump float VdotH = dot(v, h);
lowp vec3 specularReflection = f0 + (reflectance90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0);
lowp float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
lowp float geometricOcclusion = attenuationL * attenuationV;
- mediump float NdotH = dot(n, h);
- lowp float f = (NdotH * roughnessSq - NdotH) * NdotH + 1.0;
+ highp float NdotH = dot(n, h);
+ highp float f = (NdotH * roughnessSq - NdotH) * NdotH + 1.0;
lowp float microfacetDistribution = roughnessSq / (M_PI * f * f);;
// Calculation of analytical lighting contribution
}
}
+ if(float(uIsShadowEnabled) * uShadowIntensity > 0.0)
+ {
+ mediump float exposureFactor = 0.0;
+ if(uEnableShadowSoftFiltering > 0)
+ {
+#ifdef GLSL_VERSION_1_0
+ ivec2 texSize = ivec2(uShadowMapWidth, uShadowMapHeight);
+#else
+ ivec2 texSize = textureSize(sShadowMap, 0);
+#endif
+ mediump vec2 texelSize = vec2(1.0) / vec2(texSize.x, texSize.y);
+ mediump vec2 pcfSample = vec2(1.0, 0.0);
+ for (int i = 0; i < kPcfSampleCount; ++i)
+ {
+ pcfSample = vec2(kCosPcfTheta * pcfSample.x - kSinPcfTheta * pcfSample.y,
+ kSinPcfTheta * pcfSample.x + kCosPcfTheta * pcfSample.y);
+ lowp float depthValue = TEXTURE(sShadowMap, positionFromLightView.xy + pcfSample * texelSize).r;
+ exposureFactor += (depthValue < positionFromLightView.z - uShadowBias) ? 0.0 : 1.0;
+ }
+ exposureFactor *= kInvSampleCount;
+ }
+ else
+ {
+ mediump float depthValue = TEXTURE(sShadowMap, positionFromLightView.xy).r;
+ exposureFactor = (depthValue < positionFromLightView.z - uShadowBias) ? 0.0 : 1.0;
+ }
+ color *= (1.0 - (1.0 - exposureFactor) * uShadowIntensity);
+ }
+
#ifdef OCCLUSION
- lowp float ao = texture(sOcclusion, vUV).r;
+ mediump vec2 occlusionTexCoords = mix(vUV, computeTextureTransform(vUV, uOcclusionTextureTransform), uOcclusionTextureTransformAvailable);
+ lowp float ao = TEXTURE(sOcclusion, occlusionTexCoords).r;
color = mix(color, color * ao, uOcclusionStrength);
#endif // OCCLUSION
#ifdef EMISSIVE_TEXTURE
- lowp vec3 emissive = linear(texture(sEmissive, vUV).rgb) * uEmissiveFactor;
+ mediump vec2 emissiveTexCoords = mix(vUV, computeTextureTransform(vUV, uEmissiveTextureTransform), uEmissiveTextureTransformAvailable);
+ lowp vec3 emissive = linear(TEXTURE(sEmissive, emissiveTexCoords).rgb) * uEmissiveFactor;
#else
lowp vec3 emissive = uEmissiveFactor;
#endif // EMISSIVE_TEXTURE
color += emissive;
- FragColor = vec4(pow(color, vec3(1.0 / 2.2)), baseColor.a) * uColor;
+ OUT_COLOR = vec4(pow(color, vec3(1.0 / 2.2)), baseColor.a) * uColor;
}