diff --git a/src/art/artJS.js b/src/art/artJS.js index b34793724f7d5fce012d1d9381459fec219d7dce..5d0f98c5686d830e3714ac50ec6836fd06ce944c 100644 --- a/src/art/artJS.js +++ b/src/art/artJS.js @@ -186,7 +186,7 @@ App.Art.webglInitialize = function() { // start Webgl engine, textures are streamed asynchronously App.Art.engine = new App.Art.Engine(); - App.Art.engine.bind(sceneData); + App.Art.engine.bind(sceneData, scene); App.Art.engineReady = true; LoadScreen.unlock(loadLockID); diff --git a/src/art/webgl/engine.js b/src/art/webgl/engine.js index 50a84cb7ff525cefe598be4f74f7eaeeef4e255b..98d1b1f1a0e9dd9d45712e7174e7579334363225 100644 --- a/src/art/webgl/engine.js +++ b/src/art/webgl/engine.js @@ -1,164 +1,175 @@ 'use strict'; App.Art.Engine = class { - constructor() { - this.vsSourceBg = `#version 300 es - precision highp float; + getVsSourceBg() { + return `#version 300 es + precision highp float; - in vec2 vertexPosition; - out vec2 vertexPos; + in vec2 vertexPosition; + out vec2 vertexPos; - void main() { - vertexPos = vertexPosition; - gl_Position = vec4(vertexPosition, 0.0, 1.0); - }`; - - this.fsSourceBg = `#version 300 es - precision highp float; - precision highp sampler2D; - - uniform sampler2D textSampler; - uniform vec4 backgroundColor; - - in vec2 vertexPos; - out vec4 outputColor; - - 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); - }`; - - this.vsSource = `#version 300 es - precision highp float; - - uniform mat4 matView; - uniform mat4 matProj; - uniform mat4 matRot; - uniform mat4 matTrans; - uniform mat4 matScale; - - in vec3 vertexNormal; - in vec3 vertexPosition; - in vec2 textureCoordinate; - in vec3 vertexTangent; - - in vec3 vertexNormalMorph; - in vec3 vertexPositionMorph; - - out vec2 textureCoord; - out vec3 normal; - out mat3 TBN; - - void main() { - gl_Position = matProj * matView * matTrans * matScale * matRot * vec4(vertexPosition + vertexPositionMorph, 1.0) + 0.01; - normal = normalize((matRot * vec4(vertexNormal + vertexNormalMorph, 1.0)).xyz); - - vec3 T = normalize(vec3(matTrans * matRot * vec4(vertexTangent, 0.0))); - vec3 N = normalize(vec3(matTrans * matRot * vec4(vertexNormal + vertexNormalMorph, 0.0))); - T = normalize(T - dot(T, N) * N); - vec3 B = cross(N, T); - TBN = mat3(T, B, N); - - textureCoord = textureCoordinate; - }`; - - this.fsSource = `#version 300 es - precision highp float; - precision highp sampler2D; - - uniform float lightInt; - uniform float lightAmb; - uniform vec3 lightColor; - uniform float whiteM; - uniform float gammaY; - - uniform vec3 Ka; - uniform vec3 Kd; - uniform vec3 Ks; - uniform float d; - uniform float Ns; - - uniform float sNormals; - uniform float sAmbient; - uniform float sDiffuse; - uniform float sSpecular; - uniform float sAlpha; - uniform float sGamma; - uniform float sReinhard; - uniform float sNormal; - - uniform vec3 lightVect; - uniform vec3 lookDir; - - uniform sampler2D textSampler[6]; - - in vec2 textureCoord; - in vec3 normal; - in mat3 TBN; - - out vec4 outputColor; - - void main() { - 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); - float map_Ns = 0.0; - float map_d = 1.0; - float specular = 1.0; - - 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); - } - - float angle = max(dot(-lightVect, new_normal),0.0); - vec3 reflection = reflect(-lightVect, new_normal); - - if (sAmbient == 1.0) - map_Ka = Ka * texture(textSampler[0], textureCoord.st).rgb; - - if (sDiffuse == 1.0) - map_Kd = Kd * texture(textSampler[1], textureCoord.st).rgb; - - if (sSpecular == 1.0) { - map_Ks = Ks * texture(textSampler[2], textureCoord.st).rgb; - map_Ns = Ns * texture(textSampler[3], textureCoord.st).r; - specular = pow(max(dot(reflection, lookDir),0.0), (0.0001+map_Ns)); - } - - if (sAlpha == 1.0) - map_d = d * texture(textSampler[4], textureCoord.st).r; - - vec3 Ld = map_Kd * lightInt * angle * lightColor; - vec3 Ls = map_Ks * specular * lightColor; - vec3 La = map_Ka * lightAmb * lightColor; - - vec3 vLighting = Ld + Ls + La; - vec3 c = map_Kd * vLighting; - - 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.r = pow(c.r, (1.0/gammaY)); - c.g = pow(c.g, (1.0/gammaY)); - c.b = pow(c.b, (1.0/gammaY)); - } - - if (sNormals == 1.0) { - c = new_normal; - } - - outputColor = vec4(c*map_d, map_d); - }`; - } + void main() { + vertexPos = vertexPosition; + gl_Position = vec4(vertexPosition, 0.0, 1.0); + }` + } + + getFsSourceBg() { + return `#version 300 es + precision highp float; + precision highp sampler2D; + + uniform sampler2D textSampler; + uniform vec4 backgroundColor; + + in vec2 vertexPos; + out vec4 outputColor; + + 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); + }` + } + + getVsSource() { + return `#version 300 es + precision highp float; + + uniform mat4 matView; + uniform mat4 matProj; + uniform mat4 matRot; + uniform mat4 matTrans; + uniform mat4 matScale; + + in vec3 vertexNormal; + in vec3 vertexPosition; + in vec2 textureCoordinate; + in vec3 vertexTangent; + + in vec3 vertexNormalMorph; + in vec3 vertexPositionMorph; + + out vec2 textureCoord; + out vec3 normal; + out mat3 TBN; + + void main() { + gl_Position = matProj * matView * matTrans * matScale * matRot * vec4(vertexPosition + vertexPositionMorph, 1.0) + 0.01; + normal = normalize((matRot * vec4(vertexNormal + vertexNormalMorph, 1.0)).xyz); + + vec3 T = normalize(vec3(matTrans * matRot * vec4(vertexTangent, 0.0))); + vec3 N = normalize(vec3(matTrans * matRot * vec4(vertexNormal + vertexNormalMorph, 0.0))); + T = normalize(T - dot(T, N) * N); + vec3 B = cross(N, T); + TBN = mat3(T, B, N); + + textureCoord = textureCoordinate; + }` + } + + getFsSource(l) { + return `#version 300 es + precision highp float; + precision highp sampler2D; + + uniform float lightInt[${l}]; + uniform float lightAmb[${l}]; + uniform vec3 lightColor[${l}]; + uniform float whiteM; + uniform float gammaY; + + uniform vec3 Ka; + uniform vec3 Kd; + uniform vec3 Ks; + uniform float d; + uniform float Ns; + + uniform float sNormals; + uniform float sAmbient; + uniform float sDiffuse; + uniform float sSpecular; + uniform float sAlpha; + uniform float sGamma; + uniform float sReinhard; + uniform float sNormal; + + uniform vec3 lightVect[${l}]; + uniform vec3 lookDir; + + uniform sampler2D textSampler[6]; + + in vec2 textureCoord; + in vec3 normal; + in mat3 TBN; + + out vec4 outputColor; + + void main() { + 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); + float map_Ns = 0.0; + float map_d = 1.0; + + 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 (sAmbient == 1.0) + map_Ka = Ka * texture(textSampler[0], textureCoord.st).rgb; + + if (sDiffuse == 1.0) + map_Kd = Kd * texture(textSampler[1], textureCoord.st).rgb; + + if (sSpecular == 1.0) { + map_Ks = Ks * texture(textSampler[2], textureCoord.st).rgb; + map_Ns = Ns * texture(textSampler[3], textureCoord.st).r; + } + + if (sAlpha == 1.0) + map_d = d * texture(textSampler[4], textureCoord.st).r; + + 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); + for (int i = 0; i < ${l}; 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 * lightColor[i]; + La += map_Ka * lightAmb[i] * lightColor[i]; + } + + vec3 vLighting = Ld + Ls + La; + vec3 c = map_Kd * vLighting; + + 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.r = pow(c.r, (1.0/gammaY)); + c.g = pow(c.g, (1.0/gammaY)); + c.b = pow(c.b, (1.0/gammaY)); + } + + if (sNormals == 1.0) { + c = new_normal; + } + + outputColor = vec4(c*map_d, map_d); + }` + } initBuffers() { this.backgroundPositionBuffer = this.gl.createBuffer(); @@ -260,14 +271,14 @@ App.Art.Engine = class { }); } - initShaders() { + initShaders(sceneParams) { // compile shaders let vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER); - this.gl.shaderSource(vertexShader, this.vsSource); + this.gl.shaderSource(vertexShader, this.getVsSource()); this.gl.compileShader(vertexShader); let fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); - this.gl.shaderSource(fragmentShader, this.fsSource); + this.gl.shaderSource(fragmentShader, this.getFsSource(sceneParams.lights.length)); this.gl.compileShader(fragmentShader); this.shaderProgram = this.gl.createProgram(); @@ -276,11 +287,11 @@ App.Art.Engine = class { this.gl.linkProgram(this.shaderProgram); let vertexShaderBg = this.gl.createShader(this.gl.VERTEX_SHADER); - this.gl.shaderSource(vertexShaderBg, this.vsSourceBg); + this.gl.shaderSource(vertexShaderBg, this.getVsSourceBg()); this.gl.compileShader(vertexShaderBg); let fragmentShaderBg = this.gl.createShader(this.gl.FRAGMENT_SHADER); - this.gl.shaderSource(fragmentShaderBg, this.fsSourceBg); + this.gl.shaderSource(fragmentShaderBg, this.getFsSourceBg()); this.gl.compileShader(fragmentShaderBg); this.shaderProgramBg = this.gl.createProgram(); @@ -313,7 +324,7 @@ App.Art.Engine = class { this.gl.enableVertexAttribArray(this.vertexPositionMorphAttribute); } - bind(sceneData) { + bind(sceneData, sceneParams) { this.sceneData = sceneData; this.offscreenCanvas = document.createElement("canvas"); @@ -329,7 +340,7 @@ App.Art.Engine = class { this.initBuffers(); this.initTextures(); - this.initShaders(); + this.initShaders(sceneParams); } render(sceneParams, canvas) { @@ -393,13 +404,6 @@ App.Art.Engine = class { let matTrans = this.matrixMakeTranslation(sceneParams.transform.x, sceneParams.transform.y, sceneParams.transform.z); let matScale = this.matrixMakeScaling( sceneParams.transform.scale); - let lightVect = this.polarToCart(this.degreeToRad(sceneParams.light.yr), this.degreeToRad(sceneParams.light.xr)); - let lightAmb = sceneParams.light.ambient; - let lightInt = sceneParams.light.intensity; - let lightColor = sceneParams.light.color; - let whiteM = sceneParams.settings.whiteM; - let gammaY = sceneParams.settings.gammaY; - // set uniforms this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "sNormals"), sceneParams.settings.normals); this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "sAmbient"), sceneParams.settings.ambient); @@ -409,14 +413,24 @@ App.Art.Engine = class { 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"), whiteM); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "gammaY"), gammaY); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "lightAmb"), lightAmb); - this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "lightInt"), lightInt); - this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "lightColor"), lightColor); - this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "lightVect"), lightVect); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "whiteM"), sceneParams.settings.whiteM); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "gammaY"), sceneParams.settings.gammaY); + + for (let i = 0; i < sceneParams.lights.length; i++) { + this.a = sceneParams.lights.length; + let lightVect = this.polarToCart(this.degreeToRad(sceneParams.lights[i].yr), this.degreeToRad(sceneParams.lights[i].xr)); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "lightAmb[" + i + "]"), sceneParams.lights[i].ambient); + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "lightInt[" + i + "]"), sceneParams.lights[i].intensity); + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "lightColor[" + i + "]"), sceneParams.lights[i].color); + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "lightVect[" + i + "]"), lightVect); + } + this.gl.uniform3fv(this.gl.getUniformLocation(this.shaderProgram, "lookDir"), lookDir); + for (let i = 0; i < sceneParams.model.morphs.length; i++) { + this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, sceneParams.model.morphs[i].morphId), sceneParams.model.morphs[i].value); + } + for (let i = 0; i < sceneParams.model.morphs.length; i++) { this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, sceneParams.model.morphs[i].morphId), sceneParams.model.morphs[i].value); } @@ -454,48 +468,51 @@ App.Art.Engine = class { } let visible = sceneParams.model.figures[i].surfaces[j].visible; - let matId = sceneParams.model.figures[i].surfaces[j].matId; - 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.modelTextures[parseInt(mat.map_Ka)]); - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[0]"), 0); - - this.gl.activeTexture(this.gl.TEXTURE1); - this.gl.bindTexture(this.gl.TEXTURE_2D, this.modelTextures[parseInt(mat.map_Kd)]); - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[1]"), 1); - - this.gl.activeTexture(this.gl.TEXTURE2); - this.gl.bindTexture(this.gl.TEXTURE_2D, this.modelTextures[parseInt(mat.map_Ks)]); - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[2]"), 2); - - this.gl.activeTexture(this.gl.TEXTURE3); - this.gl.bindTexture(this.gl.TEXTURE_2D, this.modelTextures[parseInt(mat.map_Ns)]); - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[3]"), 3); - - this.gl.activeTexture(this.gl.TEXTURE4); - this.gl.bindTexture(this.gl.TEXTURE_2D, this.modelTextures[parseInt(mat.map_D)]); - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[4]"), 4); - - this.gl.activeTexture(this.gl.TEXTURE5); - this.gl.bindTexture(this.gl.TEXTURE_2D, this.modelTextures[parseInt(mat.map_Kn)]); - this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[5]"), 5); - - 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.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "Ns"), mat.Ns); - - // draw materials - this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.verticesIndexBuffer[count]); - this.gl.drawElements(this.gl.TRIANGLES, this.indexSizes[count], this.gl.UNSIGNED_INT, 0); - } + + for (let h=0; h < sceneParams.model.figures[i].surfaces[j].matIds.length; h++) { + let matId = sceneParams.model.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.modelTextures[parseInt(mat.map_Ka)]); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[0]"), 0); + + this.gl.activeTexture(this.gl.TEXTURE1); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.modelTextures[parseInt(mat.map_Kd)]); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[1]"), 1); + + this.gl.activeTexture(this.gl.TEXTURE2); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.modelTextures[parseInt(mat.map_Ks)]); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[2]"), 2); + + this.gl.activeTexture(this.gl.TEXTURE3); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.modelTextures[parseInt(mat.map_Ns)]); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[3]"), 3); + + this.gl.activeTexture(this.gl.TEXTURE4); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.modelTextures[parseInt(mat.map_D)]); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[4]"), 4); + + this.gl.activeTexture(this.gl.TEXTURE5); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.modelTextures[parseInt(mat.map_Kn)]); + this.gl.uniform1i(this.gl.getUniformLocation(this.shaderProgram, "textSampler[5]"), 5); + + 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.uniform1f(this.gl.getUniformLocation(this.shaderProgram, "Ns"), mat.Ns); + + // draw materials + this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.verticesIndexBuffer[count]); + this.gl.drawElements(this.gl.TRIANGLES, this.indexSizes[count], this.gl.UNSIGNED_INT, 0); + } + } } } }