summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMauro Persano <mauro.persano@kdab.com>2018-11-01 09:37:56 -0300
committerMauro Persano <mauro.persano@kdab.com>2018-11-05 21:06:45 +0000
commitab5a1549ea25bb2a939b4fe526f5af28bbf2d713 (patch)
tree59d04f60b613ced534db67487d7d439476466ae5
parent7b401dcd3345d42108eb162ea354f64152c9d0a4 (diff)
downloadqt3d-ab5a1549ea25bb2a939b4fe526f5af28bbf2d713.tar.gz
Make floating point precision explicit in ES3 MetalRough shader
Change-Id: Ibd59dd30e31ded3cbf169fa583d537a7d67fee96 Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r--src/extras/shaders/es3/metalrough.inc.frag186
1 files changed, 94 insertions, 92 deletions
diff --git a/src/extras/shaders/es3/metalrough.inc.frag b/src/extras/shaders/es3/metalrough.inc.frag
index 85f392f4c..f145e90f8 100644
--- a/src/extras/shaders/es3/metalrough.inc.frag
+++ b/src/extras/shaders/es3/metalrough.inc.frag
@@ -48,46 +48,48 @@
**
****************************************************************************/
-precision highp float;
+#ifndef FP
+#define FP highp
+#endif
// Exposure correction
-uniform float exposure;
+uniform FP float exposure;
// Gamma correction
-const float gamma = 2.2;
+const FP float gamma = 2.2;
#pragma include light.inc.frag
-int mipLevelCount(const in samplerCube cube)
+int mipLevelCount(const in FP samplerCube cube)
{
int baseSize = textureSize(cube, 0).x;
int nMips = int(log2(float(baseSize > 0 ? baseSize : 1))) + 1;
return nMips;
}
-float remapRoughness(const in float roughness)
+float remapRoughness(const in FP float roughness)
{
// As per page 14 of
// http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
// we remap the roughness to give a more perceptually linear response
// of "bluriness" as a function of the roughness specified by the user.
// r = roughness^2
- const float maxSpecPower = 999999.0;
- const float minRoughness = sqrt(2.0 / (maxSpecPower + 2.0));
+ const FP float maxSpecPower = 999999.0;
+ const FP float minRoughness = sqrt(2.0 / (maxSpecPower + 2.0));
return max(roughness * roughness, minRoughness);
}
-float alphaToMipLevel(float alpha)
+FP float alphaToMipLevel(FP float alpha)
{
- float specPower = 2.0 / (alpha * alpha) - 2.0;
+ FP float specPower = 2.0 / (alpha * alpha) - 2.0;
// We use the mip level calculation from Lys' default power drop, which in
// turn is a slight modification of that used in Marmoset Toolbag. See
// https://docs.knaldtech.com/doku.php?id=specular_lys for details.
// For now we assume a max specular power of 999999 which gives
// maxGlossiness = 1.
- const float k0 = 0.00098;
- const float k1 = 0.9921;
- float glossiness = (pow(2.0, -10.0 / sqrt(specPower)) - k0) / k1;
+ const FP float k0 = 0.00098;
+ const FP float k1 = 0.9921;
+ FP float glossiness = (pow(2.0, -10.0 / sqrt(specPower)) - k0) / k1;
// TODO: Optimize by doing this on CPU and set as
// uniform int envLight.specularMipLevels say (if present in shader).
@@ -96,35 +98,35 @@ float alphaToMipLevel(float alpha)
// Offset of smallest miplevel we should use (corresponds to specular
// power of 1). I.e. in the 32x32 sized mip.
- const float mipOffset = 5.0;
+ const FP float mipOffset = 5.0;
// The final factor is really 1 - g / g_max but as mentioned above g_max
// is 1 by definition here so we can avoid the division. If we make the
// max specular power for the spec map configurable, this will need to
// be handled properly.
- float mipLevel = (float(mipLevels) - 1.0 - mipOffset) * (1.0 - glossiness);
+ FP float mipLevel = (float(mipLevels) - 1.0 - mipOffset) * (1.0 - glossiness);
return mipLevel;
}
-float normalDistribution(const in vec3 n, const in vec3 h, const in float alpha)
+FP float normalDistribution(const in FP vec3 n, const in FP vec3 h, const in FP float alpha)
{
// Blinn-Phong approximation - see
// http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html
- float specPower = 2.0 / (alpha * alpha) - 2.0;
+ FP float specPower = 2.0 / (alpha * alpha) - 2.0;
return (specPower + 2.0) / (2.0 * 3.14159) * pow(max(dot(n, h), 0.0), specPower);
}
-vec3 fresnelFactor(const in vec3 color, const in float cosineFactor)
+FP vec3 fresnelFactor(const in FP vec3 color, const in FP float cosineFactor)
{
// Calculate the Fresnel effect value
- vec3 f = color;
- vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0);
+ FP vec3 f = color;
+ FP vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0);
return clamp(F, f, vec3(1.0));
}
-float geometricModel(const in float lDotN,
- const in float vDotN,
- const in vec3 h)
+FP float geometricModel(const in FP float lDotN,
+ const in FP float vDotN,
+ const in FP vec3 h)
{
// Implicit geometric model (equal to denominator in specular model).
// This currently assumes that there is no attenuation by geometric shadowing or
@@ -132,46 +134,46 @@ float geometricModel(const in float lDotN,
return lDotN * vDotN;
}
-vec3 specularModel(const in vec3 F0,
- const in float sDotH,
- const in float sDotN,
- const in float vDotN,
- const in vec3 n,
- const in vec3 h)
+FP vec3 specularModel(const in FP vec3 F0,
+ const in FP float sDotH,
+ const in FP float sDotN,
+ const in FP float vDotN,
+ const in FP vec3 n,
+ const in FP vec3 h)
{
// Clamp sDotN and vDotN to small positive value to prevent the
// denominator in the reflection equation going to infinity. Balance this
// by using the clamped values in the geometric factor function to
// avoid ugly seams in the specular lighting.
- float sDotNPrime = max(sDotN, 0.001);
- float vDotNPrime = max(vDotN, 0.001);
+ FP float sDotNPrime = max(sDotN, 0.001);
+ FP float vDotNPrime = max(vDotN, 0.001);
- vec3 F = fresnelFactor(F0, sDotH);
- float G = geometricModel(sDotNPrime, vDotNPrime, h);
+ FP vec3 F = fresnelFactor(F0, sDotH);
+ FP float G = geometricModel(sDotNPrime, vDotNPrime, h);
- vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime);
+ FP vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime);
return clamp(cSpec, vec3(0.0), vec3(1.0));
}
-vec3 pbrModel(const in int lightIndex,
- const in vec3 wPosition,
- const in vec3 wNormal,
- const in vec3 wView,
- const in vec3 baseColor,
- const in float metalness,
- const in float alpha,
- const in float ambientOcclusion)
+FP vec3 pbrModel(const in int lightIndex,
+ const in FP vec3 wPosition,
+ const in FP vec3 wNormal,
+ const in FP vec3 wView,
+ const in FP vec3 baseColor,
+ const in FP float metalness,
+ const in FP float alpha,
+ const in FP float ambientOcclusion)
{
// Calculate some useful quantities
- vec3 n = wNormal;
- vec3 s = vec3(0.0);
- vec3 v = wView;
- vec3 h = vec3(0.0);
+ FP vec3 n = wNormal;
+ FP vec3 s = vec3(0.0);
+ FP vec3 v = wView;
+ FP vec3 h = vec3(0.0);
- float vDotN = dot(v, n);
- float sDotN = 0.0;
- float sDotH = 0.0;
- float att = 1.0;
+ FP float vDotN = dot(v, n);
+ FP float sDotN = 0.0;
+ FP float sDotH = 0.0;
+ FP float att = 1.0;
if (lights[lightIndex].type != TYPE_DIRECTIONAL) {
// Point and Spot lights
@@ -208,22 +210,22 @@ vec3 pbrModel(const in int lightIndex,
sDotH = dot(s, h);
// Calculate diffuse component
- vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color;
- vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159;
+ FP vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color;
+ FP vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159;
// Calculate specular component
- vec3 dielectricColor = vec3(0.04);
- vec3 F0 = mix(dielectricColor, baseColor, metalness);
- vec3 specularFactor = vec3(0.0);
+ FP vec3 dielectricColor = vec3(0.04);
+ FP vec3 F0 = mix(dielectricColor, baseColor, metalness);
+ FP vec3 specularFactor = vec3(0.0);
if (sDotN > 0.0) {
specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h);
specularFactor *= normalDistribution(n, h, alpha);
}
- vec3 specularColor = lights[lightIndex].color;
- vec3 specular = specularColor * specularFactor;
+ FP vec3 specularColor = lights[lightIndex].color;
+ FP vec3 specular = specularColor * specularFactor;
// Blend between diffuse and specular to conserver energy
- vec3 color = att * lights[lightIndex].intensity * (specular + diffuse * (vec3(1.0) - specular));
+ FP vec3 color = att * lights[lightIndex].intensity * (specular + diffuse * (vec3(1.0) - specular));
// Reduce by ambient occlusion amount
color *= ambientOcclusion;
@@ -231,36 +233,36 @@ vec3 pbrModel(const in int lightIndex,
return color;
}
-vec3 pbrIblModel(const in vec3 wNormal,
- const in vec3 wView,
- const in vec3 baseColor,
- const in float metalness,
- const in float alpha,
- const in float ambientOcclusion)
+FP vec3 pbrIblModel(const in FP vec3 wNormal,
+ const in FP vec3 wView,
+ const in FP vec3 baseColor,
+ const in FP float metalness,
+ const in FP float alpha,
+ const in FP float ambientOcclusion)
{
// Calculate reflection direction of view vector about surface normal
// vector in world space. This is used in the fragment shader to sample
// from the environment textures for a light source. This is equivalent
// to the l vector for punctual light sources. Armed with this, calculate
// the usual factors needed
- vec3 n = wNormal;
- vec3 l = reflect(-wView, n);
- vec3 v = wView;
- vec3 h = normalize(l + v);
- float vDotN = dot(v, n);
- float lDotN = dot(l, n);
- float lDotH = dot(l, h);
+ FP vec3 n = wNormal;
+ FP vec3 l = reflect(-wView, n);
+ FP vec3 v = wView;
+ FP vec3 h = normalize(l + v);
+ FP float vDotN = dot(v, n);
+ FP float lDotN = dot(l, n);
+ FP float lDotH = dot(l, h);
// Calculate diffuse component
- vec3 diffuseColor = (1.0 - metalness) * baseColor;
- vec3 diffuse = diffuseColor * texture(envLight.irradiance, l).rgb;
+ FP vec3 diffuseColor = (1.0 - metalness) * baseColor;
+ FP vec3 diffuse = diffuseColor * texture(envLight.irradiance, l).rgb;
// Calculate specular component
- vec3 dielectricColor = vec3(0.04);
- vec3 F0 = mix(dielectricColor, baseColor, metalness);
- vec3 specularFactor = specularModel(F0, lDotH, lDotN, vDotN, n, h);
+ FP vec3 dielectricColor = vec3(0.04);
+ FP vec3 F0 = mix(dielectricColor, baseColor, metalness);
+ FP vec3 specularFactor = specularModel(F0, lDotH, lDotN, vDotN, n, h);
- float lod = alphaToMipLevel(alpha);
+ FP float lod = alphaToMipLevel(alpha);
//#define DEBUG_SPECULAR_LODS
#ifdef DEBUG_SPECULAR_LODS
if (lod > 7.0)
@@ -280,11 +282,11 @@ vec3 pbrIblModel(const in vec3 wNormal,
else if (lod > 0.0)
return vec3(1.0, 0.0, 1.0);
#endif
- vec3 specularSkyColor = textureLod(envLight.specular, l, lod).rgb;
- vec3 specular = specularSkyColor * specularFactor;
+ FP vec3 specularSkyColor = textureLod(envLight.specular, l, lod).rgb;
+ FP vec3 specular = specularSkyColor * specularFactor;
// Blend between diffuse and specular to conserve energy
- vec3 color = specular + diffuse * (vec3(1.0) - specularFactor);
+ FP vec3 color = specular + diffuse * (vec3(1.0) - specularFactor);
// Reduce by ambient occlusion amount
color *= ambientOcclusion;
@@ -292,28 +294,28 @@ vec3 pbrIblModel(const in vec3 wNormal,
return color;
}
-vec3 toneMap(const in vec3 c)
+FP vec3 toneMap(const in FP vec3 c)
{
return c / (c + vec3(1.0));
}
-vec3 gammaCorrect(const in vec3 color)
+FP vec3 gammaCorrect(const in FP vec3 color)
{
return pow(color, vec3(1.0 / gamma));
}
-vec4 metalRoughFunction(const in vec4 baseColor,
- const in float metalness,
- const in float roughness,
- const in float ambientOcclusion,
- const in vec3 worldPosition,
- const in vec3 worldView,
- const in vec3 worldNormal)
+FP vec4 metalRoughFunction(const in FP vec4 baseColor,
+ const in FP float metalness,
+ const in FP float roughness,
+ const in FP float ambientOcclusion,
+ const in FP vec3 worldPosition,
+ const in FP vec3 worldView,
+ const in FP vec3 worldNormal)
{
- vec3 cLinear = vec3(0.0);
+ FP vec3 cLinear = vec3(0.0);
// Remap roughness for a perceptually more linear correspondence
- float alpha = remapRoughness(roughness);
+ FP float alpha = remapRoughness(roughness);
for (int i = 0; i < envLightCount; ++i) {
cLinear += pbrIblModel(worldNormal,
@@ -339,10 +341,10 @@ vec4 metalRoughFunction(const in vec4 baseColor,
cLinear *= pow(2.0, exposure);
// Apply simple (Reinhard) tonemap transform to get into LDR range [0, 1]
- vec3 cToneMapped = toneMap(cLinear);
+ FP vec3 cToneMapped = toneMap(cLinear);
// Apply gamma correction prior to display
- vec3 cGamma = gammaCorrect(cToneMapped);
+ FP vec3 cGamma = gammaCorrect(cToneMapped);
return vec4(cGamma, 1.0);
}