From 01445776850ae762305648a4965b4107e1c64410 Mon Sep 17 00:00:00 2001 From: Elohiem <20236-Elohiem@users.noreply.gitgud.io> Date: Tue, 24 Aug 2021 01:27:26 +0200 Subject: [PATCH] PBR initial commit --- js/003-data/gameVariableData.js | 1 - src/art/artJS.js | 2 + src/art/webgl/art.js | 20 +- src/art/webgl/engine.js | 987 ++++++++++++++++++++++++-------- src/art/webgl/ui.js | 11 - src/gui/options/options.js | 2 - 6 files changed, 755 insertions(+), 268 deletions(-) diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js index d366e2ad04b..9c4d6c78d5e 100644 --- a/js/003-data/gameVariableData.js +++ b/js/003-data/gameVariableData.js @@ -142,7 +142,6 @@ App.Data.defaultGameStateVariables = { setZoomSpeed: 1, setFaceCulling: false, setTextureResolution: 1024, - setColorBurn: true, showAgeDetail: 1, showAppraisal: 1, showAssignToScenes: 1, diff --git a/src/art/artJS.js b/src/art/artJS.js index 6c759a84739..17fb6e1cccc 100644 --- a/src/art/artJS.js +++ b/src/art/artJS.js @@ -242,6 +242,8 @@ App.Art.webglArtElement = function(slave, artSize) { App.Art.applyMaterials(slave, scene, p); App.Art.applyMorphs(slave, scene, p); + console.log(scene); + // create UI and render based on active view container.innerText = ""; App.Art.createWebglUI(container, slave, artSize, scene, p); diff --git a/src/art/webgl/art.js b/src/art/webgl/art.js index 5719c499499..22ca02d63c8 100644 --- a/src/art/webgl/art.js +++ b/src/art/webgl/art.js @@ -1128,10 +1128,10 @@ App.Art.applyMaterials = function(slave, scene, p) { let scleraColorLeft = App.Art.hexToRgb(extractColor(hasLeftEye(slave) ? extractColor(slave.eye.left.sclera) : extractColor("black"))); let scleraColorRight = App.Art.hexToRgb(extractColor(hasRightEye(slave) ? extractColor(slave.eye.right.sclera) : extractColor("black"))); - materials.push(["Iris_Left", "Kd", [irisColorLeft[0], irisColorLeft[1], irisColorLeft[2]]]); - materials.push(["Iris_Right", "Kd", [irisColorRight[0], irisColorRight[1], irisColorRight[2]]]); - materials.push(["Sclera_Left", "Kd", [scleraColorLeft[0] * 0.6, scleraColorLeft[1] * 0.6, scleraColorLeft[2] * 0.56]]); - materials.push(["Sclera_Right", "Kd", [scleraColorRight[0] * 0.6, scleraColorRight[1] * 0.6, scleraColorRight[2] * 0.56]]); + materials.push(["Iris_Left", "Kd", [irisColorLeft[0]*2, irisColorLeft[1]*2, irisColorLeft[2]*2]]); + materials.push(["Iris_Right", "Kd", [irisColorRight[0]*2, irisColorRight[1]*2, irisColorRight[2]*2]]); + materials.push(["Sclera_Left", "Kd", [scleraColorLeft[0]*0.8, scleraColorLeft[1]*0.8, scleraColorLeft[2]*0.8]]); + materials.push(["Sclera_Right", "Kd", [scleraColorRight[0]*0.8, scleraColorRight[1]*0.8, scleraColorRight[2]*0.8]]); // expected skin color let O = App.Art.hexToRgb(skinColorCatcher(slave).skinColor); @@ -1182,9 +1182,9 @@ App.Art.applyMaterials = function(slave, scene, p) { materials.push(["WhiteToneAnus", "Ks", S]); materials.push(["WhiteToneGenitalia", "Kd", mA]); materials.push(["WhiteToneGenitalia", "Ks", S]); - materials.push(["WhiteFutalicious_Genitalia_G8F_Glans_Futalicious_Shell", "Kd", [mA[0]*0.8, mA[1]*0.8, mA[2]*0.8]]); + materials.push(["WhiteFutalicious_Genitalia_G8F_Glans_Futalicious_Shell", "Kd", [mA[0]*0.9, mA[1]*0.9, mA[2]*0.9]]); materials.push(["WhiteFutalicious_Genitalia_G8F_Glans_Futalicious_Shell", "Ks", S]); - materials.push(["nipple_mask", "Kd", [areolaColor[0]*0.7/A[0], areolaColor[1]*0.7/A[1], areolaColor[2]*0.7/A[2]]]); + materials.push(["nipple_mask", "Kd", [areolaColor[0]/A[0], areolaColor[1]/A[1], areolaColor[2]/A[2]]]); materials.push(["nipple_mask", "map_Kd", "base2/skin/torso white.jpg"]); } else if (sqBO < sqAO && sqBO < sqCO && sqBO < sqDO) { materials.push(["LightToneTorso", "Kd", mB]); @@ -1207,9 +1207,9 @@ App.Art.applyMaterials = function(slave, scene, p) { materials.push(["LightToneAnus", "Ks", S]); materials.push(["LightToneGenitalia", "Kd", mB]); materials.push(["LightToneGenitalia", "Ks", S]); - materials.push(["LightFutalicious_Genitalia_G8F_Glans_Futalicious_Shell", "Kd", [mB[0]*0.8, mB[1]*0.77, mB[2]*0.80]]); + materials.push(["LightFutalicious_Genitalia_G8F_Glans_Futalicious_Shell", "Kd", [mB[0]*0.8, mB[1]*0.77, mB[2]*0.8]]); materials.push(["LightFutalicious_Genitalia_G8F_Glans_Futalicious_Shell", "Ks", S]); - materials.push(["nipple_mask", "Kd", [areolaColor[0]*0.8/B[0], areolaColor[1]*0.8/B[1], areolaColor[2]*0.8/B[2]]]); + materials.push(["nipple_mask", "Kd", [areolaColor[0]/B[0], areolaColor[1]/B[1], areolaColor[2]/B[2]]]); materials.push(["nipple_mask", "map_Kd", "base2/skin/torso light.jpg"]); } else if (sqCO < sqBO && sqCO < sqAO && sqCO < sqDO) { materials.push(["MidToneTorso", "Kd", mC]); @@ -1232,7 +1232,7 @@ App.Art.applyMaterials = function(slave, scene, p) { materials.push(["MidToneAnus", "Ks", S]); materials.push(["MidToneGenitalia", "Kd", mC]); materials.push(["MidToneGenitalia", "Ks", S]); - materials.push(["MidFutalicious_Genitalia_G8F_Glans_Futalicious_Shell", "Kd", [mC[0]*0.65, mC[1]*0.65, mC[2]*0.65]]); + materials.push(["MidFutalicious_Genitalia_G8F_Glans_Futalicious_Shell", "Kd", [mC[0]*0.7, mC[1]*0.7, mC[2]*0.7]]); materials.push(["MidFutalicious_Genitalia_G8F_Glans_Futalicious_Shell", "Ks", S]); materials.push(["nipple_mask", "Kd", [areolaColor[0]/C[0], areolaColor[1]/C[1], areolaColor[2]/C[2]]]); materials.push(["nipple_mask", "map_Kd", "base2/skin/torso mid.jpg"]); @@ -1257,7 +1257,7 @@ App.Art.applyMaterials = function(slave, scene, p) { materials.push(["DarkToneAnus", "Ks", S]); materials.push(["DarkToneGenitalia", "Kd", mD]); materials.push(["DarkToneGenitalia", "Ks", S]); - materials.push(["DarkFutalicious_Genitalia_G8F_Glans_Futalicious_Shell", "Kd", [mD[0]*0.75, mD[1]*0.75, mD[2]*0.75]]); + materials.push(["DarkFutalicious_Genitalia_G8F_Glans_Futalicious_Shell", "Kd", [mD[0]*0.85, mD[1]*0.85, mD[2]*0.85]]); materials.push(["DarkFutalicious_Genitalia_G8F_Glans_Futalicious_Shell", "Ks", S]); materials.push(["nipple_mask", "Kd", [areolaColor[0]/D[0], areolaColor[1]/D[1], areolaColor[2]/D[2]]]); materials.push(["nipple_mask", "map_Kd", "base2/skin/torso dark.jpg"]); diff --git a/src/art/webgl/engine.js b/src/art/webgl/engine.js index 4b4e5608758..75cd35adcaa 100644 --- a/src/art/webgl/engine.js +++ b/src/art/webgl/engine.js @@ -1,76 +1,164 @@ 'use strict'; App.Art.Engine = class { - getVsSourceBg() { + getVsSourceGeometry() { return `#version 300 es - precision highp float; + precision highp float; - in vec2 vertexPosition; - out vec2 vertexPos; - - void main() { - vertexPos = vertexPosition; - gl_Position = vec4(vertexPosition, 0.0, 1.0); - }`; - } + uniform mat4 matModelViewProjection; + uniform mat4 matModelView; + uniform mat4 matModel; + uniform mat4 matNormal; - getFsSourceBg() { - return `#version 300 es - precision highp float; - precision highp sampler2D; + in vec3 vertexNormal; + in vec3 vertexPosition; + in vec2 textureCoordinate; - uniform sampler2D textSampler; - uniform vec4 backgroundColor; + in vec3 vertexNormalMorph; + in vec3 vertexPositionMorph; - in vec2 vertexPos; - out vec4 outputColor; + out vec2 textureCoord; + out vec3 normal; + out vec3 pos; - void main() { - vec2 textureCoord = vec2(vertexPos.s, -vertexPos.t) * 0.5 + 0.5; - vec3 c = backgroundColor.rgb * texture(textSampler, textureCoord.st).rgb; - outputColor = vec4(c.rgb * backgroundColor.a, backgroundColor.a); - }`; + void main() { + gl_Position = matModelViewProjection * vec4(vertexPosition + vertexPositionMorph, 1.0); + normal = normalize((matNormal * vec4(vertexNormal + vertexNormalMorph, 1.0)).xyz); + + textureCoord = textureCoordinate; + pos = (matModelView * vec4(vertexPosition + vertexPositionMorph, 1.0)).xyz; + }`; } - getVsSource() { + getFsSourceGeometry() { return `#version 300 es - precision highp float; + precision highp float; - uniform mat4 matView; - uniform mat4 matProj; - uniform mat4 matRot; - uniform mat4 matTrans; - uniform mat4 matScale; + layout(location = 0) out vec3 gPosition; + layout(location = 1) out vec3 gNormal; + layout(location = 2) out float gAlpha; - in vec3 vertexNormal; - in vec3 vertexPosition; - in vec2 textureCoordinate; - in vec3 vertexTangent; + uniform sampler2D alpha; - in vec3 vertexNormalMorph; - in vec3 vertexPositionMorph; + in vec2 textureCoord; + in vec3 pos; + in vec3 normal; - out vec2 textureCoord; - out vec3 normal; - out vec3 pos; - out mat3 TBN; + void main() { + float map_d = texture(alpha, textureCoord).r; - void main() { - gl_Position = matProj * matView * matTrans * matScale * matRot * vec4(vertexPosition + vertexPositionMorph, 1.0); - normal = normalize((matRot * vec4(vertexNormal + vertexNormalMorph, 1.0)).xyz); + if (map_d < 0.85) + discard; + + gPosition = pos; + gNormal = normal; + gAlpha = map_d; + }`; + } + + getVsSourceQuad() { + return `#version 300 es + precision highp float; + + in vec2 vertexPosition; + in vec2 textureCoordinate; - vec3 T = normalize((matRot * vec4(vertexTangent, 1.0)).xyz); - vec3 N = normalize((matRot * vec4(vertexNormal + vertexNormalMorph, 1.0)).xyz); - T = normalize(T - dot(T, N) * N); - vec3 B = cross(N, T); - TBN = mat3(T, B, N); + out vec2 textureCoord; - textureCoord = textureCoordinate; - pos = (matTrans * matScale * matRot * vec4(vertexPosition + vertexPositionMorph, 1.0)).xyz; + void main() { + textureCoord = textureCoordinate; + gl_Position = vec4(vertexPosition, 0.0, 1.0); }`; } - getFsSource(dl, pl) { + getFsSourceSSAO() { + return `#version 300 es + precision highp float; + + out float ao; + + in vec2 textureCoord; + + uniform sampler2D gPosition; + uniform sampler2D gNormal; + uniform sampler2D gAlpha; + uniform sampler2D texNoise; + + uniform vec3 samples[32]; + + uniform mat4 projection; + uniform mat4 view; + + uniform float radius; + uniform float bias; + uniform float scale; + + void main() { + vec2 resolution = vec2(textureSize(gPosition, 0)); + vec3 pos = texture(gPosition, textureCoord).xyz; + vec3 normal = normalize(texture(gNormal, textureCoord).rgb); + + // tile noise texture over screen based on screen dimensions divided by noise size + vec3 randomVec = normalize(texture(texNoise, textureCoord * resolution / vec2(3.0, 3.0)).xyz); + + // create TBN + vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); + vec3 bitangent = cross(normal, tangent); + mat3 TBN = mat3(tangent, bitangent, normal); + + // iterate over the sample kernel and calculate occlusion factor + float occlusion = 0.0; + for(int i = 0; i < 32; i++) + { + // get sample position + vec3 samplePos = TBN * samples[i]; // from tangent to view-space + samplePos = pos + samplePos * radius; + + // project sample position + vec4 offset = vec4(samplePos, 1.0); + offset = projection * offset; // from view to clip-space + offset.xy /= offset.w; // perspective divide + offset.xy = offset.xy * 0.5 + 0.5; // transform to range 0.0 - 1.0 + + float sampleDepth = texture(gPosition, offset.xy).z; + + // range check & accumulate + float rangeCheck = smoothstep(0.0, 1.0, radius / abs(pos.z - sampleDepth)); + occlusion += (sampleDepth <= samplePos.z + bias ? 1.0 : 0.0) * rangeCheck; + } + occlusion = 1.0 - (occlusion / scale); + + ao = occlusion * texture(gAlpha, textureCoord).r; + }`; + } + + getFsSourceSSAOBlur() { + return `#version 300 es + precision highp float; + + out float ao; + in vec2 textureCoord; + + uniform sampler2D ssaoInput; + uniform int blur; + + void main() + { + vec2 texelSize = 1.0 / vec2(textureSize(ssaoInput, 0)); + float result = 0.0; + for (int x = -blur; x <= blur; x++) + { + for (int y = -blur; y <= blur; y++) + { + vec2 offset = vec2(float(x), float(y)) * texelSize; + result += texture(ssaoInput, textureCoord + offset).r; + } + } + ao = result / (float(blur*2+1) * float(blur*2+1)); + }`; + } + + getFsSourceForwardPass(dl, pl) { return `#version 300 es precision highp float; precision highp sampler2D; @@ -87,8 +175,11 @@ App.Art.Engine = class { uniform float whiteM; uniform float gammaY; + uniform vec3 irradiance; + uniform float ssaoInt; + uniform float albedoInt; - uniform vec3 Ka; + uniform vec3 Ka; uniform vec3 Kd; uniform vec3 Ks; uniform vec3 Ke; @@ -96,117 +187,221 @@ App.Art.Engine = class { uniform float Ns; uniform float sNormals; + uniform float sSSAO; + uniform float sAO; uniform float sAmbient; uniform float sDiffuse; uniform float sSpecular; uniform float sEmission; uniform float sAlpha; uniform float sGamma; + uniform float sHDR; uniform float sReinhard; uniform float sNormal; - uniform float sColorBurn; + + uniform float roughness; + uniform float metallic; + uniform vec3 fresnel; - uniform vec3 lookDir; + uniform vec3 cameraPos; uniform sampler2D textSampler[7]; - in vec2 textureCoord; - in vec3 normal; + in vec2 textureCoord; + in vec3 normal; in vec3 pos; - in mat3 TBN; out vec4 outputColor; + const float PI = 3.14159265359; + + float distributionGGX(vec3 N, vec3 H, float roughness) + { + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float num = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return num / denom; + } + + float geometrySchlickGGX(float NdotV, float roughness) + { + float r = (roughness + 1.0); + float k = (r*r) / 8.0; + + float num = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return num / denom; + } + + float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) + { + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = geometrySchlickGGX(NdotV, roughness); + float ggx1 = geometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; + } + + vec3 fresnelSchlick(float cosTheta, vec3 F0) + { + return F0 + (1.0 - F0) * pow(max(1.0 - cosTheta, 0.0), 5.0); + } + + vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) + { + return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(max(1.0 - cosTheta, 0.0), 5.0); + } + + mat3 createTBNMatrix(vec3 position, vec2 coord, vec3 normal) + { + vec3 tangent = normalize(dFdx(position)*dFdy(coord).t - dFdy(position)*dFdx(coord).t); + vec3 bitangent = cross(normal, tangent); + return mat3(tangent, bitangent, normal); + } + void main() { + vec2 resolution = vec2(textureSize(textSampler[0], 0)); + mat3 TBN = createTBNMatrix(pos, textureCoord, normal); + vec3 new_normal = normal; - vec3 map_Ka = vec3(0.0,0.0,0.0); vec3 map_Kd = vec3(0.0,0.0,0.0); vec3 map_Ks = vec3(0.0,0.0,0.0); vec3 map_Ke = vec3(0.0,0.0,0.0); float map_Ns = 0.0; float map_d = 1.0; + float ao = 0.0; + float r = roughness; - if (sNormal == 1.0) { - vec3 map_Kn = texture(textSampler[5], textureCoord.st).rgb *2.0-1.0; - if (map_Kn != vec3(-1.0,-1.0,-1.0)) - new_normal = normalize(TBN * map_Kn); + if (sNormal == 1.0) { + vec3 map_Kn = texture(textSampler[5], textureCoord).rgb *2.0-1.0; + if (map_Kn != vec3(-1.0,-1.0,-1.0)) { + new_normal = normalize(TBN * map_Kn); + } } - if (sAmbient == 1.0) - map_Ka = Ka * texture(textSampler[0], textureCoord.st).rgb; + if (sSSAO == 1.0) + ao = texture(textSampler[0], vec2(gl_FragCoord.x, gl_FragCoord.y) / resolution).r; - if (sDiffuse == 1.0) - map_Kd = Kd * texture(textSampler[1], textureCoord.st).rgb; + if (sDiffuse == 1.0) + map_Kd = Kd * texture(textSampler[1], textureCoord).rgb; if (sSpecular == 1.0) { - map_Ks = Ks * texture(textSampler[2], textureCoord.st).rgb; - map_Ns = Ns * texture(textSampler[3], textureCoord.st).r; + map_Ks = Ks * texture(textSampler[2], textureCoord).rgb; + map_Ns = Ns * texture(textSampler[3], textureCoord).r; + r = (1.0 - map_Ks.r) * roughness; } - if (sEmission == 1.0) { - map_Ke = Ke * texture(textSampler[6], textureCoord.st).rgb; - } + if (sEmission == 1.0) + map_Ke = Ke * texture(textSampler[6], textureCoord).rgb; if (sAlpha == 1.0) - map_d = d * texture(textSampler[4], textureCoord.st).r; + map_d = d * texture(textSampler[4], textureCoord).r; if (map_d < 0.05) discard; - vec3 Ld = vec3(0.0,0.0,0.0); - vec3 Ls = vec3(0.0,0.0,0.0); - vec3 La = vec3(0.0,0.0,0.0); + // material parameters + vec3 albedo = pow(map_Kd, vec3(albedoInt)); + ao = pow(ao, ssaoInt); + + vec3 N = new_normal; + vec3 V = normalize(cameraPos - pos); + vec3 F0 = mix(fresnel, albedo, metallic); + + // reflectance equation + vec3 Lo = vec3(0.0); vec3 Le = map_Ke; + for (int i = 0; i < ${dl}; i++) { - if (sColorBurn == 1.0) { - float l1 = dot(map_Kd, vec3(0.2126,0.7152,0.0722)); - float l2 = dot(map_Kd * map_Kd, vec3(0.2126,0.7152,0.0722)); - map_Kd = l1/(l2+0.0001) * map_Kd * map_Kd; + // calculate per-light radiance + vec3 L = -lightVect[i]; + vec3 H = normalize(V + L); + float attenuation = lightInt[i]; + vec3 radiance = lightColor[i] * attenuation; + + // cook-torrance brdf + float NDF = distributionGGX(N, H, r); + float G = geometrySmith(N, V, L, r); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001; + vec3 specular = numerator / denominator; + + // kS is equal to Fresnel + vec3 kD = vec3(1.0) - F; + kD *= 1.0 - metallic; + + // add to outgoing radiance Lo + float NdotL = max(dot(N, L), 0.0); + Lo += (kD * albedo / PI + specular) * radiance * NdotL; } - map_Ka = map_Kd * map_Ka; - - for (int i = 0; i < ${dl}; i++) { - float angle = max(dot(-lightVect[i], new_normal),0.0); - vec3 reflection = reflect(-lightVect[i], new_normal); - float specular = pow(max(dot(reflection, lookDir),0.0), (0.0001+map_Ns)); - - Ld += map_Kd * lightInt[i] * angle * lightColor[i]; - Ls += map_Ks * lightInt[i] * specular * angle * lightColor[i]; - La += map_Ka * lightInt[i] * (1.0-angle) * lightAmb[i] * lightColor[i]; - } + for (int i = 0; i < ${pl}; i++) { + + // calculate per-light radiance + vec3 L = normalize(pointLightPos[i] - pos); + vec3 H = normalize(V + L); + float attenuation = pointLightInt[i]; + vec3 radiance = pointLightColor[i] * attenuation; + + // cook-torrance brdf + float NDF = distributionGGX(N, H, r); + float G = geometrySmith(N, V, L, r); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001; + vec3 specular = numerator / denominator; + + // kS is equal to Fresnel + vec3 kD = vec3(1.0) - F; + kD *= 1.0 - metallic; + + // add to outgoing radiance Lo + float NdotL = max(dot(N, L), 0.0); + Lo += (kD * albedo / PI + specular) * radiance * NdotL; + } - for (int i = 0; i < ${pl}; i++) { - vec3 pointLightDir = normalize(pos - pointLightPos[i]); - float angle = max(dot(-pointLightDir, new_normal),0.0); - vec3 reflection = reflect(-pointLightDir, new_normal); - float specular = pow(max(dot(reflection, lookDir),0.0), (0.0001+map_Ns)); + // ambient lighting + vec3 kS = fresnelSchlickRoughness(max(dot(N, V), 0.0), F0, r); + vec3 kD = vec3(1.0) - metallic; - Ld += map_Kd * pointLightInt[i] * angle * pointLightColor[i]; - Ls += map_Ks * pointLightInt[i] * specular * angle * pointLightColor[i]; - La += map_Ka * pointLightInt[i] * (1.0-angle) * pointLightAmb[i] * pointLightColor[i]; - } + vec3 ambient = (kD * irradiance * albedo) * ao; - vec3 vLighting = Ld + Ls + La + Le; - vec3 c = vLighting; + vec3 c = ambient + Lo + Le; - if (sGamma == 1.0) { - c.r = pow(c.r, (1.0/gammaY)); - c.g = pow(c.g, (1.0/gammaY)); - c.b = pow(c.b, (1.0/gammaY)); + if (sHDR == 1.0) { + c = c / (c + vec3(1.0)); } - - if (sReinhard == 1.0) { + + if (sReinhard == 1.0) { float l_old = 0.2126*c.r+0.7152*c.g+0.0722*c.b; float numerator = l_old * (1.0 + (l_old / (whiteM*whiteM))); float l_new = numerator / (1.0 + l_old); c = c * (l_new / l_old); } + if (sGamma == 1.0) { + c = pow(c, vec3(1.0/gammaY)); + } + if (sNormals == 1.0) { c = new_normal; } + if (sAO == 1.0) { + c = vec3(ao); + } + outputColor = vec4(c*map_d, map_d); }`; } @@ -219,14 +414,20 @@ App.Art.Engine = class { this.buffers.models[m] = new class {}; } - // init background buffers - this.buffers.backgroundPositionBuffer = this.gl.createBuffer(); - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.backgroundPositionBuffer); - this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, 1, 1, -1, 1]), this.gl.STATIC_DRAW); + // init quad buffers + this.buffers.quadPositionBuffer = this.gl.createBuffer(); + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.quadPositionBuffer); + this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([-1, 1, -1, -1, 1, 1, 1, -1]), this.gl.STATIC_DRAW); - this.buffers.backgroundIndexBuffer = this.gl.createBuffer(); - this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.buffers.backgroundIndexBuffer); - this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 0, 2, 3]), this.gl.STATIC_DRAW); + this.buffers.quadTextureBuffer = this.gl.createBuffer(); + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.quadTextureBuffer); + this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([0, 1, 0, 0, 1, 1, 1, 0]), this.gl.STATIC_DRAW); + + this.buffers.quadIndexBuffer = this.gl.createBuffer(); + this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.buffers.quadIndexBuffer); + this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 1, 2, 3]), this.gl.STATIC_DRAW); + + this.initFrameBuffers(this.buffers, 1200, 1500); // init model buffers for (let m=0; m < this.buffers.models.length; m++) { @@ -236,7 +437,6 @@ App.Art.Engine = class { modelBuffers.verticesPositionBuffer = []; modelBuffers.verticesNormalBuffer = []; modelBuffers.verticesTextureCoordBuffer = []; - modelBuffers.verticesTangentBuffer = []; modelBuffers.vertexCount = []; modelBuffers.verticesMorphBuffer = []; modelBuffers.verticesNormalMorphBuffer = []; @@ -257,10 +457,6 @@ App.Art.Engine = class { this.gl.bindBuffer(this.gl.ARRAY_BUFFER, modelBuffers.verticesTextureCoordBuffer[i]); this.gl.bufferData(this.gl.ARRAY_BUFFER, this.base64ToFloat(modelData.figures[i].texts), this.gl.STATIC_DRAW); - modelBuffers.verticesTangentBuffer[i] = this.gl.createBuffer(); - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, modelBuffers.verticesTangentBuffer[i]); - this.gl.bufferData(this.gl.ARRAY_BUFFER, this.base64ToFloat(modelData.figures[i].tans), this.gl.STATIC_DRAW); - // return dummy morph modelBuffers.verticesMorphBuffer[i] = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, modelBuffers.verticesMorphBuffer[i]); @@ -283,6 +479,123 @@ App.Art.Engine = class { } } + updateResolution(screenWidth, screenHeight) { + this.gl.bindTexture(this.gl.TEXTURE_2D, this.buffers.gPosition); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA32F, screenWidth, screenHeight, 0, this.gl.RGBA, this.gl.FLOAT, null); + + this.gl.bindTexture(this.gl.TEXTURE_2D, this.buffers.gNormal); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA16F, screenWidth, screenHeight, 0, this.gl.RGBA, this.gl.FLOAT, null); + + this.gl.bindTexture(this.gl.TEXTURE_2D, this.buffers.gAlpha); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.R16F, screenWidth, screenHeight, 0, this.gl.RED, this.gl.FLOAT, null); + + this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, this.buffers.rboDepth); + this.gl.renderbufferStorage(this.gl.RENDERBUFFER, this.gl.DEPTH_COMPONENT16, screenWidth, screenHeight); + + this.gl.bindTexture(this.gl.TEXTURE_2D, this.buffers.ssaoColorBuffer); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.R16F, screenWidth, screenHeight, 0, this.gl.RED, this.gl.FLOAT, null); + + this.gl.bindTexture(this.gl.TEXTURE_2D, this.buffers.ssaoColorBufferBlur); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.R16F, screenWidth, screenHeight, 0, this.gl.RED, this.gl.FLOAT, null); + + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null); + } + + initFrameBuffers(buffers, screenWidth, screenHeight) { + // configure g-buffer framebuffer + buffers.gBuffer = this.gl.createFramebuffer(); + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, buffers.gBuffer); + + // position color buffer + buffers.gPosition = this.gl.createTexture(); + this.gl.bindTexture(this.gl.TEXTURE_2D, buffers.gPosition); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA32F, screenWidth, screenHeight, 0, this.gl.RGBA, this.gl.FLOAT, null); + this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, buffers.gPosition, 0); + // normal color buffer + buffers.gNormal = this.gl.createTexture(); + this.gl.bindTexture(this.gl.TEXTURE_2D, buffers.gNormal); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA16F, screenWidth, screenHeight, 0, this.gl.RGBA, this.gl.FLOAT, null); + this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT1, this.gl.TEXTURE_2D, buffers.gNormal, 0); + // alpha buffer + buffers.gAlpha = this.gl.createTexture(); + this.gl.bindTexture(this.gl.TEXTURE_2D, buffers.gAlpha); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.R16F, screenWidth, screenHeight, 0, this.gl.RED, this.gl.FLOAT, null); + this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT2, this.gl.TEXTURE_2D, buffers.gAlpha, 0); + + let attachments = []; + attachments[0] = this.gl.COLOR_ATTACHMENT0; + attachments[1] = this.gl.COLOR_ATTACHMENT1; + attachments[2] = this.gl.COLOR_ATTACHMENT2; + this.gl.drawBuffers(attachments); + + // create and attach depth buffer + buffers.rboDepth = this.gl.createRenderbuffer(); + this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, buffers.rboDepth); + this.gl.renderbufferStorage(this.gl.RENDERBUFFER, this.gl.DEPTH_COMPONENT16, screenWidth, screenHeight); + this.gl.framebufferRenderbuffer(this.gl.FRAMEBUFFER, this.gl.DEPTH_ATTACHMENT, this.gl.RENDERBUFFER, buffers.rboDepth); + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null); + + // SSAO color buffer + buffers.ssaoColorBuffer = this.gl.createTexture(); + this.gl.bindTexture(this.gl.TEXTURE_2D, buffers.ssaoColorBuffer); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.R16F, screenWidth, screenHeight, 0, this.gl.RED, this.gl.FLOAT, null); + + buffers.ssaoFBO = this.gl.createFramebuffer(); + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, buffers.ssaoFBO); + this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, buffers.ssaoColorBuffer, 0); + + // SSAO blur buffer + buffers.ssaoColorBufferBlur = this.gl.createTexture(); + this.gl.bindTexture(this.gl.TEXTURE_2D, buffers.ssaoColorBufferBlur); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.R16F, screenWidth, screenHeight, 0, this.gl.RED, this.gl.FLOAT, null); + + buffers.ssaoBlurFBO = this.gl.createFramebuffer(); + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, buffers.ssaoBlurFBO); + this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, buffers.ssaoColorBufferBlur, 0); + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null); + + // generate sample kernel + this.buffers.ssaoKernel = []; + for (let i = 0; i < 32; i++) { + let sample = [Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0, Math.random()]; + sample = this.vectorNormalize(sample); + sample = this.vectorMul(sample, Math.random()); + let scale = i / 32.0; + + // scale samples s.t. they're more aligned to center of kernel + scale = this.lerp(0.1, 1.0, scale * scale); + sample = this.vectorMul(sample, scale); + this.buffers.ssaoKernel.push(sample); + } + + // generate noise texture + let ssaoNoise = []; + for (let i = 0; i < 9; i++) { + let noise = [Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0, 0.0, 1.0]; + ssaoNoise = ssaoNoise.concat(noise); + } + + buffers.noiseTexture = this.gl.createTexture(); + this.gl.bindTexture(this.gl.TEXTURE_2D, buffers.noiseTexture); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.REPEAT); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.REPEAT); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA16F, 3, 3, 0, this.gl.RGBA, this.gl.FLOAT, new Float32Array(ssaoNoise)); + } + initMorphs(modelBuffers, modelData, dir) { window.sceneBlocks = {}; // automatically populated during loading of morphs @@ -382,7 +695,6 @@ App.Art.Engine = class { if(typeof V.setTextureResolution !== "undefined") { textureSize = V.setTextureResolution; } - if (width > textureSize || height > textureSize) { if (width > textureSize) { width = textureSize; @@ -423,65 +735,82 @@ App.Art.Engine = class { initShaders(sceneParams) { // compile shaders - let vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER); - this.gl.shaderSource(vertexShader, this.getVsSource()); - this.gl.compileShader(vertexShader); - - let fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); - this.gl.shaderSource(fragmentShader, this.getFsSource(sceneParams.directionalLights.length, sceneParams.pointLights.length)); - this.gl.compileShader(fragmentShader); - - this.shaderProgram = this.gl.createProgram(); - this.gl.attachShader(this.shaderProgram, vertexShader); - this.gl.attachShader(this.shaderProgram, fragmentShader); - this.gl.linkProgram(this.shaderProgram); - - let vertexShaderBg = this.gl.createShader(this.gl.VERTEX_SHADER); - this.gl.shaderSource(vertexShaderBg, this.getVsSourceBg()); - this.gl.compileShader(vertexShaderBg); - - let fragmentShaderBg = this.gl.createShader(this.gl.FRAGMENT_SHADER); - this.gl.shaderSource(fragmentShaderBg, this.getFsSourceBg()); - this.gl.compileShader(fragmentShaderBg); - - this.shaderProgramBg = this.gl.createProgram(); - this.gl.attachShader(this.shaderProgramBg, vertexShaderBg); - this.gl.attachShader(this.shaderProgramBg, fragmentShaderBg); - this.gl.linkProgram(this.shaderProgramBg); - - this.gl.useProgram(this.shaderProgram); + let vertexShaderGeometry = this.gl.createShader(this.gl.VERTEX_SHADER); + this.gl.shaderSource(vertexShaderGeometry, this.getVsSourceGeometry()); + this.gl.compileShader(vertexShaderGeometry); + + let fragmentShaderGeometry = this.gl.createShader(this.gl.FRAGMENT_SHADER); + this.gl.shaderSource(fragmentShaderGeometry, this.getFsSourceGeometry()); + this.gl.compileShader(fragmentShaderGeometry); + + let vertexShaderQuad = this.gl.createShader(this.gl.VERTEX_SHADER); + this.gl.shaderSource(vertexShaderQuad, this.getVsSourceQuad()); + this.gl.compileShader(vertexShaderQuad); + + let fragmentShaderSSAO = this.gl.createShader(this.gl.FRAGMENT_SHADER); + this.gl.shaderSource(fragmentShaderSSAO, this.getFsSourceSSAO()); + this.gl.compileShader(fragmentShaderSSAO); + + let fragmentShaderSSAOBlur = this.gl.createShader(this.gl.FRAGMENT_SHADER); + this.gl.shaderSource(fragmentShaderSSAOBlur, this.getFsSourceSSAOBlur()); + this.gl.compileShader(fragmentShaderSSAOBlur); + + let fragmentShaderForwardPass = this.gl.createShader(this.gl.FRAGMENT_SHADER); + this.gl.shaderSource(fragmentShaderForwardPass, this.getFsSourceForwardPass(sceneParams.directionalLights.length, sceneParams.pointLights.length)); + this.gl.compileShader(fragmentShaderForwardPass); + + this.shaderProgramGeometry = this.gl.createProgram(); + this.gl.attachShader(this.shaderProgramGeometry, vertexShaderGeometry); + this.gl.attachShader(this.shaderProgramGeometry, fragmentShaderGeometry); + this.gl.linkProgram(this.shaderProgramGeometry); + + this.shaderProgramSSAO = this.gl.createProgram(); + this.gl.attachShader(this.shaderProgramSSAO, vertexShaderQuad); + this.gl.attachShader(this.shaderProgramSSAO, fragmentShaderSSAO); + this.gl.linkProgram(this.shaderProgramSSAO); + + this.shaderProgramSSAOBlur = this.gl.createProgram(); + this.gl.attachShader(this.shaderProgramSSAOBlur, vertexShaderQuad); + this.gl.attachShader(this.shaderProgramSSAOBlur, fragmentShaderSSAOBlur); + this.gl.linkProgram(this.shaderProgramSSAOBlur); + + this.shaderProgramForwardPass = this.gl.createProgram(); + this.gl.attachShader(this.shaderProgramForwardPass, vertexShaderGeometry); + this.gl.attachShader(this.shaderProgramForwardPass, fragmentShaderForwardPass); + this.gl.linkProgram(this.shaderProgramForwardPass); // enable vertex attributes - this.backgroundPositionAttribute = this.gl.getAttribLocation(this.shaderProgramBg, "vertexPosition"); - this.gl.enableVertexAttribArray(this.backgroundPositionAttribute); - this.vertexPositionAttribute = this.gl.getAttribLocation(this.shaderProgram, "vertexPosition"); + this.vertexPositionAttribute = this.gl.getAttribLocation(this.shaderProgramGeometry, "vertexPosition"); this.gl.enableVertexAttribArray(this.vertexPositionAttribute); - this.textureCoordAttribute = this.gl.getAttribLocation(this.shaderProgram, "textureCoordinate"); + this.textureCoordAttribute = this.gl.getAttribLocation(this.shaderProgramGeometry, "textureCoordinate"); this.gl.enableVertexAttribArray(this.textureCoordAttribute); - this.vertexNormalAttribute = this.gl.getAttribLocation(this.shaderProgram, "vertexNormal"); + this.vertexNormalAttribute = this.gl.getAttribLocation(this.shaderProgramGeometry, "vertexNormal"); this.gl.enableVertexAttribArray(this.vertexNormalAttribute); - this.vertexTangentAttribute = this.gl.getAttribLocation(this.shaderProgram, "vertexTangent"); - this.gl.enableVertexAttribArray(this.vertexTangentAttribute); - - this.vertexNormalMorphAttribute = this.gl.getAttribLocation(this.shaderProgram, "vertexNormalMorph"); + this.vertexNormalMorphAttribute = this.gl.getAttribLocation(this.shaderProgramGeometry, "vertexNormalMorph"); this.gl.enableVertexAttribArray(this.vertexNormalMorphAttribute); - this.vertexPositionMorphAttribute = this.gl.getAttribLocation(this.shaderProgram, "vertexPositionMorph"); + this.vertexPositionMorphAttribute = this.gl.getAttribLocation(this.shaderProgramGeometry, "vertexPositionMorph"); this.gl.enableVertexAttribArray(this.vertexPositionMorphAttribute); + + this.quadPositionAttribute = this.gl.getAttribLocation(this.shaderProgramSSAO, "vertexPosition"); + this.gl.enableVertexAttribArray(this.quadPositionAttribute); + + this.quadTextureAttribute = this.gl.getAttribLocation(this.shaderProgramSSAO, "textureCoordinate"); + this.gl.enableVertexAttribArray(this.quadTextureAttribute); } bind(sceneData, sceneParams, dir) { this.offscreenCanvas = document.createElement("canvas"); this.gl = this.offscreenCanvas.getContext("webgl2", {alpha:true, premultipliedAlpha: true}); + this.gl.getExtension('EXT_color_buffer_float'); this.gl.enable(this.gl.DEPTH_TEST); + this.gl.depthMask(true); this.gl.depthFunc(this.gl.LEQUAL); - this.gl.enable(this.gl.BLEND); - this.gl.blendEquation( this.gl.FUNC_ADD ); this.gl.blendFunc(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA); this.initBuffers(sceneData, dir); @@ -490,10 +819,8 @@ App.Art.Engine = class { } render(sceneParams, canvas) { - // set render resolution - this.offscreenCanvas.width = sceneParams.settings.rwidth; - this.offscreenCanvas.height = sceneParams.settings.rheight; - this.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight); + // update logic + this.update(sceneParams); // set culling if (V.setFaceCulling) { @@ -502,19 +829,32 @@ App.Art.Engine = class { } else { this.gl.disable(this.gl.CULL_FACE); } - - // draw background this.gl.clearColor(0, 0, 0, 0); - this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); - this.gl.useProgram(this.shaderProgramBg); - if (sceneParams.background.visible) { - this.drawBackground(sceneParams); - } // draw scene - this.gl.clear(this.gl.DEPTH_BUFFER_BIT); - this.gl.useProgram(this.shaderProgram); - this.drawScene(sceneParams); + this.gl.disable(this.gl.BLEND); + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.buffers.gBuffer); + this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); + this.gl.useProgram(this.shaderProgramGeometry); + this.drawGeometry(sceneParams); + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null); + this.gl.enable(this.gl.BLEND); + + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.buffers.ssaoFBO); + this.gl.clear(this.gl.COLOR_BUFFER_BIT); + this.gl.useProgram(this.shaderProgramSSAO); + this.drawSSAO(sceneParams); + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null); + + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.buffers.ssaoBlurFBO); + this.gl.clear(this.gl.COLOR_BUFFER_BIT); + this.gl.useProgram(this.shaderProgramSSAOBlur); + this.drawSSAOBlur(sceneParams); + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null); + + this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); + this.gl.useProgram(this.shaderProgramForwardPass); + this.drawForwardPass(sceneParams); // clone from offscreen to real canvas let ctx = canvas.getContext('2d', {alpha:true}); @@ -522,21 +862,13 @@ App.Art.Engine = class { ctx.drawImage(this.gl.canvas, 0, 0, canvas.width, canvas.height); } - drawBackground(sceneParams) { - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramBg, "textSampler"), 0); - this.gl.uniform4fv(this.gl.getUniformLocation(this.shaderProgramBg, "backgroundColor"), sceneParams.background.color); - - this.gl.activeTexture(this.gl.TEXTURE0); - this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures[sceneParams.background.filename]); - - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.backgroundPositionBuffer); - this.gl.vertexAttribPointer(this.backgroundPositionAttribute, 2, this.gl.FLOAT, false, 0, 0); - - this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.buffers.backgroundIndexBuffer); - this.gl.drawElements(this.gl.TRIANGLES, 6, this.gl.UNSIGNED_SHORT, 0); - } + update(sceneParams) { + // set render resolution + this.offscreenCanvas.width = sceneParams.settings.rwidth; + this.offscreenCanvas.height = sceneParams.settings.rheight; + this.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight); + this.updateResolution(sceneParams.settings.rwidth, sceneParams.settings.rheight); - drawScene(sceneParams) { // create camera let camRotX = this.degreeToRad(-sceneParams.camera.xr); let camRotY = this.degreeToRad(-sceneParams.camera.yr); @@ -553,45 +885,192 @@ App.Art.Engine = class { // create scene transforms let matProj = this.matrixMakeProjection(sceneParams.camera.fov, sceneParams.settings.rheight/sceneParams.settings.rwidth, sceneParams.camera.fnear, sceneParams.camera.ffar); let matView = this.matrixInverse(matCamera); + this.buffers.matProj = matProj; + this.buffers.matView = matView; - // set scene uniforms - let sColorBurn = true; - if(typeof V.setColorBurn !== "undefined") { - sColorBurn = V.setColorBurn; + for (let m=0; m < this.buffers.models.length; m++) { + let modelBuffers = this.buffers.models[m]; + let modelParams = sceneParams.models[m]; + + if(!modelParams.visible) { + continue; + } + + // create model transforms + this.applyMorphs(modelParams, modelBuffers); + + let matRot = this.matrixMakeRotation(this.degreeToRad(modelParams.transform.xr), this.degreeToRad(modelParams.transform.yr), this.degreeToRad(modelParams.transform.zr)); + let matTrans = this.matrixMakeTranslation(modelParams.transform.x, modelParams.transform.y, modelParams.transform.z); + let matScale = this.matrixMakeScaling( modelParams.transform.scale); + let matModel = this.matrixMulMatrix4(matScale, this.matrixMulMatrix4(matTrans, matRot)); + let matModelView = this.matrixMulMatrix4(matModel, matView); + let matModelViewProjection = this.matrixMulMatrix4(matModelView, matProj); + let matNormal = this.matrixTranspose(this.matrixInverse(matModelView)); + + modelBuffers.matModel = matModel; + modelBuffers.matModelView = matModelView; + modelBuffers.matModelViewProjection = matModelViewProjection; + modelBuffers.matNormal = matNormal; + } + } + + drawGeometry(sceneParams) { + // process each model in the scene + for (let m=0; m < this.buffers.models.length; m++) { + let modelBuffers = this.buffers.models[m]; + let modelParams = sceneParams.models[m]; + + if(!modelParams.visible) { + continue; + } + + // set model uniform + this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgramGeometry, "matModelViewProjection"), false, new Float32Array(this.matrixFlatten(modelBuffers.matModelViewProjection))); + this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgramGeometry, "matModelView"), false, new Float32Array(this.matrixFlatten(modelBuffers.matModelView))); + this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgramGeometry, "matModel"), false, new Float32Array(this.matrixFlatten(modelBuffers.matModel))); + this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgramGeometry, "matNormal"), false, new Float32Array(this.matrixFlatten(modelBuffers.matNormal))); + + for (let i=0, count=0; i < modelParams.figures.length; i++) { + if(!modelParams.figures[i].visible) { + count += modelParams.figures[i].surfaces.length; + continue; + } + + // bind vertex buffers per figure + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, modelBuffers.verticesPositionBuffer[i]); + this.gl.vertexAttribPointer(this.vertexPositionAttribute, 3, this.gl.FLOAT, false, 0, 0); + + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, modelBuffers.verticesTextureCoordBuffer[i]); + this.gl.vertexAttribPointer(this.textureCoordAttribute, 2, this.gl.FLOAT, false, 0, 0); + + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, modelBuffers.verticesNormalBuffer[i]); + this.gl.vertexAttribPointer(this.vertexNormalAttribute, 3, this.gl.FLOAT, false, 0, 0); + + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, modelBuffers.verticesMorphBuffer[i]); + this.gl.vertexAttribPointer(this.vertexPositionMorphAttribute, 3, this.gl.FLOAT, false, 0, 0); + + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, modelBuffers.verticesNormalMorphBuffer[i]); + this.gl.vertexAttribPointer(this.vertexNormalMorphAttribute, 3, this.gl.FLOAT, false, 0, 0); + + // bind materials per surface and set uniforms + for (let j=0; j < modelParams.figures[i].surfaces.length; j++, count++) { + let visible = modelParams.figures[i].surfaces[j].visible; + + for (let h=0; h < modelParams.figures[i].surfaces[j].matIds.length; h++) { + let matId = modelParams.figures[i].surfaces[j].matIds[h]; + let matIdx = sceneParams.materials.map(e => e.matId).indexOf(matId); + if (matIdx === -1) { + continue; + } + let mat = sceneParams.materials[matIdx]; + + if (mat.d > 0 && visible) { + this.gl.activeTexture(this.gl.TEXTURE0); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures[mat.map_D]); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramGeometry, "alpha"), 0); + + this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, modelBuffers.verticesIndexBuffer[count]); + this.gl.drawElements(this.gl.TRIANGLES, modelBuffers.indexSizes[count], this.gl.UNSIGNED_INT, 0); + } + } + } + } } + } + + drawSSAO(sceneParams) { + this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgramSSAO, "projection"), false, new Float32Array(this.matrixFlatten(this.buffers.matProj))); + this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgramSSAO, "view"), false, new Float32Array(this.matrixFlatten(this.buffers.matView))); + + for (let i = 0; i < 32; ++i) { + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgramSSAO, "samples[" + i + "]"), this.buffers.ssaoKernel[i]); + } + + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramSSAO, "radius"), sceneParams.ssao.radius); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramSSAO, "bias"), sceneParams.ssao.bias); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramSSAO, "scale"), sceneParams.ssao.scale); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "sNormals"), sceneParams.settings.normals); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "sAmbient"), sceneParams.settings.ambient); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "sDiffuse"), sceneParams.settings.diffuse); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "sSpecular"), sceneParams.settings.specular); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "sEmission"), sceneParams.settings.emission); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "sNormal"), sceneParams.settings.normal); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "sAlpha"), sceneParams.settings.alpha); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "sReinhard"), sceneParams.settings.reinhard); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "sGamma"), sceneParams.settings.gamma); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "whiteM"), sceneParams.settings.whiteM); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "gammaY"), sceneParams.settings.gammaY); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "sColorBurn"), Number(sColorBurn)); + this.gl.activeTexture(this.gl.TEXTURE0); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.buffers.gPosition); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramSSAO, "gPosition"), 0); + + this.gl.activeTexture(this.gl.TEXTURE1); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.buffers.gNormal); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramSSAO, "gNormal"), 1); + + this.gl.activeTexture(this.gl.TEXTURE2); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.buffers.gAlpha); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramSSAO, "gAlpha"), 2); + + this.gl.activeTexture(this.gl.TEXTURE3); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.buffers.noiseTexture); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramSSAO, "texNoise"), 3); + + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.quadPositionBuffer); + this.gl.vertexAttribPointer(this.quadPositionAttribute, 2, this.gl.FLOAT, false, 0, 0); + + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.quadTextureBuffer); + this.gl.vertexAttribPointer(this.quadTextureAttribute, 2, this.gl.FLOAT, false, 0, 0); + + this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.buffers.quadIndexBuffer); + this.gl.drawElements(this.gl.TRIANGLES, 6, this.gl.UNSIGNED_SHORT, 0); + } + + drawSSAOBlur(sceneParams) { + this.gl.activeTexture(this.gl.TEXTURE0); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.buffers.ssaoColorBuffer); + + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramSSAOBlur, "blur"), sceneParams.ssao.blur); + + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.quadPositionBuffer); + this.gl.vertexAttribPointer(this.quadPositionAttribute, 2, this.gl.FLOAT, false, 0, 0); + + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffers.quadTextureBuffer); + this.gl.vertexAttribPointer(this.quadTextureAttribute, 2, this.gl.FLOAT, false, 0, 0); + + this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.buffers.quadIndexBuffer); + this.gl.drawElements(this.gl.TRIANGLES, 6, this.gl.UNSIGNED_SHORT, 0); + } + + drawForwardPass(sceneParams) { + // set scene uniforms + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "sNormals"), sceneParams.settings.normals); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "sAO"), sceneParams.settings.ao); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "sSSAO"), sceneParams.settings.ssao); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "sAmbient"), sceneParams.settings.ambient); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "sDiffuse"), sceneParams.settings.diffuse); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "sSpecular"), sceneParams.settings.specular); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "sEmission"), sceneParams.settings.emission); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "sNormal"), sceneParams.settings.normal); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "sAlpha"), sceneParams.settings.alpha); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "sReinhard"), sceneParams.settings.reinhard); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "sGamma"), sceneParams.settings.gamma); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "whiteM"), sceneParams.settings.whiteM); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "gammaY"), sceneParams.settings.gammaY); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "sHDR"), sceneParams.settings.hdr); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "roughness"), sceneParams.pbr.roughness); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "metallic"), sceneParams.pbr.metallic); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "albedoInt"), sceneParams.pbr.albedo); + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "fresnel"), sceneParams.pbr.fresnel); + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "irradiance"), sceneParams.pbr.irradiance); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "ssaoInt"), sceneParams.ssao.intensity); for (let i = 0; i < sceneParams.directionalLights.length; i++) { let lightVect = this.polarToCart(this.degreeToRad(sceneParams.directionalLights[i].yr), this.degreeToRad(sceneParams.directionalLights[i].xr)); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "lightAmb[" + i + "]"), sceneParams.directionalLights[i].ambient); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "lightInt[" + i + "]"), sceneParams.directionalLights[i].intensity); - this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "lightColor[" + i + "]"), sceneParams.directionalLights[i].color); - this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "lightVect[" + i + "]"), lightVect); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "lightAmb[" + i + "]"), sceneParams.directionalLights[i].ambient); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "lightInt[" + i + "]"), sceneParams.directionalLights[i].intensity); + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "lightColor[" + i + "]"), sceneParams.directionalLights[i].color); + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "lightVect[" + i + "]"), lightVect); } for (let i = 0; i < sceneParams.pointLights.length; i++) { - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "pointLightAmb[" + i + "]"), sceneParams.pointLights[i].ambient); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "pointLightInt[" + i + "]"), sceneParams.pointLights[i].intensity); - this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "pointLightColor[" + i + "]"), sceneParams.pointLights[i].color); - this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "pointLightPos[" + i + "]"), [sceneParams.pointLights[i].x, sceneParams.pointLights[i].y, sceneParams.pointLights[i].z]); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "pointLightAmb[" + i + "]"), sceneParams.pointLights[i].ambient); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "pointLightInt[" + i + "]"), sceneParams.pointLights[i].intensity); + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "pointLightColor[" + i + "]"), sceneParams.pointLights[i].color); + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "pointLightPos[" + i + "]"), [sceneParams.pointLights[i].x, sceneParams.pointLights[i].y, sceneParams.pointLights[i].z]); } - this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "lookDir"), lookDir); - - this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgram, "matProj"), false, new Float32Array(this.matrixFlatten(matProj))); - this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgram, "matView"), false, new Float32Array(this.matrixFlatten(matView))); + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "cameraPos"), [sceneParams.camera.x, sceneParams.camera.y, sceneParams.camera.z]); // process each model in the scene for (let m=0; m < this.buffers.models.length; m++) { @@ -602,17 +1081,11 @@ App.Art.Engine = class { continue; } - // create model transforms - this.applyMorphs(modelParams, modelBuffers); - - let matRot = this.matrixMakeRotation(this.degreeToRad(modelParams.transform.xr), this.degreeToRad(modelParams.transform.yr), this.degreeToRad(modelParams.transform.zr)); - let matTrans = this.matrixMakeTranslation(modelParams.transform.x, modelParams.transform.y, modelParams.transform.z); - let matScale = this.matrixMakeScaling( modelParams.transform.scale); - - // set model uniforms - this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgram, "matTrans"), false, new Float32Array(this.matrixFlatten(matTrans))); - this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgram, "matScale"), false, new Float32Array(this.matrixFlatten(matScale))); - this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgram, "matRot"), false, new Float32Array(this.matrixFlatten(matRot))); + // set model uniform + this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "matModelViewProjection"), false, new Float32Array(this.matrixFlatten(modelBuffers.matModelViewProjection))); + this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "matModelView"), false, new Float32Array(this.matrixFlatten(modelBuffers.matModelView))); + this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "matModel"), false, new Float32Array(this.matrixFlatten(modelBuffers.matModel))); + this.gl.uniformMatrix4fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "matNormal"), false, new Float32Array(this.matrixFlatten(modelBuffers.matNormal))); for (let i=0, count=0; i < modelParams.figures.length; i++) { if(!modelParams.figures[i].visible) { @@ -630,9 +1103,6 @@ App.Art.Engine = class { this.gl.bindBuffer(this.gl.ARRAY_BUFFER, modelBuffers.verticesNormalBuffer[i]); this.gl.vertexAttribPointer(this.vertexNormalAttribute, 3, this.gl.FLOAT, false, 0, 0); - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, modelBuffers.verticesTangentBuffer[i]); - this.gl.vertexAttribPointer(this.vertexTangentAttribute, 3, this.gl.FLOAT, false, 0, 0); - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, modelBuffers.verticesMorphBuffer[i]); this.gl.vertexAttribPointer(this.vertexPositionMorphAttribute, 3, this.gl.FLOAT, false, 0, 0); @@ -653,39 +1123,39 @@ App.Art.Engine = class { if (mat.d > 0 && visible) { this.gl.activeTexture(this.gl.TEXTURE0); - this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures[mat.map_Ka]); - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[0]"), 0); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.buffers.ssaoColorBufferBlur); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramForwardPass, "textSampler[0]"), 0); this.gl.activeTexture(this.gl.TEXTURE1); this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures[mat.map_Kd]); - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[1]"), 1); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramForwardPass, "textSampler[1]"), 1); this.gl.activeTexture(this.gl.TEXTURE2); this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures[mat.map_Ks]); - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[2]"), 2); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramForwardPass, "textSampler[2]"), 2); this.gl.activeTexture(this.gl.TEXTURE3); this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures[mat.map_Ns]); - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[3]"), 3); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramForwardPass, "textSampler[3]"), 3); this.gl.activeTexture(this.gl.TEXTURE4); this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures[mat.map_D]); - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[4]"), 4); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramForwardPass, "textSampler[4]"), 4); this.gl.activeTexture(this.gl.TEXTURE5); this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures[mat.map_Kn]); - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[5]"), 5); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramForwardPass, "textSampler[5]"), 5); this.gl.activeTexture(this.gl.TEXTURE6); this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures[mat.map_Ke]); - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[6]"), 6); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgramForwardPass, "textSampler[6]"), 6); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "d"), mat.d); - this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "Ka"), mat.Ka); - this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "Kd"), mat.Kd); - this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "Ks"), mat.Ks); - this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "Ke"), mat.Ke); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "Ns"), mat.Ns); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "d"), mat.d); + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "Ka"), mat.Ka); + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "Kd"), mat.Kd); + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "Ks"), mat.Ks); + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgramForwardPass, "Ke"), mat.Ke); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgramForwardPass, "Ns"), mat.Ns); // draw materials this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, modelBuffers.verticesIndexBuffer[count]); @@ -885,6 +1355,25 @@ App.Art.Engine = class { m1[2][0] * m2[0][2] + m1[2][1] * m2[1][2] + m1[2][2] * m2[2][2]]]; } + matrixMulMatrix4(m1, m2) { + return [[m1[0][0] * m2[0][0] + m1[0][1] * m2[1][0] + m1[0][2] * m2[2][0] + m1[0][3] * m2[3][0], + m1[0][0] * m2[0][1] + m1[0][1] * m2[1][1] + m1[0][2] * m2[2][1] + m1[0][3] * m2[3][1], + m1[0][0] * m2[0][2] + m1[0][1] * m2[1][2] + m1[0][2] * m2[2][2] + m1[0][3] * m2[3][2], + m1[0][0] * m2[0][3] + m1[0][1] * m2[1][3] + m1[0][2] * m2[2][3] + m1[0][3] * m2[3][3]], + [m1[1][0] * m2[0][0] + m1[1][1] * m2[1][0] + m1[1][2] * m2[2][0] + m1[1][3] * m2[3][0], + m1[1][0] * m2[0][1] + m1[1][1] * m2[1][1] + m1[1][2] * m2[2][1] + m1[1][3] * m2[3][1], + m1[1][0] * m2[0][2] + m1[1][1] * m2[1][2] + m1[1][2] * m2[2][2] + m1[1][3] * m2[3][2], + m1[1][0] * m2[0][3] + m1[1][1] * m2[1][3] + m1[1][2] * m2[2][3] + m1[1][3] * m2[3][3]], + [m1[2][0] * m2[0][0] + m1[2][1] * m2[1][0] + m1[2][2] * m2[2][0] + m1[2][3] * m2[3][0], + m1[2][0] * m2[0][1] + m1[2][1] * m2[1][1] + m1[2][2] * m2[2][1] + m1[2][3] * m2[3][1], + m1[2][0] * m2[0][2] + m1[2][1] * m2[1][2] + m1[2][2] * m2[2][2] + m1[2][3] * m2[3][2], + m1[2][0] * m2[0][3] + m1[2][1] * m2[1][3] + m1[2][2] * m2[2][3] + m1[2][3] * m2[3][3]], + [m1[3][0] * m2[0][0] + m1[3][1] * m2[1][0] + m1[3][2] * m2[2][0] + m1[3][3] * m2[3][0], + m1[3][0] * m2[0][1] + m1[3][1] * m2[1][1] + m1[3][2] * m2[2][1] + m1[3][3] * m2[3][1], + m1[3][0] * m2[0][2] + m1[3][1] * m2[1][2] + m1[3][2] * m2[2][2] + m1[3][3] * m2[3][2], + m1[3][0] * m2[0][3] + m1[3][1] * m2[1][3] + m1[3][2] * m2[2][3] + m1[3][3] * m2[3][3]]]; + } + matrixMulVector(m, v) { return [v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0], v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1], @@ -898,11 +1387,21 @@ App.Art.Engine = class { [-(m[3][0]*m[0][0]+m[3][1]*m[0][1]+m[3][2]*m[0][2]), -(m[3][0]*m[1][0]+m[3][1]*m[1][1]+m[3][2]*m[1][2]), -(m[3][0]*m[2][0]+m[3][1]*m[2][1]+m[3][2]*m[2][2]), 1]]; } + matrixTranspose(m) { + return [[m[0][0], m[1][0], m[2][0], m[3][0]], + [m[0][1], m[1][1], m[2][1], m[3][1]], + [m[0][2], m[1][2], m[2][2], m[3][2]], + [m[0][3], m[1][3], m[2][3], m[3][3]]]; + } + matrixFlatten(m) { return [m[0][0], m[0][1], m[0][2], m[0][3], m[1][0], m[1][1], m[1][2], m[1][3], m[2][0], m[2][1], m[2][2], m[2][3], m[3][0], m[3][1], m[3][2], m[3][3]]; } -}; + lerp(a, b, f) { + return a + f * (b - a); + } +}; diff --git a/src/art/webgl/ui.js b/src/art/webgl/ui.js index 2f6d90315a4..d58a042a8d7 100644 --- a/src/art/webgl/ui.js +++ b/src/art/webgl/ui.js @@ -186,17 +186,6 @@ App.Art.createWebglUI = function(container, slave, artSize, scene, p) { scene.settings.rwidth = cvs.width * V.setSuperSampling; scene.settings.rheight = cvs.height * V.setSuperSampling; - scene.settings.gamma = false; - scene.settings.gammaY = 1.0; - - scene.settings.reinhard = true; - scene.settings.whiteM = 1.20; - - if (!V.setColorBurn) { - scene.settings.whiteM = 1.30; - scene.directionalLights[0].intensity = 1.15; - } - App.Art.engine.render(scene, cvs); /* diff --git a/src/gui/options/options.js b/src/gui/options/options.js index 3fc9ed2dcd3..02f80bedbde 100644 --- a/src/gui/options/options.js +++ b/src/gui/options/options.js @@ -1128,8 +1128,6 @@ App.UI.artOptions = function() { options.addOption("Texture resolution", "setTextureResolution") .addValue("1024", 1024).on().addValue("2048", 2048).off().addValue("4096", 4096).off() .addComment("Refresh the page to take affect."); - options.addOption("Color burn", "setColorBurn") - .addValue("Enabled", true).on().addValue("Disabled", false).off(); } options.addOption("PA avatar art is", "seeAvatar") -- GitLab