Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add attribution for the shader equations, also some misc cleanup #17

Merged
merged 1 commit into from
Jun 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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