Skip to content

Commit

Permalink
Add attribution for the shader equations, also some misc cleanup
Browse files Browse the repository at this point in the history
Rename the "normal matrix" to better reflect its usage as a transform
from model -> world
Don't modify the gl context, instead store information about extensions
in the state
move the camera/view calculations outside of the per-mesh loop
Add information about which papers the different lighting information
came from to the shader.
  • Loading branch information
snagy committed Jun 9, 2017
1 parent efb537a commit 259b261
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 48 deletions.
7 changes: 3 additions & 4 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,6 @@ function init(vertSource, fragSource) {

var ctx2d = canvas2d.getContext("2d");

// Load extensions
gl.hasLodExt = gl.getExtension('EXT_shader_texture_lod');
gl.hasDerivativesExt = gl.getExtension('OES_standard_derivatives');
var hasSRGBExt = gl.getExtension('EXT_SRGB');

glState = {
Expand All @@ -147,6 +144,8 @@ function init(vertSource, fragSource) {
vertSource: vertSource,
fragSource: fragSource,
scene: null,
hasLODExtension:gl.getExtension('EXT_shader_texture_lod'),
hasDerivativesExtension:gl.getExtension('OES_standard_derivatives'),
sRGBifAvailable: (hasSRGBExt ? hasSRGBExt.SRGB_EXT : gl.RGBA)
};

Expand All @@ -170,7 +169,7 @@ function init(vertSource, fragSource) {
// Get location of mvp matrix uniform
glState.uniforms['u_mvpMatrix'] = { 'funcName': 'uniformMatrix4fv' };
// Get location of normal matrix uniform
glState.uniforms['u_NormalMatrix'] = { 'funcName': 'uniformMatrix4fv' };
glState.uniforms['u_modelMatrix'] = { 'funcName': 'uniformMatrix4fv' };

// Light
glState.uniforms['u_LightDirection'] = { 'funcName': 'uniform3f', 'vals': [0.0, 0.5, 0.5] };
Expand Down
40 changes: 20 additions & 20 deletions scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class Mesh {
}
var imageInfos = this.initTextures(gl, gltf);

this.initProgram(gl);
this.initProgram(gl, globalState);

this.accessorsLoading = 0;
// Attributes
Expand All @@ -65,7 +65,7 @@ class Mesh {
}


initProgram(gl) {
initProgram(gl, globalState) {
var definesToString = function(defines) {
var outStr = '';
for (var def in defines) {
Expand All @@ -75,7 +75,7 @@ class Mesh {
};

var shaderDefines = definesToString(this.defines);//"#define USE_SAVED_TANGENTS 1\n#define USE_MATHS 1\n#define USE_IBL 1\n";
if (gl.hasLodExt) {
if (globalState.hasLODExtension) {
shaderDefines += '#define USE_TEX_LOD 1\n';
}

Expand Down Expand Up @@ -111,28 +111,12 @@ class Mesh {
var modelMatrix = mat4.create();
mat4.multiply(modelMatrix, modelMatrix, transform);

// Update view matrix
// roll, pitch and translate are all globals. :)
var xRotation = mat4.create();
mat4.rotateY(xRotation, xRotation, roll);
var yRotation = mat4.create();
mat4.rotateX(yRotation, yRotation, pitch);
view = mat4.create();
mat4.multiply(view, yRotation, xRotation);
view[14] = -translate;

if (this.material.doubleSided) {
gl.disable(gl.CULL_FACE);
} else {
gl.enable(gl.CULL_FACE);
}

// set this outside of this function
var cameraPos = [view[14] * Math.sin(roll) * Math.cos(-pitch),
view[14] * Math.sin(-pitch),
-view[14] * Math.cos(roll) * Math.cos(-pitch)];
globalState.uniforms['u_Camera'].vals = cameraPos;

// Update mvp matrix
var mvMatrix = mat4.create();
var mvpMatrix = mat4.create();
Expand All @@ -142,7 +126,7 @@ class Mesh {
globalState.uniforms['u_mvpMatrix'].vals = [false, mvpMatrix];

// Update normal matrix
globalState.uniforms['u_NormalMatrix'].vals = [false, modelMatrix];
globalState.uniforms['u_modelMatrix'].vals = [false, modelMatrix];

applyState(gl, this.program, globalState, this.glState);

Expand Down Expand Up @@ -353,6 +337,22 @@ class Scene {
}
};

// set up the camera position and view matrix
var cameraPos = [-translate * Math.sin(roll) * Math.cos(-pitch),
-translate * Math.sin(-pitch),
translate * Math.cos(roll) * Math.cos(-pitch)];
this.globalState.uniforms['u_Camera'].vals = cameraPos;

// Update view matrix
// roll, pitch and translate are all globals.
var xRotation = mat4.create();
mat4.rotateY(xRotation, xRotation, roll);
var yRotation = mat4.create();
mat4.rotateX(yRotation, yRotation, pitch);
this.viewMatrix = mat4.create();
mat4.multiply(this.viewMatrix, yRotation, xRotation);
this.viewMatrix[14] = -translate;

var firstNode = this.nodes[0];

drawNodeRecursive(this, firstNode, mat4.create());
Expand Down
44 changes: 26 additions & 18 deletions shaders/pbr-frag.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -62,38 +62,43 @@ struct PBRInfo

const float M_PI = 3.141592653589793;

// diffuse
// The following equations model the diffuse term of the lighting equation
// Implementation of diffuse from "Physically-Based Shading at Disney" by Brent Burley
vec3 disneyDiffuse(PBRInfo pbrInputs)
{
float f90 = 2.*pbrInputs.LdotH*pbrInputs.LdotH*pbrInputs.roughness - 0.5;

return (pbrInputs.baseColor/M_PI)*(1.0+f90*pow((1.0-pbrInputs.NdotL),5.0))*(1.0+f90*pow((1.0-pbrInputs.NdotV),5.0));
}

// basic Lambertian diffuse, implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog
vec3 lambertianDiffuse(PBRInfo pbrInputs)
{
return pbrInputs.baseColor / M_PI;
}

// F
// r
// The following equations model the Fresnel reflectance term of the spec equation (aka F())
// implementation of fresnel from “An Inexpensive BRDF Model for Physically based Rendering” by Christophe Schlick
vec3 fresnelSchlick2(PBRInfo pbrInputs)
{
return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0);
}

// Simplified implementation of fresnel from “An Inexpensive BRDF Model for Physically based Rendering” by Christophe Schlick
vec3 fresnelSchlick(PBRInfo pbrInputs)
{
return pbrInputs.metalness + (vec3(1.0) - pbrInputs.metalness) * pow(1.0 - pbrInputs.VdotH, 5.0);
}

// G
float microfacetCookTorrance(PBRInfo pbrInputs)
// The following equations model the geometric occlusion term of the spec equation (aka G())
// Implementation from “A Reflectance Model for Computer Graphics” by Robert Cook and Kenneth Torrance,
float geometricOcclusionCookTorrance(PBRInfo pbrInputs)
{
return min(min(2.*pbrInputs.NdotV*pbrInputs.NdotH/pbrInputs.VdotH, 2.*pbrInputs.NdotL*pbrInputs.NdotH/pbrInputs.VdotH),1.0);
}

float microfacetSchlick(PBRInfo pbrInputs)
// implementation of microfacet occlusion from “An Inexpensive BRDF Model for Physically based Rendering” by Christophe Schlick
float geometricOcclusionSchlick(PBRInfo pbrInputs)
{
float k = pbrInputs.roughness * 0.79788; // 0.79788 = sqrt(2.0/3.1415);
// alternately, k can be defined with
Expand All @@ -104,7 +109,8 @@ float microfacetSchlick(PBRInfo pbrInputs)
return l * n;
}

float microfacetSmith_var1(PBRInfo pbrInputs)
// the following Smith implementations are from “Geometrical Shadowing of a Random Rough Surface” by Bruce G. Smith
float geometricOcclusionSmith(PBRInfo pbrInputs)
{
float NdotL2 = pbrInputs.NdotL * pbrInputs.NdotL;
float NdotV2 = pbrInputs.NdotV * pbrInputs.NdotV;
Expand All @@ -113,21 +119,24 @@ float microfacetSmith_var1(PBRInfo pbrInputs)
return (1. / max((1. + v + l ),0.000001));
}

float SmithVisibilityG1_var2(float NdotV, float r){
float SmithG1_var2(float NdotV, float r)
{
float tanSquared = (1.0 - NdotV * NdotV) / max((NdotV * NdotV),0.00001);
return 2.0 / (1.0 + sqrt(1.0 + r * r * tanSquared));
}

float SmithG1(float NdotV, float r) {
float SmithG1(float NdotV, float r)
{
return 2.0 * NdotV / (NdotV + sqrt(r*r+(1.0-r*r)*(NdotV*NdotV)));
}


float SmithVisibilityGGX(PBRInfo pbrInputs){
return SmithVisibilityG1_var2(pbrInputs.NdotL, pbrInputs.roughness) * SmithVisibilityG1_var2(pbrInputs.NdotV, pbrInputs.roughness);
float geometricOcclusionSmithGGX(PBRInfo pbrInputs)
{
return SmithG1_var2(pbrInputs.NdotL, pbrInputs.roughness) * SmithG1_var2(pbrInputs.NdotV, pbrInputs.roughness);
}

// D
// The following equation(s) model the distribution of microfacet normals across the area being drawn (aka D())
// implementation from “Average Irregularity Representation of a Roughened Surface for Ray Reflection” by T. S. Trowbridge, and K. P. Reitz
float GGX(PBRInfo pbrInputs)
{
float roughnessSq = pbrInputs.roughness*pbrInputs.roughness;
Expand All @@ -137,7 +146,6 @@ float GGX(PBRInfo pbrInputs)


void main() {

// Normal Map
#ifndef HAS_TANGENTS
vec3 pos_dx = dFdx(v_Position);
Expand Down Expand Up @@ -224,10 +232,10 @@ void main() {

vec3 F = fresnelSchlick2(pbrInputs);
//vec3 F = fresnelSchlick(pbrInputs);
//float G = microfacetCookTorrance(pbrInputs);
//float G = microfacetSmith(pbrInputs);
//float G = microfacetSchlick(pbrInputs);
float G = SmithVisibilityGGX(pbrInputs);
//float G = geometricOcclusionCookTorrance(pbrInputs);
//float G = geometricOcclusionSmith(pbrInputs);
//float G = geometricOcclusionSchlick(pbrInputs);
float G = geometricOcclusionSmithGGX(pbrInputs);
float D = GGX(pbrInputs);

vec3 diffuseContrib = (1.0 - F) * lambertianDiffuse(pbrInputs);
Expand Down
12 changes: 6 additions & 6 deletions shaders/pbr-vert.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ attribute vec2 a_UV;
#endif

uniform mat4 u_mvpMatrix;
uniform mat4 u_NormalMatrix;
uniform mat4 u_modelMatrix;

varying vec3 v_Position;
varying vec2 v_UV;
Expand All @@ -19,24 +19,24 @@ varying vec2 v_UV;
#ifdef HAS_TANGENTS
varying mat3 v_TBN;
#else
varying vec3 v_Normal;
varying vec3 v_Normal;
#endif
#endif


void main(){
vec4 pos = u_NormalMatrix * a_Position;
vec4 pos = u_modelMatrix * a_Position;
v_Position = vec3(pos.xyz) / pos.w;


#ifdef HAS_NORMALS
#ifdef HAS_TANGENTS
vec3 normalW = normalize(vec3(u_NormalMatrix * vec4(a_Normal.xyz, 0.0)));
vec3 tangentW = normalize(vec3(u_NormalMatrix * vec4(a_Tangent.xyz, 0.0)));
vec3 normalW = normalize(vec3(u_modelMatrix * vec4(a_Normal.xyz, 0.0)));
vec3 tangentW = normalize(vec3(u_modelMatrix * vec4(a_Tangent.xyz, 0.0)));
vec3 bitangentW = cross(normalW, tangentW) * a_Tangent.w;
v_TBN = mat3(tangentW, bitangentW, normalW);
#else // HAS_TANGENTS != 1
v_Normal = normalize(vec3(u_NormalMatrix * a_Normal));
v_Normal = normalize(vec3(u_modelMatrix * a_Normal));
#endif
#endif

Expand Down

0 comments on commit 259b261

Please sign in to comment.