Skip to content

Commit

Permalink
Merge pull request #143 from KhronosGroup/feature/#102_shader-cleanup
Browse files Browse the repository at this point in the history
#102 shader cleanup
  • Loading branch information
Benjamin Schmithüsen authored Dec 17, 2018
2 parents c53b74f + 6d4be63 commit 13ab5ab
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 141 deletions.
2 changes: 2 additions & 0 deletions src/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import metallicRoughnessShader from './shaders/metallic-roughness.frag';
import primitiveShader from './shaders/primitive.vert';
import texturesShader from './shaders/textures.glsl';
import tonemappingShader from'./shaders/tonemapping.glsl';
import shaderFunctions from './shaders/functions.glsl';

class gltfRenderer
{
Expand All @@ -29,6 +30,7 @@ class gltfRenderer
shaderSources.set("metallic-roughness.frag", metallicRoughnessShader);
shaderSources.set("tonemapping.glsl", tonemappingShader);
shaderSources.set("textures.glsl", texturesShader);
shaderSources.set("functions.glsl", shaderFunctions);

this.shaderCache = new ShaderCache(shaderSources);

Expand Down
132 changes: 132 additions & 0 deletions src/shaders/functions.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// textures.glsl needs to be included

const float M_PI = 3.141592653589793;
const float c_MinReflectance = 0.04;

varying vec3 v_Position;

#ifdef HAS_NORMALS
#ifdef HAS_TANGENTS
varying mat3 v_TBN;
#else
varying vec3 v_Normal;
#endif
#endif

#ifdef HAS_VERTEX_COLOR_VEC3
varying vec3 v_Color;
#endif
#ifdef HAS_VERTEX_COLOR_VEC4
varying vec4 v_Color;
#endif

struct AngularInfo
{
float NdotL; // cos angle between normal and light direction
float NdotV; // cos angle between normal and view direction
float NdotH; // cos angle between normal and half vector
float LdotH; // cos angle between light direction and half vector

float VdotH; // cos angle between view direction and half vector

vec3 padding;
};

vec4 getVertexColor()
{
vec4 color = vec4(1.0, 1.0, 1.0, 1.0);

#ifdef HAS_VERTEX_COLOR_VEC3
color.rgb = v_Color;
#endif
#ifdef HAS_VERTEX_COLOR_VEC4
color = v_Color;
#endif

return color;
}

// Find the normal for this fragment, pulling either from a predefined normal map
// or from the interpolated mesh normal and tangent attributes.
vec3 getNormal()
{
vec2 UV = getNormalUV();

// Retrieve the tangent space matrix
#ifndef HAS_TANGENTS
vec3 pos_dx = dFdx(v_Position);
vec3 pos_dy = dFdy(v_Position);
vec3 tex_dx = dFdx(vec3(UV, 0.0));
vec3 tex_dy = dFdy(vec3(UV, 0.0));
vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);

#ifdef HAS_NORMALS
vec3 ng = normalize(v_Normal);
#else
vec3 ng = cross(pos_dx, pos_dy);
#endif

t = normalize(t - ng * dot(ng, t));
vec3 b = normalize(cross(ng, t));
mat3 tbn = mat3(t, b, ng);
#else // HAS_TANGENTS
mat3 tbn = v_TBN;
#endif

#ifdef HAS_NORMAL_MAP
vec3 n = texture2D(u_NormalSampler, UV).rgb;
n = normalize(tbn * ((2.0 * n - 1.0) * vec3(u_NormalScale, u_NormalScale, 1.0)));
#else
// The tbn matrix is linearly interpolated, so we need to re-normalize
vec3 n = normalize(tbn[2].xyz);
#endif

return n;
}

float getPerceivedBrightness(vec3 vector)
{
return sqrt(0.299 * vector.r * vector.r + 0.587 * vector.g * vector.g + 0.114 * vector.b * vector.b);
}

// https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows/js/three.pbrUtilities.js#L34
float solveMetallic(vec3 diffuse, vec3 specular, float oneMinusSpecularStrength) {
float specularBrightness = getPerceivedBrightness(specular);

if (specularBrightness < c_MinReflectance) {
return 0.0;
}

float diffuseBrightness = getPerceivedBrightness(diffuse);

float a = c_MinReflectance;
float b = diffuseBrightness * oneMinusSpecularStrength / (1.0 - c_MinReflectance) + specularBrightness - 2.0 * c_MinReflectance;
float c = c_MinReflectance - specularBrightness;
float D = b * b - 4.0 * a * c;

return clamp((-b + sqrt(D)) / (2.0 * a), 0.0, 1.0);
}

AngularInfo getAngularInfo(vec3 pointToLight, vec3 normal, vec3 view)
{
// Standard one-letter names
vec3 n = normalize(normal); // Outward direction of surface point
vec3 v = normalize(view); // Direction from surface point to view
vec3 l = normalize(pointToLight); // Direction from surface point to light
vec3 h = normalize(l + v); // Direction of the vector between l and v

float NdotL = clamp(dot(n, l), 0.0, 1.0);
float NdotV = clamp(dot(n, v), 0.0, 1.0);
float NdotH = clamp(dot(n, h), 0.0, 1.0);
float LdotH = clamp(dot(l, h), 0.0, 1.0);
float VdotH = clamp(dot(v, h), 0.0, 1.0);

return AngularInfo(
NdotL,
NdotV,
NdotH,
LdotH,
VdotH,
vec3(0, 0, 0)
);
}
142 changes: 1 addition & 141 deletions src/shaders/metallic-roughness.frag
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ precision highp float;

