diff --git a/main.js b/main.js index b69c097d..a9d03acd 100644 --- a/main.js +++ b/main.js @@ -144,22 +144,38 @@ function initCubeBuffers(length, width, height, gl) { return 1; } -function loadCubeMap(gl) { +function loadCubeMap(gl, envMap, type) { var texture = gl.createTexture(); - var u_EnvSampler = gl.getUniformLocation(gl.program, 'u_EnvSampler'); - gl.activeTexture(gl.TEXTURE0); + var textureNumber = 0; + var u_EnvSampler; + if (type === "diffuse") { + u_EnvSampler = gl.getUniformLocation(gl.program, 'u_DiffuseEnvSampler'); + gl.activeTexture(gl.TEXTURE6); + textureNumber = 6; + } + else if (type === "specular") { + u_EnvSampler = gl.getUniformLocation(gl.program, 'u_SpecularEnvSampler'); + gl.activeTexture(gl.TEXTURE7); + textureNumber = 7; + } + else { + console.log('Invalid type of cubemap loaded\n'); + return -1; + } gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture); gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - var faces = [["textures/desertsky_right.png", gl.TEXTURE_CUBE_MAP_POSITIVE_X], - ["textures/desertsky_left.png", gl.TEXTURE_CUBE_MAP_NEGATIVE_X], - ["textures/desertsky_up.png", gl.TEXTURE_CUBE_MAP_POSITIVE_Y], - ["textures/desertsky_down.png", gl.TEXTURE_CUBE_MAP_NEGATIVE_Y], - ["textures/desertsky_front.png", gl.TEXTURE_CUBE_MAP_POSITIVE_Z], - ["textures/desertsky_back.png", gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]]; + var path = "textures/" + envMap + "/" + type; + + var faces = [[path + "_right.jpg", gl.TEXTURE_CUBE_MAP_POSITIVE_X], + [path + "_left.jpg", gl.TEXTURE_CUBE_MAP_NEGATIVE_X], + [path + "_top.jpg", gl.TEXTURE_CUBE_MAP_POSITIVE_Y], + [path + "_bottom.jpg", gl.TEXTURE_CUBE_MAP_NEGATIVE_Y], + [path + "_front.jpg", gl.TEXTURE_CUBE_MAP_POSITIVE_Z], + [path + "_back.jpg", gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]]; for (var i = 0; i < faces.length; i++) { var face = faces[i][1]; var image = new Image(); @@ -173,7 +189,7 @@ function loadCubeMap(gl) { image.src = faces[i][0]; } - gl.uniform1i(u_EnvSampler, 0); + gl.uniform1i(u_EnvSampler, textureNumber); return 1; } @@ -248,8 +264,10 @@ function main() { // Set positions of vertices //initCubeBuffers(1.0, 1.0, 1.0, gl); - // Create cube map - //loadCubeMap(gl); + // Create cube maps + var envMap = "papermill"; + loadCubeMap(gl, envMap, "diffuse"); + loadCubeMap(gl, envMap, "specular"); // Light var u_LightPosition = gl.getUniformLocation(gl.program, 'u_LightPosition'); @@ -332,7 +350,7 @@ function animate(angle) { var curr = Date.now(); var elapsed = curr - prev; prev = curr; - roll = angle + ((Math.PI / 8.0) * elapsed) / 1000.0; + roll = angle + ((Math.PI / 16.0) * elapsed) / 1000.0; } /****** KEYDOWN EVENT ******/ diff --git a/scene.js b/scene.js index 96346968..f40d46a4 100644 --- a/scene.js +++ b/scene.js @@ -76,7 +76,10 @@ class Scene { var normalsTexInfo = gltf.textures[this.material.normalTexture]; var normalsSrc = this.modelPath + gltf.images[normalsTexInfo.source].uri; - loadImages([baseColorSrc, metallicSrc, roughnessSrc, normalsSrc], createTextures, gl); + // brdfLUT + var brdfLUT = "textures/brdfLUT.jpg"; + + loadImages([baseColorSrc, metallicSrc, roughnessSrc, normalsSrc, brdfLUT], createTextures, gl); } drawScene(gl, modelMatrix, viewMatrix, projectionMatrix, u_mvpMatrix, u_NormalMatrix) { @@ -213,8 +216,12 @@ function createTextures(images, gl) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); - + if (i < images.length - 1){ + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); + } + else { + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + } gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, images[i]); textures.push(texture); @@ -224,18 +231,22 @@ function createTextures(images, gl) { var u_MetallicSampler = gl.getUniformLocation(gl.program, 'u_MetallicSampler'); var u_RoughnessSampler = gl.getUniformLocation(gl.program, 'u_RoughnessSampler'); var u_NormalSampler = gl.getUniformLocation(gl.program, 'u_NormalSampler'); + var u_brdfLUT = gl.getUniformLocation(gl.program, 'u_brdfLUT'); - gl.uniform1i(u_BaseColorSampler, 0); - gl.uniform1i(u_MetallicSampler, 1); - gl.uniform1i(u_RoughnessSampler, 2); - gl.uniform1i(u_NormalSampler, 3); + gl.uniform1i(u_BaseColorSampler, 1); + gl.uniform1i(u_MetallicSampler, 2); + gl.uniform1i(u_RoughnessSampler, 3); + gl.uniform1i(u_NormalSampler, 4); + gl.uniform1i(u_brdfLUT, 5); - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, textures[0]); gl.activeTexture(gl.TEXTURE1); - gl.bindTexture(gl.TEXTURE_2D, textures[1]); + gl.bindTexture(gl.TEXTURE_2D, textures[0]); gl.activeTexture(gl.TEXTURE2); - gl.bindTexture(gl.TEXTURE_2D, textures[2]); + gl.bindTexture(gl.TEXTURE_2D, textures[1]); gl.activeTexture(gl.TEXTURE3); + gl.bindTexture(gl.TEXTURE_2D, textures[2]); + gl.activeTexture(gl.TEXTURE4); gl.bindTexture(gl.TEXTURE_2D, textures[3]); + gl.activeTexture(gl.TEXTURE5); + gl.bindTexture(gl.TEXTURE_2D, textures[4]); } diff --git a/shaders/pbr-frag.glsl b/shaders/pbr-frag.glsl index 2c9a0fe2..362ed34f 100644 --- a/shaders/pbr-frag.glsl +++ b/shaders/pbr-frag.glsl @@ -1,6 +1,8 @@ precision mediump float; uniform vec3 u_LightPosition; -uniform samplerCube u_EnvSampler; +uniform samplerCube u_DiffuseEnvSampler; +uniform samplerCube u_SpecularEnvSampler; +uniform sampler2D u_brdfLUT; uniform sampler2D u_BaseColorSampler; uniform sampler2D u_MetallicSampler; uniform sampler2D u_RoughnessSampler; @@ -18,8 +20,6 @@ varying vec3 v_Position; const float M_PI = 3.141592653589793; void main(){ - vec4 baseColor = texture2D(u_BaseColorSampler, v_UV); - // Normal Map vec3 n = normalize(v_Normal); vec3 t = normalize(v_Tangent); @@ -28,42 +28,25 @@ void main(){ n = texture2D(u_NormalSampler, v_UV).rgb; n = normalize(n * 2.0 - 1.0); n = normalize(tbn * n); - - vec3 l = normalize(u_LightPosition - v_Position); vec3 v = normalize(u_Camera - v_Position); - vec3 h = normalize(l + v); - float nDotV = max(0.0, dot(n,v)); - float nDotL = max(0.0, dot(n,l)); - float nDotH = max(0.0, dot(n,h)); - float vDotH = max(0.0, dot(v,h)); + vec3 r = -normalize(reflect(v, n)); + float NoV = max(0.0, dot(n, v)); - // Fresnel Term: Schlick's Approximation + float roughness = texture2D(u_RoughnessSampler, v_UV).x; float metallic = texture2D(u_MetallicSampler, v_UV).x; - vec3 specularColor = (baseColor.rgb * metallic) + (vec3(0.04) * (1.0 - metallic)); - vec3 f = specularColor + ((1.0 - specularColor) * pow(1.0 - vDotH, 5.0)); + vec3 baseColor = texture2D(u_BaseColorSampler, v_UV).rgb; - // Geometric Attenuation Term: Schlick-Beckmann - float roughness = texture2D(u_RoughnessSampler, v_UV).x; - float a = roughness * roughness; // UE4 definition - float k = ((roughness + 1.0) * (roughness + 1.0)) / 8.0; - float g1L = nDotL / ((nDotL * (1.0 - k)) + k); - float g1V = nDotV / ((nDotV * (1.0 - k)) + k); - float g = g1L * g1V; + vec3 brdf = texture2D(u_brdfLUT, vec2(NoV, 1.0 - roughness)).rgb; + vec3 diffuseLight = textureCube(u_DiffuseEnvSampler, n).rgb; + vec3 specularLight = textureCube(u_SpecularEnvSampler, r).rgb; - // Normal Distribution Function: GGX (Trowbridge-Reitz) - float a2 = a * a; - float nDotH2 = nDotH * nDotH; - float denom = M_PI * (nDotH2 * (a2 - 1.0) + 1.0) * (nDotH2 * (a2 - 1.0) + 1.0); - float d = a2 / denom; + vec3 f0 = vec3(0.04); + vec3 diffuseColor = baseColor * (1.0 - metallic); + vec3 specularColor = mix(f0, baseColor, metallic); - // Specular BRDF - vec3 specBRDF = (d * f * g) / (4.0 * nDotL * nDotV); + vec3 color = (diffuseLight * diffuseColor) + (specularLight * (specularColor * brdf.x + brdf.y)); - metallic = 0.5; // Hack to look good before environment maps - vec3 diffuseColor = baseColor.rgb * (1.0 - metallic); - vec4 diffuse = vec4(diffuseColor * nDotL, 1.0); - vec4 specular = vec4(specularColor * specBRDF, 1.0); - gl_FragColor = clamp(diffuse + specular, 0.0, 1.0); + gl_FragColor = vec4(color, 1.0); } diff --git a/shaders/single-light-pbr-frag.glsl b/shaders/single-light-pbr-frag.glsl new file mode 100644 index 00000000..4f1820bd --- /dev/null +++ b/shaders/single-light-pbr-frag.glsl @@ -0,0 +1,71 @@ +precision mediump float; +uniform vec3 u_LightPosition; +uniform samplerCube u_DiffuseEnvSampler; +uniform samplerCube u_SpecularEnvSampler; +uniform sampler2D u_brdfLUT; +uniform sampler2D u_BaseColorSampler; +uniform sampler2D u_MetallicSampler; +uniform sampler2D u_RoughnessSampler; +uniform sampler2D u_NormalSampler; +uniform vec3 u_Camera; +uniform vec3 u_BaseColor; +uniform float u_Metallic; +uniform float u_Roughness; +varying vec4 v_Color; +varying vec2 v_UV; +varying vec3 v_Tangent; +varying vec3 v_Normal; +varying vec3 v_Position; + +const float M_PI = 3.141592653589793; + +void main(){ + vec4 baseColor = texture2D(u_BaseColorSampler, v_UV); + + // Normal Map + vec3 n = normalize(v_Normal); + vec3 t = normalize(v_Tangent); + vec3 b = cross(n, t); + mat3 tbn = mat3(t, b, n); + n = texture2D(u_NormalSampler, v_UV).rgb; + n = normalize(n * 2.0 - 1.0); + n = normalize(tbn * n); + + vec3 l = normalize(u_LightPosition - v_Position); + vec3 v = normalize(u_Camera - v_Position); + vec3 h = normalize(l + v); + float nDotV = max(0.0, dot(n,v)); + float nDotL = max(0.0, dot(n,l)); + float nDotH = max(0.0, dot(n,h)); + float vDotH = max(0.0, dot(v,h)); + + // Fresnel Term: Schlick's Approximation + float metallic = texture2D(u_MetallicSampler, v_UV).x; + vec3 specularColor = (baseColor.rgb * metallic) + (vec3(0.04) * (1.0 - metallic)); + vec3 f = specularColor + ((1.0 - specularColor) * pow(1.0 - vDotH, 5.0)); + + // Geometric Attenuation Term: Schlick-Beckmann + float roughness = texture2D(u_RoughnessSampler, v_UV).x; + float a = roughness * roughness; // UE4 definition + float k = ((roughness + 1.0) * (roughness + 1.0)) / 8.0; + float g1L = nDotL / ((nDotL * (1.0 - k)) + k); + float g1V = nDotV / ((nDotV * (1.0 - k)) + k); + float g = g1L * g1V; + + // Normal Distribution Function: GGX (Trowbridge-Reitz) + float a2 = a * a; + float nDotH2 = nDotH * nDotH; + float denom = M_PI * (nDotH2 * (a2 - 1.0) + 1.0) * (nDotH2 * (a2 - 1.0) + 1.0); + float d = a2 / denom; + + // Specular BRDF + vec3 specBRDF = (d * f * g) / (4.0 * nDotL * nDotV); + + metallic = max(0.5, u_Metallic); // Hack to look good before environment maps + vec3 diffuseColor = baseColor.rgb * (1.0 - metallic); + vec4 diffuse = vec4(diffuseColor * nDotL, 1.0); + vec4 specular = vec4(specularColor * specBRDF, 1.0); + gl_FragColor = clamp(diffuse + specular, 0.0, 1.0); +} + + diff --git a/textures/brdfLUT.jpg b/textures/brdfLUT.jpg new file mode 100644 index 00000000..6d171a38 Binary files /dev/null and b/textures/brdfLUT.jpg differ diff --git a/textures/papermill/diffuse_back.jpg b/textures/papermill/diffuse_back.jpg new file mode 100644 index 00000000..9ba140c5 Binary files /dev/null and b/textures/papermill/diffuse_back.jpg differ diff --git a/textures/papermill/diffuse_bottom.jpg b/textures/papermill/diffuse_bottom.jpg new file mode 100644 index 00000000..d7c18b4d Binary files /dev/null and b/textures/papermill/diffuse_bottom.jpg differ diff --git a/textures/papermill/diffuse_front.jpg b/textures/papermill/diffuse_front.jpg new file mode 100644 index 00000000..c76d5edb Binary files /dev/null and b/textures/papermill/diffuse_front.jpg differ diff --git a/textures/papermill/diffuse_left.jpg b/textures/papermill/diffuse_left.jpg new file mode 100644 index 00000000..c66a1136 Binary files /dev/null and b/textures/papermill/diffuse_left.jpg differ diff --git a/textures/papermill/diffuse_right.jpg b/textures/papermill/diffuse_right.jpg new file mode 100644 index 00000000..7d4a5490 Binary files /dev/null and b/textures/papermill/diffuse_right.jpg differ diff --git a/textures/papermill/diffuse_top.jpg b/textures/papermill/diffuse_top.jpg new file mode 100644 index 00000000..216e2286 Binary files /dev/null and b/textures/papermill/diffuse_top.jpg differ diff --git a/textures/papermill/env_back.jpg b/textures/papermill/env_back.jpg new file mode 100644 index 00000000..0f4d556d Binary files /dev/null and b/textures/papermill/env_back.jpg differ diff --git a/textures/papermill/env_bottom.jpg b/textures/papermill/env_bottom.jpg new file mode 100644 index 00000000..03949f3e Binary files /dev/null and b/textures/papermill/env_bottom.jpg differ diff --git a/textures/papermill/env_front.jpg b/textures/papermill/env_front.jpg new file mode 100644 index 00000000..ceff4ce0 Binary files /dev/null and b/textures/papermill/env_front.jpg differ diff --git a/textures/papermill/env_left.jpg b/textures/papermill/env_left.jpg new file mode 100644 index 00000000..57bc7998 Binary files /dev/null and b/textures/papermill/env_left.jpg differ diff --git a/textures/papermill/env_right.jpg b/textures/papermill/env_right.jpg new file mode 100644 index 00000000..4e03a9d7 Binary files /dev/null and b/textures/papermill/env_right.jpg differ diff --git a/textures/papermill/env_top.jpg b/textures/papermill/env_top.jpg new file mode 100644 index 00000000..fac22132 Binary files /dev/null and b/textures/papermill/env_top.jpg differ diff --git a/textures/papermill/specular_back.jpg b/textures/papermill/specular_back.jpg new file mode 100644 index 00000000..c7705332 Binary files /dev/null and b/textures/papermill/specular_back.jpg differ diff --git a/textures/papermill/specular_bottom.jpg b/textures/papermill/specular_bottom.jpg new file mode 100644 index 00000000..7b5271c5 Binary files /dev/null and b/textures/papermill/specular_bottom.jpg differ diff --git a/textures/papermill/specular_front.jpg b/textures/papermill/specular_front.jpg new file mode 100644 index 00000000..1412ed42 Binary files /dev/null and b/textures/papermill/specular_front.jpg differ diff --git a/textures/papermill/specular_left.jpg b/textures/papermill/specular_left.jpg new file mode 100644 index 00000000..76249316 Binary files /dev/null and b/textures/papermill/specular_left.jpg differ diff --git a/textures/papermill/specular_right.jpg b/textures/papermill/specular_right.jpg new file mode 100644 index 00000000..b4312858 Binary files /dev/null and b/textures/papermill/specular_right.jpg differ diff --git a/textures/papermill/specular_top.jpg b/textures/papermill/specular_top.jpg new file mode 100644 index 00000000..56edddae Binary files /dev/null and b/textures/papermill/specular_top.jpg differ