UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

922 lines (921 loc) 34.1 kB
import Base from "./core/Base.mjs"; import GLInfo from "./core/GLInfo.mjs"; import glenum from "./core/glenum.mjs"; import vendor from "./core/vendor.mjs"; import Material from "./Material.mjs"; import Vector2 from "./math/Vector2.mjs"; import ProgramManager from "./gpu/ProgramManager.mjs"; import Shader from "./Shader.mjs"; import prezGLSL from "./shader/source/prez.glsl.mjs"; import mat4 from "./glmatrix/mat4.mjs"; import vec3 from "./glmatrix/vec3.mjs"; Shader["import"](prezGLSL); var mat4Create = mat4.create; var errorShader = {}; function defaultGetMaterial(renderable) { return renderable.material; } function defaultGetUniform(renderable, material, symbol) { return material.uniforms[symbol].value; } function defaultIsMaterialChanged(renderabled, prevRenderable, material, prevMaterial) { return material !== prevMaterial; } function defaultIfRender(renderable) { return true; } function noop() { } var attributeBufferTypeMap = { float: glenum.FLOAT, byte: glenum.BYTE, ubyte: glenum.UNSIGNED_BYTE, short: glenum.SHORT, ushort: glenum.UNSIGNED_SHORT }; function VertexArrayObject(availableAttributes, availableAttributeSymbols, indicesBuffer) { this.availableAttributes = availableAttributes; this.availableAttributeSymbols = availableAttributeSymbols; this.indicesBuffer = indicesBuffer; this.vao = null; } function PlaceHolderTexture(renderer) { var blankCanvas; var webglTexture; this.bind = function(renderer2) { if (!blankCanvas) { blankCanvas = vendor.createCanvas(); blankCanvas.width = blankCanvas.height = 1; blankCanvas.getContext("2d"); } var gl = renderer2.gl; var firstBind = !webglTexture; if (firstBind) { webglTexture = gl.createTexture(); } gl.bindTexture(gl.TEXTURE_2D, webglTexture); if (firstBind) { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, blankCanvas); } }; this.unbind = function(renderer2) { renderer2.gl.bindTexture(renderer2.gl.TEXTURE_2D, null); }; this.isRenderable = function() { return true; }; } var Renderer = Base.extend( function() { return { canvas: null, _width: 100, _height: 100, devicePixelRatio: typeof window !== "undefined" && window.devicePixelRatio || 1, clearColor: [0, 0, 0, 0], clearBit: 17664, alpha: true, depth: true, stencil: false, antialias: true, premultipliedAlpha: true, preserveDrawingBuffer: false, throwError: true, gl: null, viewport: {}, maxJointNumber: 20, __currentFrameBuffer: null, _viewportStack: [], _clearStack: [], _sceneRendering: null }; }, function() { if (!this.canvas) { this.canvas = vendor.createCanvas(); } var canvas = this.canvas; try { var opts = { alpha: this.alpha, depth: this.depth, stencil: this.stencil, antialias: this.antialias, premultipliedAlpha: this.premultipliedAlpha, preserveDrawingBuffer: this.preserveDrawingBuffer }; this.gl = canvas.getContext("webgl", opts) || canvas.getContext("experimental-webgl", opts); if (!this.gl) { throw new Error(); } this._glinfo = new GLInfo(this.gl); if (this.gl.targetRenderer) { console.error("Already created a renderer"); } this.gl.targetRenderer = this; this.resize(); } catch (e) { throw "Error creating WebGL Context " + e; } this._programMgr = new ProgramManager(this); this._placeholderTexture = new PlaceHolderTexture(); }, { resize: function(width, height) { var canvas = this.canvas; var dpr = this.devicePixelRatio; if (width != null) { if (canvas.style) { canvas.style.width = width + "px"; canvas.style.height = height + "px"; } canvas.width = width * dpr; canvas.height = height * dpr; this._width = width; this._height = height; } else { this._width = canvas.width / dpr; this._height = canvas.height / dpr; } this.setViewport(0, 0, this._width, this._height); }, getWidth: function() { return this._width; }, getHeight: function() { return this._height; }, getViewportAspect: function() { var viewport = this.viewport; return viewport.width / viewport.height; }, setDevicePixelRatio: function(devicePixelRatio) { this.devicePixelRatio = devicePixelRatio; this.resize(this._width, this._height); }, getDevicePixelRatio: function() { return this.devicePixelRatio; }, getGLExtension: function(name) { return this._glinfo.getExtension(name); }, getGLParameter: function(name) { return this._glinfo.getParameter(name); }, setViewport: function(x, y, width, height, dpr) { if (typeof x === "object") { var obj = x; x = obj.x; y = obj.y; width = obj.width; height = obj.height; dpr = obj.devicePixelRatio; } dpr = dpr || this.devicePixelRatio; this.gl.viewport( x * dpr, y * dpr, width * dpr, height * dpr ); this.viewport = { x, y, width, height, devicePixelRatio: dpr }; }, saveViewport: function() { this._viewportStack.push(this.viewport); }, restoreViewport: function() { if (this._viewportStack.length > 0) { this.setViewport(this._viewportStack.pop()); } }, saveClear: function() { this._clearStack.push({ clearBit: this.clearBit, clearColor: this.clearColor }); }, restoreClear: function() { if (this._clearStack.length > 0) { var opt = this._clearStack.pop(); this.clearColor = opt.clearColor; this.clearBit = opt.clearBit; } }, bindSceneRendering: function(scene) { this._sceneRendering = scene; }, render: function(scene, camera, notUpdateScene, preZ) { var _gl = this.gl; var clearColor = this.clearColor; if (this.clearBit) { _gl.colorMask(true, true, true, true); _gl.depthMask(true); var viewport = this.viewport; var needsScissor = false; var viewportDpr = viewport.devicePixelRatio; if (viewport.width !== this._width || viewport.height !== this._height || viewportDpr && viewportDpr !== this.devicePixelRatio || viewport.x || viewport.y) { needsScissor = true; _gl.enable(_gl.SCISSOR_TEST); _gl.scissor(viewport.x * viewportDpr, viewport.y * viewportDpr, viewport.width * viewportDpr, viewport.height * viewportDpr); } _gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); _gl.clear(this.clearBit); if (needsScissor) { _gl.disable(_gl.SCISSOR_TEST); } } if (!notUpdateScene) { scene.update(false); } scene.updateLights(); camera = camera || scene.getMainCamera(); if (!camera) { console.error("Can't find camera in the scene."); return; } camera.update(); var renderList = scene.updateRenderList(camera, true); this._sceneRendering = scene; var opaqueList = renderList.opaque; var transparentList = renderList.transparent; var sceneMaterial = scene.material; scene.trigger("beforerender", this, scene, camera, renderList); if (preZ) { this.renderPreZ(opaqueList, scene, camera); _gl.depthFunc(_gl.LEQUAL); } else { _gl.depthFunc(_gl.LESS); } var worldViewMat = mat4Create(); var posViewSpace = vec3.create(); for (var i = 0; i < transparentList.length; i++) { var renderable = transparentList[i]; mat4.multiplyAffine(worldViewMat, camera.viewMatrix.array, renderable.worldTransform.array); vec3.transformMat4(posViewSpace, renderable.position.array, worldViewMat); renderable.__depth = posViewSpace[2]; } this.renderPass(opaqueList, camera, { getMaterial: function(renderable2) { return sceneMaterial || renderable2.material; }, sortCompare: this.opaqueSortCompare }); this.renderPass(transparentList, camera, { getMaterial: function(renderable2) { return sceneMaterial || renderable2.material; }, sortCompare: this.transparentSortCompare }); scene.trigger("afterrender", this, scene, camera, renderList); this._sceneRendering = null; }, getProgram: function(renderable, renderMaterial, scene) { renderMaterial = renderMaterial || renderable.material; return this._programMgr.getProgram(renderable, renderMaterial, scene); }, validateProgram: function(program) { if (program.__error) { var errorMsg = program.__error; if (errorShader[program.__uid__]) { return; } errorShader[program.__uid__] = true; if (this.throwError) { throw new Error(errorMsg); } else { this.trigger("error", errorMsg); } } }, updatePrograms: function(list, scene, passConfig) { var getMaterial = passConfig && passConfig.getMaterial || defaultGetMaterial; scene = scene || null; for (var i = 0; i < list.length; i++) { var renderable = list[i]; var renderMaterial = getMaterial.call(this, renderable); if (i > 0) { var prevRenderable = list[i - 1]; var prevJointsLen = prevRenderable.joints ? prevRenderable.joints.length : 0; var jointsLen = renderable.joints ? renderable.joints.length : 0; if (jointsLen === prevJointsLen && renderable.material === prevRenderable.material && renderable.lightGroup === prevRenderable.lightGroup) { renderable.__program = prevRenderable.__program; continue; } } var program = this._programMgr.getProgram(renderable, renderMaterial, scene); this.validateProgram(program); renderable.__program = program; } }, renderPass: function(list, camera, passConfig) { this.trigger("beforerenderpass", this, list, camera, passConfig); passConfig = passConfig || {}; passConfig.getMaterial = passConfig.getMaterial || defaultGetMaterial; passConfig.getUniform = passConfig.getUniform || defaultGetUniform; passConfig.isMaterialChanged = passConfig.isMaterialChanged || defaultIsMaterialChanged; passConfig.beforeRender = passConfig.beforeRender || noop; passConfig.afterRender = passConfig.afterRender || noop; var ifRenderObject = passConfig.ifRender || defaultIfRender; this.updatePrograms(list, this._sceneRendering, passConfig); if (passConfig.sortCompare) { list.sort(passConfig.sortCompare); } var viewport = this.viewport; var vDpr = viewport.devicePixelRatio; var viewportUniform = [ viewport.x * vDpr, viewport.y * vDpr, viewport.width * vDpr, viewport.height * vDpr ]; var windowDpr = this.devicePixelRatio; var windowSizeUniform = this.__currentFrameBuffer ? [this.__currentFrameBuffer.getTextureWidth(), this.__currentFrameBuffer.getTextureHeight()] : [this._width * windowDpr, this._height * windowDpr]; var viewportSizeUniform = [ viewportUniform[2], viewportUniform[3] ]; var time = Date.now(); if (camera) { mat4.copy(matrices.VIEW, camera.viewMatrix.array); mat4.copy(matrices.PROJECTION, camera.projectionMatrix.array); mat4.copy(matrices.VIEWINVERSE, camera.worldTransform.array); } else { mat4.identity(matrices.VIEW); mat4.identity(matrices.PROJECTION); mat4.identity(matrices.VIEWINVERSE); } mat4.multiply(matrices.VIEWPROJECTION, matrices.PROJECTION, matrices.VIEW); mat4.invert(matrices.PROJECTIONINVERSE, matrices.PROJECTION); mat4.invert(matrices.VIEWPROJECTIONINVERSE, matrices.VIEWPROJECTION); var _gl = this.gl; var scene = this._sceneRendering; var prevMaterial; var prevProgram; var prevRenderable; var depthTest, depthMask; var culling, cullFace, frontFace; var transparent; var drawID; var currentVAO; var materialTakesTextureSlot; var vaoExt = null; for (var i = 0; i < list.length; i++) { var renderable = list[i]; var isSceneNode = renderable.worldTransform != null; var worldM; if (!ifRenderObject(renderable)) { continue; } if (isSceneNode) { worldM = renderable.isSkinnedMesh && renderable.isSkinnedMesh() ? renderable.offsetMatrix ? renderable.offsetMatrix.array : matrices.IDENTITY : renderable.worldTransform.array; } var geometry = renderable.geometry; var material = passConfig.getMaterial.call(this, renderable); var program = renderable.__program; var shader = material.shader; var currentDrawID = geometry.__uid__ + "-" + program.__uid__; var drawIDChanged = currentDrawID !== drawID; drawID = currentDrawID; if (drawIDChanged && vaoExt) { vaoExt.bindVertexArrayOES(null); } if (isSceneNode) { mat4.copy(matrices.WORLD, worldM); mat4.multiply(matrices.WORLDVIEWPROJECTION, matrices.VIEWPROJECTION, worldM); mat4.multiplyAffine(matrices.WORLDVIEW, matrices.VIEW, worldM); if (shader.matrixSemantics.WORLDINVERSE || shader.matrixSemantics.WORLDINVERSETRANSPOSE) { mat4.invert(matrices.WORLDINVERSE, worldM); } if (shader.matrixSemantics.WORLDVIEWINVERSE || shader.matrixSemantics.WORLDVIEWINVERSETRANSPOSE) { mat4.invert(matrices.WORLDVIEWINVERSE, matrices.WORLDVIEW); } if (shader.matrixSemantics.WORLDVIEWPROJECTIONINVERSE || shader.matrixSemantics.WORLDVIEWPROJECTIONINVERSETRANSPOSE) { mat4.invert(matrices.WORLDVIEWPROJECTIONINVERSE, matrices.WORLDVIEWPROJECTION); } } renderable.beforeRender && renderable.beforeRender(this); passConfig.beforeRender.call(this, renderable, material, prevMaterial); var programChanged = program !== prevProgram; if (programChanged) { program.bind(this); program.setUniformOfSemantic(_gl, "VIEWPORT", viewportUniform); program.setUniformOfSemantic(_gl, "WINDOW_SIZE", windowSizeUniform); if (camera) { program.setUniformOfSemantic(_gl, "NEAR", camera.near); program.setUniformOfSemantic(_gl, "FAR", camera.far); } program.setUniformOfSemantic(_gl, "DEVICEPIXELRATIO", vDpr); program.setUniformOfSemantic(_gl, "TIME", time); program.setUniformOfSemantic(_gl, "VIEWPORT_SIZE", viewportSizeUniform); if (scene) { scene.setLightUniforms(program, renderable.lightGroup, this); } } else { program = prevProgram; } if (programChanged || passConfig.isMaterialChanged( renderable, prevRenderable, material, prevMaterial )) { if (material.depthTest !== depthTest) { material.depthTest ? _gl.enable(_gl.DEPTH_TEST) : _gl.disable(_gl.DEPTH_TEST); depthTest = material.depthTest; } if (material.depthMask !== depthMask) { _gl.depthMask(material.depthMask); depthMask = material.depthMask; } if (material.transparent !== transparent) { material.transparent ? _gl.enable(_gl.BLEND) : _gl.disable(_gl.BLEND); transparent = material.transparent; } if (material.transparent) { if (material.blend) { material.blend(_gl); } else { _gl.blendEquationSeparate(_gl.FUNC_ADD, _gl.FUNC_ADD); _gl.blendFuncSeparate(_gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA); } } materialTakesTextureSlot = this._bindMaterial( renderable, material, program, prevRenderable || null, prevMaterial || null, prevProgram || null, passConfig.getUniform ); prevMaterial = material; } var matrixSemanticKeys = shader.matrixSemanticKeys; if (isSceneNode) { for (var k = 0; k < matrixSemanticKeys.length; k++) { var semantic = matrixSemanticKeys[k]; var semanticInfo = shader.matrixSemantics[semantic]; var matrix = matrices[semantic]; if (semanticInfo.isTranspose) { var matrixNoTranspose = matrices[semanticInfo.semanticNoTranspose]; mat4.transpose(matrix, matrixNoTranspose); } program.setUniform(_gl, semanticInfo.type, semanticInfo.symbol, matrix); } } if (renderable.cullFace !== cullFace) { cullFace = renderable.cullFace; _gl.cullFace(cullFace); } if (renderable.frontFace !== frontFace) { frontFace = renderable.frontFace; _gl.frontFace(frontFace); } if (renderable.culling !== culling) { culling = renderable.culling; culling ? _gl.enable(_gl.CULL_FACE) : _gl.disable(_gl.CULL_FACE); } this._updateSkeleton(renderable, program, materialTakesTextureSlot); if (drawIDChanged) { currentVAO = this._bindVAO(vaoExt, shader, geometry, program); } this._renderObject(renderable, currentVAO, program); passConfig.afterRender(this, renderable); renderable.afterRender && renderable.afterRender(this); prevProgram = program; prevRenderable = renderable; } this.trigger("afterrenderpass", this, list, camera, passConfig); }, getMaxJointNumber: function() { return this.maxJointNumber; }, _updateSkeleton: function(object, program, slot) { var _gl = this.gl; var skeleton = object.skeleton; if (skeleton) { skeleton.update(); if (object.joints.length > this.getMaxJointNumber()) { var skinMatricesTexture = skeleton.getSubSkinMatricesTexture(object.__uid__, object.joints); program.useTextureSlot(this, skinMatricesTexture, slot); program.setUniform(_gl, "1i", "skinMatricesTexture", slot); program.setUniform(_gl, "1f", "skinMatricesTextureSize", skinMatricesTexture.width); } else { var skinMatricesArray = skeleton.getSubSkinMatrices(object.__uid__, object.joints); program.setUniformOfSemantic(_gl, "SKIN_MATRIX", skinMatricesArray); } } }, _renderObject: function(renderable, vao, program) { var _gl = this.gl; var geometry = renderable.geometry; var glDrawMode = renderable.mode; if (glDrawMode == null) { glDrawMode = 4; } var ext = null; var isInstanced = renderable.isInstancedMesh && renderable.isInstancedMesh(); if (isInstanced) { ext = this.getGLExtension("ANGLE_instanced_arrays"); if (!ext) { console.warn("Device not support ANGLE_instanced_arrays extension"); return; } } var instancedAttrLocations; if (isInstanced) { instancedAttrLocations = this._bindInstancedAttributes(renderable, program, ext); } if (vao.indicesBuffer) { var uintExt = this.getGLExtension("OES_element_index_uint"); var useUintExt = uintExt && geometry.indices instanceof Uint32Array; var indicesType = useUintExt ? _gl.UNSIGNED_INT : _gl.UNSIGNED_SHORT; if (isInstanced) { ext.drawElementsInstancedANGLE( glDrawMode, vao.indicesBuffer.count, indicesType, 0, renderable.getInstanceCount() ); } else { _gl.drawElements(glDrawMode, vao.indicesBuffer.count, indicesType, 0); } } else { if (isInstanced) { ext.drawArraysInstancedANGLE(glDrawMode, 0, geometry.vertexCount, renderable.getInstanceCount()); } else { _gl.drawArrays(glDrawMode, 0, geometry.vertexCount); } } if (isInstanced) { for (var i = 0; i < instancedAttrLocations.length; i++) { _gl.disableVertexAttribArray(instancedAttrLocations[i]); } } }, _bindInstancedAttributes: function(renderable, program, ext) { var _gl = this.gl; var instancedBuffers = renderable.getInstancedAttributesBuffers(this); var locations = []; for (var i = 0; i < instancedBuffers.length; i++) { var bufferObj = instancedBuffers[i]; var location = program.getAttribLocation(_gl, bufferObj.symbol); if (location < 0) { continue; } var glType = attributeBufferTypeMap[bufferObj.type] || _gl.FLOAT; _gl.enableVertexAttribArray(location); _gl.bindBuffer(_gl.ARRAY_BUFFER, bufferObj.buffer); _gl.vertexAttribPointer(location, bufferObj.size, glType, false, 0, 0); ext.vertexAttribDivisorANGLE(location, bufferObj.divisor); locations.push(location); } return locations; }, _bindMaterial: function(renderable, material, program, prevRenderable, prevMaterial, prevProgram, getUniformValue) { var _gl = this.gl; var sameProgram = prevProgram === program; var currentTextureSlot = program.currentTextureSlot(); var enabledUniforms = material.getEnabledUniforms(); var textureUniforms = material.getTextureUniforms(); var placeholderTexture = this._placeholderTexture; for (var u = 0; u < textureUniforms.length; u++) { var symbol = textureUniforms[u]; var uniformValue = getUniformValue(renderable, material, symbol); var uniformType = material.uniforms[symbol].type; if (uniformType === "t" && uniformValue) { uniformValue.__slot = -1; } else if (uniformType === "tv") { for (var i = 0; i < uniformValue.length; i++) { if (uniformValue[i]) { uniformValue[i].__slot = -1; } } } } placeholderTexture.__slot = -1; for (var u = 0; u < enabledUniforms.length; u++) { var symbol = enabledUniforms[u]; var uniform = material.uniforms[symbol]; var uniformValue = getUniformValue(renderable, material, symbol); var uniformType = uniform.type; var isTexture = uniformType === "t"; if (isTexture) { if (!uniformValue || !uniformValue.isRenderable()) { uniformValue = placeholderTexture; } } if (prevMaterial && sameProgram) { var prevUniformValue = getUniformValue(prevRenderable, prevMaterial, symbol); if (isTexture) { if (!prevUniformValue || !prevUniformValue.isRenderable()) { prevUniformValue = placeholderTexture; } } if (prevUniformValue === uniformValue) { if (isTexture) { program.takeCurrentTextureSlot(this, null); } else if (uniformType === "tv" && uniformValue) { for (var i = 0; i < uniformValue.length; i++) { program.takeCurrentTextureSlot(this, null); } } continue; } } if (uniformValue == null) { continue; } else if (isTexture) { if (uniformValue.__slot < 0) { var slot = program.currentTextureSlot(); var res = program.setUniform(_gl, "1i", symbol, slot); if (res) { program.takeCurrentTextureSlot(this, uniformValue); uniformValue.__slot = slot; } } else { program.setUniform(_gl, "1i", symbol, uniformValue.__slot); } } else if (Array.isArray(uniformValue)) { if (uniformValue.length === 0) { continue; } if (uniformType === "tv") { if (!program.hasUniform(symbol)) { continue; } var arr = []; for (var i = 0; i < uniformValue.length; i++) { var texture = uniformValue[i]; if (texture.__slot < 0) { var slot = program.currentTextureSlot(); arr.push(slot); program.takeCurrentTextureSlot(this, texture); texture.__slot = slot; } else { arr.push(texture.__slot); } } program.setUniform(_gl, "1iv", symbol, arr); } else { program.setUniform(_gl, uniform.type, symbol, uniformValue); } } else { program.setUniform(_gl, uniform.type, symbol, uniformValue); } } var newSlot = program.currentTextureSlot(); program.resetTextureSlot(currentTextureSlot); return newSlot; }, _bindVAO: function(vaoExt, shader, geometry, program) { var isStatic = !geometry.dynamic; var _gl = this.gl; var vaoId = this.__uid__ + "-" + program.__uid__; var vao = geometry.__vaoCache[vaoId]; if (!vao) { var chunks = geometry.getBufferChunks(this); if (!chunks || !chunks.length) { return; } var chunk = chunks[0]; var attributeBuffers = chunk.attributeBuffers; var indicesBuffer = chunk.indicesBuffer; var availableAttributes = []; var availableAttributeSymbols = []; for (var a = 0; a < attributeBuffers.length; a++) { var attributeBufferInfo = attributeBuffers[a]; var name = attributeBufferInfo.name; var semantic = attributeBufferInfo.semantic; var symbol; if (semantic) { var semanticInfo = shader.attributeSemantics[semantic]; symbol = semanticInfo && semanticInfo.symbol; } else { symbol = name; } if (symbol && program.attributes[symbol]) { availableAttributes.push(attributeBufferInfo); availableAttributeSymbols.push(symbol); } } vao = new VertexArrayObject( availableAttributes, availableAttributeSymbols, indicesBuffer ); if (isStatic) { geometry.__vaoCache[vaoId] = vao; } } var needsBindAttributes = true; if (vaoExt && isStatic) { if (vao.vao == null) { vao.vao = vaoExt.createVertexArrayOES(); } else { needsBindAttributes = false; } vaoExt.bindVertexArrayOES(vao.vao); } var availableAttributes = vao.availableAttributes; var indicesBuffer = vao.indicesBuffer; if (needsBindAttributes) { var locationList = program.enableAttributes(this, vao.availableAttributeSymbols, vaoExt && isStatic && vao); for (var a = 0; a < availableAttributes.length; a++) { var location = locationList[a]; if (location === -1) { continue; } var attributeBufferInfo = availableAttributes[a]; var buffer = attributeBufferInfo.buffer; var size = attributeBufferInfo.size; var glType = attributeBufferTypeMap[attributeBufferInfo.type] || _gl.FLOAT; _gl.bindBuffer(_gl.ARRAY_BUFFER, buffer); _gl.vertexAttribPointer(location, size, glType, false, 0, 0); } if (geometry.isUseIndices()) { _gl.bindBuffer(_gl.ELEMENT_ARRAY_BUFFER, indicesBuffer.buffer); } } return vao; }, renderPreZ: function(list, scene, camera) { var _gl = this.gl; var preZPassMaterial = this._prezMaterial || new Material({ shader: new Shader(Shader.source("clay.prez.vertex"), Shader.source("clay.prez.fragment")) }); this._prezMaterial = preZPassMaterial; _gl.colorMask(false, false, false, false); _gl.depthMask(true); this.renderPass(list, camera, { ifRender: function(renderable) { return !renderable.ignorePreZ; }, isMaterialChanged: function(renderable, prevRenderable) { var matA = renderable.material; var matB = prevRenderable.material; return matA.get("diffuseMap") !== matB.get("diffuseMap") || (matA.get("alphaCutoff") || 0) !== (matB.get("alphaCutoff") || 0); }, getUniform: function(renderable, depthMaterial, symbol) { if (symbol === "alphaMap") { return renderable.material.get("diffuseMap"); } else if (symbol === "alphaCutoff") { if (renderable.material.isDefined("fragment", "ALPHA_TEST") && renderable.material.get("diffuseMap")) { var alphaCutoff = renderable.material.get("alphaCutoff"); return alphaCutoff || 0; } return 0; } else if (symbol === "uvRepeat") { return renderable.material.get("uvRepeat"); } else if (symbol === "uvOffset") { return renderable.material.get("uvOffset"); } else { return depthMaterial.get(symbol); } }, getMaterial: function() { return preZPassMaterial; }, sort: this.opaqueSortCompare }); _gl.colorMask(true, true, true, true); _gl.depthMask(true); }, disposeScene: function(scene) { this.disposeNode(scene, true, true); scene.dispose(); }, disposeNode: function(root, disposeGeometry, disposeTexture) { if (root.getParent()) { root.getParent().remove(root); } var disposedMap = {}; root.traverse(function(node) { var material = node.material; if (node.geometry && disposeGeometry) { node.geometry.dispose(this); } if (disposeTexture && material && !disposedMap[material.__uid__]) { var textureUniforms = material.getTextureUniforms(); for (var u = 0; u < textureUniforms.length; u++) { var uniformName = textureUniforms[u]; var val = material.uniforms[uniformName].value; var uniformType = material.uniforms[uniformName].type; if (!val) { continue; } if (uniformType === "t") { val.dispose && val.dispose(this); } else if (uniformType === "tv") { for (var k = 0; k < val.length; k++) { if (val[k]) { val[k].dispose && val[k].dispose(this); } } } } disposedMap[material.__uid__] = true; } if (node.dispose) { node.dispose(this); } }, this); }, disposeGeometry: function(geometry) { geometry.dispose(this); }, disposeTexture: function(texture) { texture.dispose(this); }, disposeFrameBuffer: function(frameBuffer) { frameBuffer.dispose(this); }, dispose: function() { }, screenToNDC: function(x, y, out) { if (!out) { out = new Vector2(); } y = this._height - y; var viewport = this.viewport; var arr = out.array; arr[0] = (x - viewport.x) / viewport.width; arr[0] = arr[0] * 2 - 1; arr[1] = (y - viewport.y) / viewport.height; arr[1] = arr[1] * 2 - 1; return out; } } ); Renderer.opaqueSortCompare = Renderer.prototype.opaqueSortCompare = function(x, y) { if (x.renderOrder === y.renderOrder) { if (x.__program === y.__program) { if (x.material === y.material) { return x.geometry.__uid__ - y.geometry.__uid__; } return x.material.__uid__ - y.material.__uid__; } if (x.__program && y.__program) { return x.__program.__uid__ - y.__program.__uid__; } return 0; } return x.renderOrder - y.renderOrder; }; Renderer.transparentSortCompare = Renderer.prototype.transparentSortCompare = function(x, y) { if (x.renderOrder === y.renderOrder) { if (x.__depth === y.__depth) { if (x.__program === y.__program) { if (x.material === y.material) { return x.geometry.__uid__ - y.geometry.__uid__; } return x.material.__uid__ - y.material.__uid__; } if (x.__program && y.__program) { return x.__program.__uid__ - y.__program.__uid__; } return 0; } return x.__depth - y.__depth; } return x.renderOrder - y.renderOrder; }; var matrices = { IDENTITY: mat4Create(), WORLD: mat4Create(), VIEW: mat4Create(), PROJECTION: mat4Create(), WORLDVIEW: mat4Create(), VIEWPROJECTION: mat4Create(), WORLDVIEWPROJECTION: mat4Create(), WORLDINVERSE: mat4Create(), VIEWINVERSE: mat4Create(), PROJECTIONINVERSE: mat4Create(), WORLDVIEWINVERSE: mat4Create(), VIEWPROJECTIONINVERSE: mat4Create(), WORLDVIEWPROJECTIONINVERSE: mat4Create(), WORLDTRANSPOSE: mat4Create(), VIEWTRANSPOSE: mat4Create(), PROJECTIONTRANSPOSE: mat4Create(), WORLDVIEWTRANSPOSE: mat4Create(), VIEWPROJECTIONTRANSPOSE: mat4Create(), WORLDVIEWPROJECTIONTRANSPOSE: mat4Create(), WORLDINVERSETRANSPOSE: mat4Create(), VIEWINVERSETRANSPOSE: mat4Create(), PROJECTIONINVERSETRANSPOSE: mat4Create(), WORLDVIEWINVERSETRANSPOSE: mat4Create(), VIEWPROJECTIONINVERSETRANSPOSE: mat4Create(), WORLDVIEWPROJECTIONINVERSETRANSPOSE: mat4Create() }; Renderer.COLOR_BUFFER_BIT = glenum.COLOR_BUFFER_BIT; Renderer.DEPTH_BUFFER_BIT = glenum.DEPTH_BUFFER_BIT; Renderer.STENCIL_BUFFER_BIT = glenum.STENCIL_BUFFER_BIT; var Renderer$1 = Renderer; export { Renderer$1 as default };