#include <tonemapping.glsl>
#include <textures.glsl>
#include <functions.glsl>

// KHR_lights_punctual extension.
// see https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
Expand Down Expand Up @@ -73,45 +74,6 @@ uniform vec3 u_Camera;
// debugging flags used for shader output of intermediate PBR variables
uniform vec4 u_ScaleIBLAmbient;

//
//

varying vec3 v_Position;

#ifdef HAS_NORMALS
#ifdef HAS_TANGENTS
varying mat3 v_TBN;
#else
varying vec3 v_Normal;
#endif
#endif

#ifdef HAS_VERTEX_COLOR_VEC3
varying vec3 v_Color;
#endif
#ifdef HAS_VERTEX_COLOR_VEC4
varying vec4 v_Color;
#endif

//
//

// Encapsulate the various inputs used by the various functions in the shading equation
// We store values in this struct to simplify the integration of alternative implementations
// of the shading terms, outlined in the Readme.md Appendix.

struct AngularInfo
{
float NdotL; // cos angle between normal and light direction
float NdotV; // cos angle between normal and view direction
float NdotH; // cos angle between normal and half vector
float LdotH; // cos angle between light direction and half vector

float VdotH; // cos angle between view direction and half vector

vec3 padding;
};

struct MaterialInfo
{
float perceptualRoughness; // roughness value, as authored by the model creator (input to shader)
Expand All @@ -128,61 +90,6 @@ struct MaterialInfo
float padding;
};

const float M_PI = 3.141592653589793;
const float c_MinReflectance = 0.04;

vec4 getVertexColor()
{
vec4 color = vec4(1.0, 1.0, 1.0, 1.0);

#ifdef HAS_VERTEX_COLOR_VEC3
color.rgb = v_Color;
#endif
#ifdef HAS_VERTEX_COLOR_VEC4
color = v_Color;
#endif

return color;
}

// Find the normal for this fragment, pulling either from a predefined normal map
// or from the interpolated mesh normal and tangent attributes.
vec3 getNormal()
{
vec2 UV = getNormalUV();

// Retrieve the tangent space matrix
#ifndef HAS_TANGENTS
vec3 pos_dx = dFdx(v_Position);
vec3 pos_dy = dFdy(v_Position);
vec3 tex_dx = dFdx(vec3(UV, 0.0));
vec3 tex_dy = dFdy(vec3(UV, 0.0));
vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);

#ifdef HAS_NORMALS
vec3 ng = normalize(v_Normal);
#else
vec3 ng = cross(pos_dx, pos_dy);
#endif

t = normalize(t - ng * dot(ng, t));
vec3 b = normalize(cross(ng, t));
mat3 tbn = mat3(t, b, ng);
#else // HAS_TANGENTS
mat3 tbn = v_TBN;
#endif

#ifdef HAS_NORMAL_MAP
vec3 n = texture2D(u_NormalSampler, UV).rgb;
n = normalize(tbn * ((2.0 * n - 1.0) * vec3(u_NormalScale, u_NormalScale, 1.0)));
#else
// The tbn matrix is linearly interpolated, so we need to re-normalize
vec3 n = normalize(tbn[2].xyz);
#endif

return n;
}

// Calculation of the lighting contribution from an optional Image Based Light source.
// Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
// See our README.md on Environment Maps [3] for additional discussion.
Expand Down Expand Up @@ -269,53 +176,6 @@ float microfacetDistribution(MaterialInfo materialInfo, AngularInfo angularInfo)
return roughnessSq / (M_PI * f * f);
}

float getPerceivedBrightness(vec3 vector)
{
return sqrt(0.299 * vector.r * vector.r + 0.587 * vector.g * vector.g + 0.114 * vector.b * vector.b);
}

// https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows/js/three.pbrUtilities.js#L34
float solveMetallic(vec3 diffuse, vec3 specular, float oneMinusSpecularStrength) {
float specularBrightness = getPerceivedBrightness(specular);

if (specularBrightness < c_MinReflectance) {
return 0.0;
}

float diffuseBrightness = getPerceivedBrightness(diffuse);

float a = c_MinReflectance;
float b = diffuseBrightness * oneMinusSpecularStrength / (1.0 - c_MinReflectance) + specularBrightness - 2.0 * c_MinReflectance;
float c = c_MinReflectance - specularBrightness;
float D = b * b - 4.0 * a * c;

return clamp((-b + sqrt(D)) / (2.0 * a), 0.0, 1.0);
}

AngularInfo getAngularInfo(vec3 pointToLight, vec3 normal, vec3 view)
{
// Standard one-letter names
vec3 n = normalize(normal); // Outward direction of surface point
vec3 v = normalize(view); // Direction from surface point to view
vec3 l = normalize(pointToLight); // Direction from surface point to light
vec3 h = normalize(l + v); // Direction of the vector between l and v

float NdotL = clamp(dot(n, l), 0.0, 1.0);
float NdotV = clamp(dot(n, v), 0.0, 1.0);
float NdotH = clamp(dot(n, h), 0.0, 1.0);
float LdotH = clamp(dot(l, h), 0.0, 1.0);
float VdotH = clamp(dot(v, h), 0.0, 1.0);

return AngularInfo(
NdotL,
NdotV,
NdotH,
LdotH,
VdotH,
vec3(0, 0, 0)
);
}

vec3 getPointShade(vec3 pointToLight, MaterialInfo materialInfo, vec3 normal, vec3 view)
{
AngularInfo angularInfo = getAngularInfo(pointToLight, normal, view);
Expand Down

0 comments on commit 13ab5ab

Please sign in to comment.