cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
922 lines (921 loc) • 34.1 kB
JavaScript
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 };