Skip to content

Commit

Permalink
Merge pull request #17 from snagy/master
Browse files Browse the repository at this point in the history
Add attribution for the shader equations, also some misc cleanup
  • Loading branch information
emackey authored Jun 11, 2017
2 parents efb537a + 259b261 commit 25f0564
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 25f0564

Please sign in to comment.