Comparing version 0.1.2 to 0.1.3-beta.0
{ | ||
"name": "t3d", | ||
"version": "0.1.2", | ||
"version": "0.1.3-beta.0", | ||
"description": "t3d.js is a web-first, light weight, extendable 3D rendering library.", | ||
@@ -5,0 +5,0 @@ "type": "module", |
@@ -12,2 +12,3 @@ import { TEXEL_ENCODING_TYPE, PIXEL_FORMAT, PIXEL_TYPE, TEXTURE_FILTER, TEXTURE_WRAP, COMPARE_FUNC, OPERATION } from './const.js'; | ||
import { WebGLVertexArrayBindings } from './webgl/WebGLVertexArrayBindings.js'; | ||
import { WebGLGeometries } from './webgl/WebGLGeometries.js'; | ||
import { Camera } from './scenes/Camera.js'; | ||
@@ -134,2 +135,7 @@ import { Light } from './scenes/Light.js'; | ||
WebGLGeometries.prototype.setBufferExternal = function(buffer, webglBuffer) { | ||
console.warn("WebGLGeometries: .setBufferExternal has been removed. Use WebGLRenderPass.setBufferExternal instead."); | ||
this._buffers.setBufferExternal(buffer, webglBuffer); | ||
} | ||
// Enum for WebGL Texture Type. | ||
@@ -136,0 +142,0 @@ export const WEBGL_TEXTURE_TYPE = { |
@@ -9,2 +9,4 @@ import { Vector3 } from '../math/Vector3.js'; | ||
let _lightDataId = 0; | ||
/** | ||
@@ -18,2 +20,5 @@ * The LightData class is used to collect lights, | ||
constructor() { | ||
this.id = _lightDataId++; | ||
this.version = 0; | ||
// Light collection array | ||
@@ -85,2 +90,4 @@ | ||
this.hash.update(this); | ||
this.version++; | ||
} | ||
@@ -87,0 +94,0 @@ |
@@ -32,3 +32,3 @@ import { Scene } from '../../scenes/Scene.js'; | ||
const geometry = new PlaneGeometry(2, 2, 1, 1); | ||
const geometry = this.geometry = new PlaneGeometry(2, 2, 1, 1); | ||
const material = this.material = new ShaderMaterial(shader); | ||
@@ -60,4 +60,12 @@ this.uniforms = material.uniforms; | ||
/** | ||
* Dispose the post pass. | ||
*/ | ||
dispose() { | ||
this.geometry.dispose(); | ||
this.material.dispose(); | ||
} | ||
} | ||
export { ShaderPostPass }; |
@@ -1,9 +0,6 @@ | ||
function sortFrontToBack(a, b) { | ||
function defaultOpaqueSortCompare(a, b) { | ||
if (a.renderOrder !== b.renderOrder) { | ||
return a.renderOrder - b.renderOrder; | ||
} else if (a.material.id !== b.material.id) { | ||
// batch | ||
return a.material.id - b.material.id; | ||
} else if (a.z !== b.z) { | ||
return a.z - b.z; | ||
} else { | ||
@@ -14,3 +11,3 @@ return a.id - b.id; | ||
function sortBackToFront(a, b) { | ||
function defaultTransparentSortCompare(a, b) { | ||
if (a.renderOrder !== b.renderOrder) { | ||
@@ -50,2 +47,6 @@ return a.renderOrder - b.renderOrder; | ||
this._cacheIndex = 0; | ||
this._lastCacheIndex = 0; | ||
this.opaqueSortCompareFn = defaultOpaqueSortCompare; | ||
this.transparentSortCompareFn = defaultTransparentSortCompare; | ||
} | ||
@@ -63,2 +64,17 @@ | ||
this.transparent.length = this.transparentCount; | ||
// Clear references from inactive renderables in the list | ||
const cacheIndex = this._cacheIndex, | ||
lastCacheIndex = this._lastCacheIndex; | ||
if (lastCacheIndex > cacheIndex) { | ||
const cache = this._cache; | ||
for (let i = cacheIndex; i < lastCacheIndex; i++) { | ||
const renderable = cache[i]; | ||
renderable.object = null; | ||
renderable.geometry = null; | ||
renderable.material = null; | ||
renderable.group = null; | ||
} | ||
} | ||
this._lastCacheIndex = cacheIndex; | ||
} | ||
@@ -102,4 +118,4 @@ | ||
sort() { | ||
this.opaque.sort(sortFrontToBack); | ||
this.transparent.sort(sortBackToFront); | ||
this.opaque.sort(this.opaqueSortCompareFn); | ||
this.transparent.sort(this.transparentSortCompareFn); | ||
} | ||
@@ -106,0 +122,0 @@ |
@@ -10,2 +10,4 @@ import { TEXEL_ENCODING_TYPE } from '../const.js'; | ||
let _cameraDataId = 0; | ||
/** | ||
@@ -22,5 +24,9 @@ * RenderStates collect all render states about scene and camera. | ||
this.camera = { | ||
id: _cameraDataId++, | ||
version: 0, | ||
near: 0, | ||
far: 0, | ||
position: new Vector3(), | ||
logDepthCameraNear: 0, | ||
logDepthBufFC: 0, | ||
viewMatrix: new Matrix4(), | ||
@@ -32,5 +38,2 @@ projectionMatrix: new Matrix4(), | ||
this.logDepthCameraNear = 0; | ||
this.logDepthBufFC = 0; | ||
this.gammaFactor = 2.0; | ||
@@ -46,2 +49,3 @@ this.outputEncoding = TEXEL_ENCODING_TYPE.LINEAR; | ||
const sceneData = this.scene; | ||
const cameraData = this.camera; | ||
const projectionMatrix = camera.projectionMatrix; | ||
@@ -58,28 +62,30 @@ | ||
this.camera.near = cameraNear; | ||
this.camera.far = cameraFar; | ||
cameraData.near = cameraNear; | ||
cameraData.far = cameraFar; | ||
if (sceneData.logarithmicDepthBuffer) { | ||
this.logDepthCameraNear = cameraNear; | ||
this.logDepthBufFC = 2.0 / (Math.log(cameraFar - cameraNear + 1.0) * Math.LOG2E); | ||
cameraData.logDepthCameraNear = cameraNear; | ||
cameraData.logDepthBufFC = 2.0 / (Math.log(cameraFar - cameraNear + 1.0) * Math.LOG2E); | ||
} else { | ||
this.logDepthCameraNear = 0; | ||
this.logDepthBufFC = 0; | ||
cameraData.logDepthCameraNear = 0; | ||
cameraData.logDepthBufFC = 0; | ||
} | ||
this.camera.position.setFromMatrixPosition(camera.worldMatrix); | ||
cameraData.position.setFromMatrixPosition(camera.worldMatrix); | ||
if (sceneData.useAnchorMatrix) { | ||
this.camera.position.applyMatrix4(sceneData.anchorMatrixInverse); | ||
cameraData.position.applyMatrix4(sceneData.anchorMatrixInverse); | ||
} | ||
this.camera.viewMatrix.copy(camera.viewMatrix); | ||
cameraData.viewMatrix.copy(camera.viewMatrix); | ||
if (sceneData.useAnchorMatrix) { | ||
this.camera.viewMatrix.multiply(sceneData.anchorMatrix); | ||
cameraData.viewMatrix.multiply(sceneData.anchorMatrix); | ||
} | ||
this.camera.projectionMatrix.copy(projectionMatrix); | ||
this.camera.projectionViewMatrix.copy(projectionMatrix).multiply(this.camera.viewMatrix); | ||
cameraData.projectionMatrix.copy(projectionMatrix); | ||
cameraData.projectionViewMatrix.copy(projectionMatrix).multiply(cameraData.viewMatrix); | ||
this.camera.rect.copy(camera.rect); | ||
cameraData.rect.copy(camera.rect); | ||
cameraData.version++; | ||
this.gammaFactor = camera.gammaFactor; | ||
@@ -86,0 +92,0 @@ this.outputEncoding = camera.outputEncoding; |
@@ -6,2 +6,4 @@ import { Matrix4 } from '../math/Matrix4.js'; | ||
let _sceneDataId = 0; | ||
/** | ||
@@ -14,2 +16,5 @@ * SceneData collect all render states about scene, Including lights. | ||
constructor() { | ||
this.id = _sceneDataId++; | ||
this.version = 0; | ||
this.useAnchorMatrix = false; | ||
@@ -52,2 +57,4 @@ this.anchorMatrix = new Matrix4(); | ||
this.numClippingPlanes = scene.clippingPlanes.length; | ||
this.version++; | ||
} | ||
@@ -54,0 +61,0 @@ |
@@ -0,14 +1,18 @@ | ||
import { WebGLProperties } from './WebGLProperties.js'; | ||
// This class handles buffer creation and updating for geometries. | ||
// When the geometry is released, release the corresponding buffer resources and VAO. | ||
class WebGLGeometries { | ||
class WebGLGeometries extends WebGLProperties { | ||
constructor(gl, properties, capabilities, vertexArrayBindings) { | ||
constructor(passId, gl, buffers, vertexArrayBindings) { | ||
super(passId); | ||
this._gl = gl; | ||
this._properties = properties; | ||
this._capabilities = capabilities; | ||
this._buffers = buffers; | ||
this._vertexArrayBindings = vertexArrayBindings; | ||
const that = this; | ||
function onGeometryDispose(event) { | ||
const geometry = event.target; | ||
const geometryProperties = properties.get(geometry); | ||
const geometryProperties = that.get(geometry); | ||
@@ -18,7 +22,7 @@ geometry.removeEventListener('dispose', onGeometryDispose); | ||
if (geometry.index !== null) { | ||
removeBuffer(gl, properties, geometry.index.buffer); | ||
buffers.removeBuffer(geometry.index.buffer); | ||
} | ||
for (const name in geometry.attributes) { | ||
removeBuffer(gl, properties, geometry.attributes[name].buffer); | ||
buffers.removeBuffer(geometry.attributes[name].buffer); | ||
} | ||
@@ -29,17 +33,11 @@ | ||
for (let i = 0, l = array.length; i < l; i++) { | ||
removeBuffer(gl, properties, array[i].buffer); | ||
buffers.removeBuffer(array[i].buffer); | ||
} | ||
} | ||
for (const key in geometryProperties._vaos) { | ||
const vao = geometryProperties[key]; | ||
if (vao) { | ||
vertexArrayBindings.disposeVAO(vao.object); | ||
} | ||
} | ||
vertexArrayBindings.releaseByGeometry(geometry); | ||
geometryProperties._vaos = {}; | ||
geometryProperties.created = false; | ||
properties.delete(geometry); | ||
that.delete(geometry); | ||
} | ||
@@ -52,7 +50,5 @@ | ||
const gl = this._gl; | ||
const properties = this._properties; | ||
const capabilities = this._capabilities; | ||
const vertexArrayBindings = this._vertexArrayBindings; | ||
const buffers = this._buffers; | ||
const geometryProperties = properties.get(geometry); | ||
const geometryProperties = this.get(geometry); | ||
@@ -62,21 +58,10 @@ if (!geometryProperties.created) { | ||
geometryProperties.created = true; | ||
geometryProperties._vaos = {}; | ||
} | ||
if (geometry.index !== null) { | ||
const buffer = geometry.index.buffer; | ||
const bufferProperties = properties.get(buffer); | ||
if (bufferProperties.glBuffer === undefined) { | ||
vertexArrayBindings.reset(); // Avoid polluting the binding state | ||
createGLBuffer(gl, bufferProperties, buffer, gl.ELEMENT_ARRAY_BUFFER); | ||
} else if (bufferProperties.version < buffer.version) { | ||
vertexArrayBindings.reset(); // Avoid polluting the binding state | ||
updateGLBuffer(gl, capabilities, bufferProperties.glBuffer, buffer, gl.ELEMENT_ARRAY_BUFFER); | ||
bufferProperties.version = buffer.version; | ||
} | ||
buffers.setBuffer(geometry.index.buffer, gl.ELEMENT_ARRAY_BUFFER, this._vertexArrayBindings); | ||
} | ||
for (const name in geometry.attributes) { | ||
updateBuffer(gl, properties, capabilities, geometry.attributes[name].buffer, gl.ARRAY_BUFFER); | ||
buffers.setBuffer(geometry.attributes[name].buffer, gl.ARRAY_BUFFER); | ||
} | ||
@@ -87,3 +72,3 @@ | ||
for (let i = 0, l = array.length; i < l; i++) { | ||
updateBuffer(gl, properties, capabilities, array[i].buffer, gl.ARRAY_BUFFER); | ||
buffers.setBuffer(array[i].buffer, gl.ARRAY_BUFFER); | ||
} | ||
@@ -95,119 +80,4 @@ } | ||
setBufferExternal(buffer, webglBuffer) { | ||
const gl = this._gl; | ||
const properties = this._properties; | ||
const bufferProperties = properties.get(buffer); | ||
if (!bufferProperties.__external) { | ||
if (bufferProperties.glBuffer) { | ||
gl.deleteBuffer(bufferProperties.glBuffer); | ||
} | ||
} | ||
const type = getBufferType(gl, buffer.array); | ||
bufferProperties.glBuffer = webglBuffer; | ||
bufferProperties.type = type; | ||
bufferProperties.bytesPerElement = buffer.array.BYTES_PER_ELEMENT; | ||
bufferProperties.version = buffer.version; | ||
bufferProperties.__external = true; | ||
} | ||
} | ||
function getBufferType(gl, array) { | ||
let type; | ||
if (array instanceof Float32Array) { | ||
type = gl.FLOAT; | ||
} else if (array instanceof Float64Array) { | ||
console.warn('Unsupported data buffer format: Float64Array.'); | ||
} else if (array instanceof Uint16Array) { | ||
type = gl.UNSIGNED_SHORT; | ||
} else if (array instanceof Int16Array) { | ||
type = gl.SHORT; | ||
} else if (array instanceof Uint32Array) { | ||
type = gl.UNSIGNED_INT; | ||
} else if (array instanceof Int32Array) { | ||
type = gl.INT; | ||
} else if (array instanceof Int8Array) { | ||
type = gl.BYTE; | ||
} else if (array instanceof Uint8Array) { | ||
type = gl.UNSIGNED_BYTE; | ||
} else { | ||
type = gl.FLOAT; | ||
} | ||
return type; | ||
} | ||
function createGLBuffer(gl, properties, buffer, bufferType) { | ||
const array = buffer.array; | ||
const usage = buffer.usage; | ||
const glBuffer = gl.createBuffer(); | ||
gl.bindBuffer(bufferType, glBuffer); | ||
gl.bufferData(bufferType, array, usage); | ||
buffer.onUploadCallback(); | ||
const type = getBufferType(gl, array); | ||
properties.glBuffer = glBuffer; | ||
properties.type = type; | ||
properties.bytesPerElement = array.BYTES_PER_ELEMENT; | ||
properties.version = buffer.version; | ||
} | ||
function updateGLBuffer(gl, capabilities, glBuffer, buffer, bufferType) { | ||
const array = buffer.array; | ||
const updateRange = buffer.updateRange; | ||
gl.bindBuffer(bufferType, glBuffer); | ||
if (updateRange.count === -1) { | ||
// Not using update ranges | ||
gl.bufferSubData(bufferType, 0, array); | ||
} else { | ||
if (capabilities.version >= 2) { | ||
gl.bufferSubData(bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, | ||
array, updateRange.offset, updateRange.count); | ||
} else { | ||
gl.bufferSubData(bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, | ||
array.subarray(updateRange.offset, updateRange.offset + updateRange.count)); | ||
} | ||
updateRange.count = -1; // reset range | ||
} | ||
} | ||
function updateBuffer(gl, properties, capabilities, buffer, bufferType) { | ||
const bufferProperties = properties.get(buffer); | ||
if (bufferProperties.glBuffer === undefined) { | ||
createGLBuffer(gl, bufferProperties, buffer, bufferType); | ||
} else if (bufferProperties.version < buffer.version) { | ||
if (!!bufferProperties.__external) { | ||
delete bufferProperties.glBuffer; | ||
createGLBuffer(gl, bufferProperties, buffer, bufferType); | ||
} else { | ||
updateGLBuffer(gl, capabilities, bufferProperties.glBuffer, buffer, bufferType); | ||
bufferProperties.version = buffer.version; | ||
} | ||
} | ||
} | ||
function removeBuffer(gl, properties, buffer) { | ||
const bufferProperties = properties.get(buffer); | ||
if (bufferProperties.glBuffer && !bufferProperties.__external) { | ||
gl.deleteBuffer(bufferProperties.glBuffer); | ||
} | ||
properties.delete(buffer); | ||
} | ||
export { WebGLGeometries }; |
@@ -9,37 +9,63 @@ import { WebGLUniforms } from './WebGLUniforms.js'; | ||
constructor(gl, vshader, fshader) { | ||
// create shaders | ||
this.gl = gl; | ||
this.vshaderSource = vshader; | ||
this.fshaderSource = fshader; | ||
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader); | ||
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader); | ||
this.id = programIdCount++; | ||
this.usedTimes = 1; | ||
// create a program object | ||
this.code = ""; | ||
const program = gl.createProgram(); | ||
gl.attachShader(program, vertexShader); | ||
gl.attachShader(program, fragmentShader); | ||
gl.linkProgram(program); | ||
this.lightId = -1; | ||
this.lightVersion = -1; | ||
this.cameraId = -1; | ||
this.cameraVersion = -1; | ||
this.sceneId = -1; | ||
this.sceneVersion = -1; | ||
// check errors | ||
this.program; | ||
if (gl.getProgramParameter(program, gl.LINK_STATUS) === false) { | ||
const programLog = gl.getProgramInfoLog(program).trim(); | ||
// compile program | ||
const vertexErrors = getShaderErrors(gl, vertexShader, 'VERTEX'); | ||
const fragmentErrors = getShaderErrors(gl, fragmentShader, 'FRAGMENT'); | ||
let program; | ||
console.error( | ||
'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + | ||
'VALIDATE_STATUS ' + gl.getProgramParameter(program, gl.VALIDATE_STATUS) + '\n\n' + | ||
'Program Info Log: ' + programLog + '\n' + | ||
vertexErrors + '\n' + | ||
fragmentErrors | ||
) | ||
} | ||
this.compile = function(checkErrors) { | ||
// create shaders | ||
// here we can delete shaders, | ||
// according to the documentation: https://www.opengl.org/sdk/docs/man/html/glLinkProgram.xhtml | ||
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader); | ||
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader); | ||
gl.deleteShader(vertexShader); | ||
gl.deleteShader(fragmentShader); | ||
// create a program object | ||
program = gl.createProgram(); | ||
gl.attachShader(program, vertexShader); | ||
gl.attachShader(program, fragmentShader); | ||
gl.linkProgram(program); | ||
// check errors | ||
if (checkErrors && gl.getProgramParameter(program, gl.LINK_STATUS) === false) { | ||
const programLog = gl.getProgramInfoLog(program).trim(); | ||
const vertexErrors = getShaderErrors(gl, vertexShader, 'VERTEX'); | ||
const fragmentErrors = getShaderErrors(gl, fragmentShader, 'FRAGMENT'); | ||
console.error( | ||
'Shader Error ' + gl.getError() + ' - ' + | ||
'VALIDATE_STATUS ' + gl.getProgramParameter(program, gl.VALIDATE_STATUS) + '\n\n' + | ||
'Program Info Log: ' + programLog + '\n' + | ||
vertexErrors + '\n' + | ||
fragmentErrors | ||
) | ||
} else { | ||
this.program = program; | ||
} | ||
// here we can delete shaders, | ||
// according to the documentation: https://www.opengl.org/sdk/docs/man/html/glLinkProgram.xhtml | ||
gl.deleteShader(vertexShader); | ||
gl.deleteShader(fragmentShader); | ||
} | ||
// set up caching for uniforms | ||
@@ -73,12 +99,2 @@ | ||
} | ||
// | ||
this.id = programIdCount++; | ||
this.usedTimes = 1; | ||
this.code = ""; | ||
this.gl = gl; | ||
this.vshaderSource = vshader; | ||
this.fshaderSource = fshader; | ||
this.program = program; | ||
} | ||
@@ -85,0 +101,0 @@ |
@@ -16,3 +16,3 @@ import { WebGLProgram } from './WebGLProgram.js'; | ||
getProgram(material, object, renderStates) { | ||
getProgram(material, object, renderStates, checkErrors) { | ||
const programs = this._programs; | ||
@@ -40,2 +40,3 @@ | ||
program = createProgram(this._gl, customDefines, props, vertexShader, fragmentShader); | ||
program.compile(checkErrors); | ||
program.code = code; | ||
@@ -42,0 +43,0 @@ |
class WebGLProperties { | ||
constructor() { | ||
this._map = new WeakMap(); | ||
constructor(passId) { | ||
this._key = '__webgl$' + passId; | ||
this._count = 0; | ||
} | ||
get(object) { | ||
let properties = this._map.get(object); | ||
const key = this._key; | ||
let properties = object[key]; | ||
if (properties === undefined) { | ||
properties = {}; | ||
this._map.set(object, properties); | ||
object[key] = properties; | ||
this._count++; | ||
} | ||
@@ -17,7 +20,11 @@ return properties; | ||
delete(object) { | ||
this._map.delete(object); | ||
const properties = object[key]; | ||
if (properties) { | ||
this._count--; | ||
delete object[key]; | ||
} | ||
} | ||
clear() { | ||
this._map = new WeakMap(); | ||
size() { | ||
return this._count; | ||
} | ||
@@ -24,0 +31,0 @@ |
import { QUERY_TYPE } from '../const.js'; | ||
import { WebGLProperties } from './WebGLProperties.js'; | ||
class WebGLQueries { | ||
class WebGLQueries extends WebGLProperties { | ||
constructor(gl, capabilities) { | ||
constructor(passId, gl, capabilities) { | ||
super(passId); | ||
this._gl = gl; | ||
@@ -10,10 +13,8 @@ this._capabilities = capabilities; | ||
const timerQuery = capabilities.timerQuery; | ||
const that = this; | ||
this._map = new WeakMap(); | ||
const onQueryDispose = (event) => { | ||
const query = event.target; | ||
const queryProperties = that.get(query); | ||
const queryProperties = this._map.get(query); | ||
query.removeEventListener('dispose', onQueryDispose); | ||
@@ -29,3 +30,3 @@ | ||
this._map.delete(query); | ||
that.delete(query); | ||
} | ||
@@ -42,10 +43,8 @@ | ||
get(query) { | ||
_get(query) { | ||
const capabilities = this._capabilities; | ||
const map = this._map; | ||
let queryProperties = map.get(query); | ||
const queryProperties = this.get(query); | ||
if (queryProperties === undefined) { | ||
queryProperties = {}; | ||
if (queryProperties._webglQuery === undefined) { | ||
query.addEventListener('dispose', this._onQueryDispose); | ||
@@ -56,4 +55,2 @@ | ||
queryProperties._result = null; | ||
map.set(query, queryProperties); | ||
} | ||
@@ -64,6 +61,2 @@ | ||
clear() { | ||
this._map = new WeakMap(); | ||
} | ||
begin(query, target) { | ||
@@ -73,3 +66,3 @@ const capabilities = this._capabilities; | ||
const queryProperties = this.get(query); | ||
const queryProperties = this._get(query); | ||
@@ -90,3 +83,3 @@ if (capabilities.version > 1) { | ||
const queryProperties = this.get(query); | ||
const queryProperties = this._get(query); | ||
@@ -103,3 +96,3 @@ if (capabilities.version > 1) { | ||
const queryProperties = this.get(query); | ||
const queryProperties = this._get(query); | ||
@@ -117,3 +110,3 @@ timerQuery.queryCounterEXT(queryProperties._webglQuery, timerQuery.TIMESTAMP_EXT); | ||
const queryProperties = this.get(query); | ||
const queryProperties = this._get(query); | ||
@@ -139,3 +132,3 @@ let available; | ||
const queryProperties = this.get(query); | ||
const queryProperties = this._get(query); | ||
@@ -142,0 +135,0 @@ if (queryProperties._result === null) { |
@@ -1,9 +0,14 @@ | ||
class WebGLRenderBuffers { | ||
import { WebGLProperties } from './WebGLProperties.js'; | ||
constructor(gl, properties, capabilities, constants) { | ||
this.gl = gl; | ||
this.properties = properties; | ||
this.capabilities = capabilities; | ||
this.constants = constants; | ||
class WebGLRenderBuffers extends WebGLProperties { | ||
constructor(passId, gl, capabilities, constants) { | ||
super(passId); | ||
this._gl = gl; | ||
this._capabilities = capabilities; | ||
this._constants = constants; | ||
const that = this; | ||
function onRenderBufferDispose(event) { | ||
@@ -14,3 +19,3 @@ const renderBuffer = event.target; | ||
const renderBufferProperties = properties.get(renderBuffer); | ||
const renderBufferProperties = that.get(renderBuffer); | ||
@@ -21,3 +26,3 @@ if (renderBufferProperties.__webglRenderbuffer && !renderBufferProperties.__external) { | ||
properties.delete(renderBuffer); | ||
that.delete(renderBuffer); | ||
} | ||
@@ -29,7 +34,7 @@ | ||
setRenderBuffer(renderBuffer) { | ||
const gl = this.gl; | ||
const capabilities = this.capabilities; | ||
const constants = this.constants; | ||
const gl = this._gl; | ||
const capabilities = this._capabilities; | ||
const constants = this._constants; | ||
const renderBufferProperties = this.properties.get(renderBuffer); | ||
const renderBufferProperties = this.get(renderBuffer); | ||
@@ -61,5 +66,5 @@ if (renderBufferProperties.__webglRenderbuffer === undefined) { | ||
setRenderBufferExternal(renderBuffer, webglRenderbuffer) { | ||
const gl = this.gl; | ||
const gl = this._gl; | ||
const renderBufferProperties = this.properties.get(renderBuffer); | ||
const renderBufferProperties = this.get(renderBuffer); | ||
@@ -66,0 +71,0 @@ if (!renderBufferProperties.__external) { |
import { WebGLPrograms } from './WebGLPrograms.js'; | ||
import { WebGLProperties } from './WebGLProperties.js'; | ||
import { WebGLCapabilities } from './WebGLCapabilities.js'; | ||
@@ -9,3 +8,5 @@ import { WebGLConstants } from './WebGLConstants.js'; | ||
import { WebGLRenderTargets } from './WebGLRenderTargets.js'; | ||
import { WebGLBuffers } from './WebGLBuffers.js'; | ||
import { WebGLGeometries } from './WebGLGeometries.js'; | ||
import { WebGLMaterials } from './WebGLMaterials.js'; | ||
import { WebGLVertexArrayBindings } from './WebGLVertexArrayBindings.js'; | ||
@@ -38,18 +39,4 @@ import { WebGLQueries } from './WebGLQueries.js'; | ||
function onMaterialDispose(event) { | ||
const material = event.target; | ||
const materialProperties = this._properties.get(material); | ||
let _renderPassId = 0; | ||
material.removeEventListener('dispose', onMaterialDispose, this); | ||
const program = materialProperties.program; | ||
if (program !== undefined) { | ||
// release program reference | ||
this._programs.releaseProgram(program); | ||
} | ||
this._properties.delete(material); | ||
} | ||
/** | ||
@@ -65,16 +52,20 @@ * WebGL Render Pass | ||
constructor(gl) { | ||
this.gl = gl; | ||
const id = _renderPassId++; | ||
const properties = new WebGLProperties(); | ||
const capabilities = new WebGLCapabilities(gl); | ||
const constants = new WebGLConstants(gl, capabilities); | ||
const state = new WebGLState(gl, capabilities); | ||
const vertexArrayBindings = new WebGLVertexArrayBindings(gl, properties, capabilities); | ||
const textures = new WebGLTextures(gl, state, properties, capabilities, constants); | ||
const renderBuffers = new WebGLRenderBuffers(gl, properties, capabilities, constants); | ||
const renderTargets = new WebGLRenderTargets(gl, state, textures, renderBuffers, properties, capabilities, constants); | ||
const geometries = new WebGLGeometries(gl, properties, capabilities, vertexArrayBindings); | ||
const textures = new WebGLTextures(id, gl, state, capabilities, constants); | ||
const renderBuffers = new WebGLRenderBuffers(id, gl, capabilities, constants); | ||
const renderTargets = new WebGLRenderTargets(id, gl, state, capabilities, textures, renderBuffers, constants); | ||
const buffers = new WebGLBuffers(id, gl, capabilities); | ||
const vertexArrayBindings = new WebGLVertexArrayBindings(id, gl, capabilities, buffers); | ||
const geometries = new WebGLGeometries(id, gl, buffers, vertexArrayBindings); | ||
const programs = new WebGLPrograms(gl, state, capabilities); | ||
const queries = new WebGLQueries(gl, capabilities); | ||
const materials = new WebGLMaterials(id, programs); | ||
const queries = new WebGLQueries(id, gl, capabilities); | ||
this.id = id; | ||
this.gl = gl; | ||
/** | ||
@@ -86,8 +77,9 @@ * An object containing details about the capabilities of the current RenderingContext. | ||
this._properties = properties; | ||
this._textures = textures; | ||
this._renderBuffers = renderBuffers; | ||
this._renderTargets = renderTargets; | ||
this._buffers = buffers; | ||
this._geometries = geometries; | ||
this._programs = programs; | ||
this._materials = materials; | ||
this._state = state; | ||
@@ -212,3 +204,3 @@ this._vertexArrayBindings = vertexArrayBindings; | ||
setBufferExternal(buffer, webglBuffer) { | ||
this._geometries.setBufferExternal(buffer, webglBuffer); | ||
this._buffers.setBufferExternal(buffer, webglBuffer); | ||
} | ||
@@ -329,3 +321,3 @@ | ||
const materialProperties = this._properties.get(material); | ||
const materialProperties = this._materials.setMaterial(material); | ||
if (material.needsUpdate === false) { | ||
@@ -364,8 +356,4 @@ if (materialProperties.program === undefined) { | ||
if (material.needsUpdate) { | ||
if (materialProperties.program === undefined) { | ||
material.addEventListener('dispose', onMaterialDispose, this); | ||
} | ||
const oldProgram = materialProperties.program; | ||
materialProperties.program = this._programs.getProgram(material, object, renderStates); | ||
materialProperties.program = this._programs.getProgram(material, object, renderStates, true); | ||
if (oldProgram) { | ||
@@ -393,2 +381,5 @@ this._programs.releaseProgram(oldProgram); // release after new program is created. | ||
const program = materialProperties.program; | ||
if (program.program === undefined) return; | ||
state.setProgram(program); | ||
@@ -405,10 +396,28 @@ | ||
// update uniforms | ||
let refreshLights = false; | ||
if (program.lightId !== lightData.id || program.lightVersion !== lightData.version) { | ||
refreshLights = true; | ||
program.lightId = lightData.id; | ||
program.lightVersion = lightData.version; | ||
} | ||
let refreshCamera = false; | ||
if (program.cameraId !== cameraData.id || program.cameraVersion !== cameraData.version) { | ||
refreshCamera = true; | ||
program.cameraId = cameraData.id; | ||
program.cameraVersion = cameraData.version; | ||
} | ||
let refreshScene = false; | ||
if (program.sceneId !== sceneData.id || program.sceneVersion !== sceneData.version) { | ||
refreshScene = true; | ||
program.sceneId = sceneData.id; | ||
program.sceneVersion = sceneData.version; | ||
} | ||
const uniforms = program.getUniforms(); | ||
// upload light uniforms | ||
// shadow map need upload first ? | ||
// or it will cause bug | ||
if (material.acceptLight) { | ||
this._uploadLights(uniforms, lightData, sceneData.disableShadowSampler); | ||
this._uploadLights(uniforms, lightData, sceneData.disableShadowSampler, refreshLights); | ||
} | ||
@@ -425,2 +434,3 @@ | ||
const key = uniform.id; | ||
const internalGroup = uniform.internalGroup; | ||
@@ -433,169 +443,44 @@ // upload custom uniforms | ||
let modelMatrix, color, scale; | ||
// u_Model: always upload this matrix | ||
if (internalGroup === 1) { | ||
let modelMatrix = object.worldMatrix; | ||
if (sceneData.useAnchorMatrix) { | ||
modelMatrix = helpMatrix4.copy(modelMatrix).premultiply(sceneData.anchorMatrixInverse); | ||
} | ||
uniform.set(modelMatrix.elements); | ||
continue; | ||
} | ||
switch (key) { | ||
// pvm matrix | ||
case "u_Projection": | ||
uniform.set(cameraData.projectionMatrix.elements); | ||
break; | ||
case "u_View": | ||
uniform.set(cameraData.viewMatrix.elements); | ||
break; | ||
case "u_Model": | ||
modelMatrix = object.worldMatrix; | ||
if (sceneData.useAnchorMatrix) { | ||
modelMatrix = helpMatrix4.copy(modelMatrix).premultiply(sceneData.anchorMatrixInverse); | ||
} | ||
uniform.set(modelMatrix.elements); | ||
break; | ||
case "u_ProjectionView": | ||
uniform.set(cameraData.projectionViewMatrix.elements); | ||
break; | ||
// uniforms about camera data | ||
if (internalGroup === 2 && refreshCamera) { | ||
uniform.internalFun(cameraData); | ||
continue; | ||
} | ||
case "u_CameraPosition": | ||
uniform.setValue(cameraData.position.x, cameraData.position.y, cameraData.position.z); | ||
break; | ||
// uniforms about scene data | ||
if (internalGroup === 3 && refreshScene) { | ||
uniform.internalFun(sceneData); | ||
continue; | ||
} | ||
case "u_Color": | ||
color = material.diffuse; | ||
uniform.setValue(color.r, color.g, color.b); | ||
break; | ||
case "u_Opacity": | ||
uniform.set(material.opacity); | ||
break; | ||
// uniforms about material | ||
if (internalGroup === 4) { | ||
uniform.internalFun(material, textures); | ||
continue; | ||
} | ||
case "diffuseMap": | ||
uniform.set(material.diffuseMap, textures); | ||
break; | ||
case "alphaMap": | ||
uniform.set(material.alphaMap, textures); | ||
break; | ||
case "alphaMapUVTransform": | ||
uniform.set(material.alphaMapTransform.elements); | ||
break; | ||
case "normalMap": | ||
uniform.set(material.normalMap, textures); | ||
break; | ||
case "normalScale": | ||
uniform.setValue(material.normalScale.x, material.normalScale.y); | ||
break; | ||
case "bumpMap": | ||
uniform.set(material.bumpMap, textures); | ||
break; | ||
case "bumpScale": | ||
uniform.set(material.bumpScale); | ||
break; | ||
case "envMap": | ||
uniform.set(envMap, textures); | ||
break; | ||
case "cubeMap": | ||
uniform.set(material.cubeMap, textures); | ||
break; | ||
case "u_EnvMap_Flip": | ||
uniform.set((envMap.images[0] && envMap.images[0].rtt) ? 1 : -1); | ||
break; | ||
case "u_EnvMap_Intensity": | ||
uniform.set(material.envMapIntensity); | ||
break; | ||
case "u_EnvMapLight_Intensity": | ||
uniform.set(sceneData.environmentLightIntensity); | ||
break; | ||
case "maxMipLevel": | ||
uniform.set(this._properties.get(envMap).__maxMipLevel || 8); // TODO replace 8 with real mip level | ||
break; | ||
case "u_Specular": | ||
uniform.set(material.shininess); | ||
break; | ||
case "u_SpecularColor": | ||
color = material.specular; | ||
uniform.setValue(color.r, color.g, color.b); | ||
break; | ||
case "specularMap": | ||
uniform.set(material.specularMap, textures); | ||
break; | ||
case "aoMap": | ||
uniform.set(material.aoMap, textures); | ||
break; | ||
case "aoMapIntensity": | ||
uniform.set(material.aoMapIntensity); | ||
break; | ||
case "aoMapUVTransform": | ||
uniform.set(material.aoMapTransform.elements); | ||
break; | ||
case "u_Roughness": | ||
uniform.set(material.roughness); | ||
break; | ||
case "roughnessMap": | ||
uniform.set(material.roughnessMap, textures); | ||
break; | ||
case "u_Metalness": | ||
uniform.set(material.metalness); | ||
break; | ||
case "metalnessMap": | ||
uniform.set(material.metalnessMap, textures); | ||
break; | ||
case "glossiness": | ||
uniform.set(material.glossiness); | ||
break; | ||
case "glossinessMap": | ||
uniform.set(material.glossinessMap, textures); | ||
break; | ||
case "emissive": | ||
color = material.emissive; | ||
uniform.setValue(color.r, color.g, color.b); | ||
break; | ||
case "emissiveMap": | ||
uniform.set(material.emissiveMap, textures); | ||
break; | ||
case "emissiveMapUVTransform": | ||
uniform.set(material.emissiveMapTransform.elements); | ||
break; | ||
case "u_FogColor": | ||
color = sceneData.fog.color; | ||
uniform.setValue(color.r, color.g, color.b); | ||
break; | ||
case "u_FogDensity": | ||
uniform.set(sceneData.fog.density); | ||
break; | ||
case "u_FogNear": | ||
uniform.set(sceneData.fog.near); | ||
break; | ||
case "u_FogFar": | ||
uniform.set(sceneData.fog.far); | ||
break; | ||
case "logDepthBufFC": | ||
uniform.set(renderStates.logDepthBufFC); | ||
break; | ||
case "logDepthCameraNear": | ||
uniform.set(renderStates.logDepthCameraNear); | ||
break; | ||
case "u_PointSize": | ||
uniform.set(material.size); | ||
break; | ||
case "u_PointScale": | ||
scale = currentRenderTarget.height * 0.5; // three.js do this | ||
// other internal uniforms | ||
if (internalGroup === 5) { | ||
if (key === 'u_PointScale') { | ||
const scale = currentRenderTarget.height * 0.5; // three.js do this | ||
uniform.set(scale); | ||
break; | ||
case "dashSize": | ||
uniform.set(material.dashSize); | ||
break; | ||
case "totalSize": | ||
uniform.set(material.dashSize + material.gapSize); | ||
break; | ||
case "scale": | ||
uniform.set(material.scale); | ||
break; | ||
case "matcap": | ||
uniform.set(material.matcap, textures); | ||
break; | ||
case "clippingPlanes": | ||
uniform.set(clippingPlanesData); | ||
break; | ||
case "uvTransform": | ||
uniform.set(material.diffuseMapTransform.elements); | ||
break; | ||
default: | ||
break; | ||
} else { | ||
uniform.internalFun(envMap, textures); | ||
} | ||
continue; | ||
} | ||
if (key === 'clippingPlanes') { | ||
uniform.set(clippingPlanesData); | ||
} | ||
} | ||
@@ -637,10 +522,10 @@ | ||
_uploadLights(uniforms, lights, disableShadowSampler) { | ||
_uploadLights(uniforms, lights, disableShadowSampler, refresh) { | ||
const textures = this._textures; | ||
if (lights.useAmbient) { | ||
if (lights.useAmbient && refresh) { | ||
uniforms.set("u_AmbientLightColor", lights.ambient); | ||
} | ||
if (lights.hemisNum > 0) { | ||
if (lights.hemisNum > 0 && refresh) { | ||
uniforms.set("u_Hemi", lights.hemisphere); | ||
@@ -650,6 +535,6 @@ } | ||
if (lights.directsNum > 0) { | ||
uniforms.set("u_Directional", lights.directional); | ||
if (refresh) uniforms.set("u_Directional", lights.directional); | ||
if (lights.directShadowNum > 0) { | ||
uniforms.set("u_DirectionalShadow", lights.directionalShadow); | ||
if (refresh) uniforms.set("u_DirectionalShadow", lights.directionalShadow); | ||
@@ -672,6 +557,6 @@ if (uniforms.has("directionalShadowMap")) { | ||
if (lights.pointsNum > 0) { | ||
uniforms.set("u_Point", lights.point); | ||
if (refresh) uniforms.set("u_Point", lights.point); | ||
if (lights.pointShadowNum > 0) { | ||
uniforms.set("u_PointShadow", lights.pointShadow); | ||
if (refresh) uniforms.set("u_PointShadow", lights.pointShadow); | ||
@@ -686,6 +571,6 @@ if (uniforms.has("pointShadowMap")) { | ||
if (lights.spotsNum > 0) { | ||
uniforms.set("u_Spot", lights.spot); | ||
if (refresh) uniforms.set("u_Spot", lights.spot); | ||
if (lights.spotShadowNum > 0) { | ||
uniforms.set("u_SpotShadow", lights.spotShadow); | ||
if (refresh) uniforms.set("u_SpotShadow", lights.spotShadow); | ||
@@ -791,4 +676,4 @@ if (uniforms.has("spotShadowMap")) { | ||
const gl = this.gl; | ||
const properties = this._properties; | ||
const capabilities = this.capabilities; | ||
const buffers = this._buffers; | ||
@@ -808,3 +693,3 @@ const useIndexBuffer = geometry.index !== null; | ||
if (useIndexBuffer) { | ||
const indexBufferProperties = properties.get(geometry.index.buffer); | ||
const indexBufferProperties = buffers.get(geometry.index.buffer); | ||
const bytesPerElement = indexBufferProperties.bytesPerElement; | ||
@@ -811,0 +696,0 @@ const type = indexBufferProperties.type; |
import { ATTACHMENT, TEXTURE_FILTER } from '../const.js'; | ||
import { isPowerOfTwo } from '../base.js'; | ||
import { WebGLProperties } from './WebGLProperties.js'; | ||
class WebGLRenderTargets { | ||
class WebGLRenderTargets extends WebGLProperties { | ||
constructor(gl, state, textures, renderBuffers, properties, capabilities, constants) { | ||
constructor(passId, gl, state, capabilities, textures, renderBuffers, constants) { | ||
super(passId); | ||
this._gl = gl; | ||
this._state = state; | ||
this._capabilities = capabilities; | ||
this._textures = textures; | ||
this._renderBuffers = renderBuffers; | ||
this._properties = properties; | ||
this._capabilities = capabilities; | ||
this._constants = constants; | ||
const that = this; | ||
function onRenderTargetDispose(event) { | ||
@@ -20,3 +24,3 @@ const renderTarget = event.target; | ||
const renderTargetProperties = properties.get(renderTarget); | ||
const renderTargetProperties = that.get(renderTarget); | ||
@@ -27,3 +31,3 @@ if (renderTargetProperties.__webglFramebuffer) { | ||
properties.delete(renderTarget); | ||
that.delete(renderTarget); | ||
@@ -45,3 +49,3 @@ if (state.currentRenderTarget === renderTarget) { | ||
const renderTargetProperties = this._properties.get(renderTarget); | ||
const renderTargetProperties = this.get(renderTarget); | ||
@@ -101,3 +105,3 @@ renderTarget.addEventListener('dispose', this._onRenderTargetDispose); | ||
const state = this._state; | ||
const properties = this._properties; | ||
const textures = this._textures; | ||
@@ -110,3 +114,3 @@ let renderTargetProperties; | ||
} else { | ||
renderTargetProperties = properties.get(renderTarget); | ||
renderTargetProperties = this.get(renderTarget); | ||
@@ -123,3 +127,3 @@ if (renderTargetProperties.__webglFramebuffer === undefined) { | ||
if (renderTarget.isRenderTargetCube) { | ||
renderTargetProperties = properties.get(renderTarget); | ||
renderTargetProperties = this.get(renderTarget); | ||
const activeCubeFace = renderTarget.activeCubeFace; | ||
@@ -130,3 +134,3 @@ if (renderTargetProperties.__currentActiveCubeFace !== activeCubeFace) { | ||
if (attachment.isTextureCube) { | ||
const textureProperties = properties.get(attachment); | ||
const textureProperties = textures.get(attachment); | ||
gl.framebufferTexture2D(gl.FRAMEBUFFER, attachTargetToGL[attachTarget], gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, 0); | ||
@@ -142,3 +146,2 @@ } | ||
const gl = this._gl; | ||
const properties = this._properties; | ||
const capabilities = this._capabilities; | ||
@@ -151,4 +154,4 @@ | ||
const readBuffer = properties.get(read).__webglFramebuffer; | ||
const drawBuffer = properties.get(draw).__webglFramebuffer; | ||
const readBuffer = this.get(read).__webglFramebuffer; | ||
const drawBuffer = this.get(draw).__webglFramebuffer; | ||
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readBuffer); | ||
@@ -202,3 +205,3 @@ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, drawBuffer); | ||
const webglTexture = this._properties.get(texture).__webglTexture; | ||
const webglTexture = this._textures.get(texture).__webglTexture; | ||
@@ -205,0 +208,0 @@ state.bindTexture(glTarget, webglTexture); |
import { TEXTURE_FILTER, TEXTURE_WRAP } from '../const.js'; | ||
import { isPowerOfTwo, nearestPowerOfTwo } from '../base.js'; | ||
import { WebGLProperties } from './WebGLProperties.js'; | ||
class WebGLTextures { | ||
class WebGLTextures extends WebGLProperties { | ||
constructor(gl, state, properties, capabilities, constants) { | ||
this.gl = gl; | ||
this.state = state; | ||
this.properties = properties; | ||
this.capabilities = capabilities; | ||
this.constants = constants; | ||
constructor(passId, gl, state, capabilities, constants) { | ||
super(passId); | ||
this._gl = gl; | ||
this._state = state; | ||
this._capabilities = capabilities; | ||
this._constants = constants; | ||
this._usedTextureUnits = 0; | ||
const that = this; | ||
function onTextureDispose(event) { | ||
const texture = event.target; | ||
const textureProperties = properties.get(texture); | ||
const textureProperties = that.get(texture); | ||
@@ -25,3 +29,3 @@ texture.removeEventListener('dispose', onTextureDispose); | ||
properties.delete(texture); | ||
that.delete(texture); | ||
} | ||
@@ -50,4 +54,4 @@ | ||
if (textureUnit >= this.capabilities.maxTextures) { | ||
console.warn('trying to use ' + textureUnit + ' texture units while this GPU supports only ' + this.capabilities.maxTextures); | ||
if (textureUnit >= this._capabilities.maxTextures) { | ||
console.warn('trying to use ' + textureUnit + ' texture units while this GPU supports only ' + this._capabilities.maxTextures); | ||
} | ||
@@ -63,6 +67,6 @@ | ||
setTexture2D(texture, slot) { | ||
const gl = this.gl; | ||
const state = this.state; | ||
const capabilities = this.capabilities; | ||
const constants = this.constants; | ||
const gl = this._gl; | ||
const state = this._state; | ||
const capabilities = this._capabilities; | ||
const constants = this._constants; | ||
@@ -73,3 +77,3 @@ if (slot !== undefined) { | ||
const textureProperties = this.properties.get(texture); | ||
const textureProperties = this.get(texture); | ||
@@ -159,6 +163,6 @@ if (texture.image && textureProperties.__version !== texture.version && (!texture.image.rtt || slot === undefined) && !textureProperties.__external) { | ||
setTextureCube(texture, slot) { | ||
const gl = this.gl; | ||
const state = this.state; | ||
const capabilities = this.capabilities; | ||
const constants = this.constants; | ||
const gl = this._gl; | ||
const state = this._state; | ||
const capabilities = this._capabilities; | ||
const constants = this._constants; | ||
@@ -169,3 +173,3 @@ if (slot !== undefined) { | ||
const textureProperties = this.properties.get(texture); | ||
const textureProperties = this.get(texture); | ||
@@ -271,6 +275,6 @@ if (texture.images.length === 6 && textureProperties.__version !== texture.version && (!texture.images[0].rtt || slot === undefined) && !textureProperties.__external) { | ||
setTexture3D(texture, slot) { | ||
const gl = this.gl; | ||
const state = this.state; | ||
const capabilities = this.capabilities; | ||
const constants = this.constants; | ||
const gl = this._gl; | ||
const state = this._state; | ||
const capabilities = this._capabilities; | ||
const constants = this._constants; | ||
@@ -286,3 +290,3 @@ if (capabilities.version < 2) { | ||
const textureProperties = this.properties.get(texture); | ||
const textureProperties = this.get(texture); | ||
@@ -329,5 +333,5 @@ if (texture.image && textureProperties.__version !== texture.version && !textureProperties.__external) { | ||
setTextureExternal(texture, webglTexture) { | ||
const gl = this.gl; | ||
const gl = this._gl; | ||
const textureProperties = this.properties.get(texture); | ||
const textureProperties = this.get(texture); | ||
@@ -347,4 +351,4 @@ if (!textureProperties.__external) { | ||
_setTextureParameters(texture, needFallback) { | ||
const gl = this.gl; | ||
const capabilities = this.capabilities; | ||
const gl = this._gl; | ||
const capabilities = this._capabilities; | ||
@@ -387,7 +391,7 @@ const wrappingToGL = this._wrappingToGL; | ||
_generateMipmap(target, texture, width, height) { | ||
const gl = this.gl; | ||
const gl = this._gl; | ||
gl.generateMipmap(target); | ||
const textureProperties = this.properties.get(texture); | ||
const textureProperties = this.get(texture); | ||
// Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11 | ||
@@ -394,0 +398,0 @@ textureProperties.__maxMipLevel = Math.log(Math.max(width, height)) * Math.LOG2E; |
@@ -6,2 +6,52 @@ import { PIXEL_TYPE, PIXEL_FORMAT, TEXTURE_FILTER, COMPARE_FUNC } from '../const.js'; | ||
// Build-in uniforms | ||
const internalUniforms = { | ||
'u_Model': [1, null], | ||
'u_Projection': [2, function(cameraData) { this.set(cameraData.projectionMatrix.elements) }], | ||
'u_View': [2, function(cameraData) { this.set(cameraData.viewMatrix.elements) }], | ||
'u_ProjectionView': [2, function(cameraData) { this.set(cameraData.projectionViewMatrix.elements) }], | ||
'u_CameraPosition': [2, function(cameraData) { this.setValue(cameraData.position.x, cameraData.position.y, cameraData.position.z) }], | ||
'logDepthBufFC': [2, function(cameraData) { this.set(cameraData.logDepthBufFC) }], | ||
'logDepthCameraNear': [2, function(cameraData) { this.set(cameraData.logDepthCameraNear) }], | ||
'u_EnvMapLight_Intensity': [3, function(sceneData) { this.set(sceneData.environmentLightIntensity) }], | ||
'u_FogColor': [3, function(sceneData) { const color = sceneData.fog.color; this.setValue(color.r, color.g, color.b) }], | ||
'u_FogDensity': [3, function(sceneData) { this.set(sceneData.fog.density) }], | ||
'u_FogNear': [3, function(sceneData) { this.set(sceneData.fog.near) }], | ||
'u_FogFar': [3, function(sceneData) { this.set(sceneData.fog.far) }], | ||
'u_Color': [4, function(material, textures) { const color = material.diffuse; this.setValue(color.r, color.g, color.b) }], | ||
'u_Opacity': [4, function(material, textures) { this.set(material.opacity) }], | ||
'diffuseMap': [4, function(material, textures) { this.set(material.diffuseMap, textures) }], | ||
'alphaMap': [4, function(material, textures) { this.set(material.alphaMap, textures) }], | ||
'alphaMapUVTransform': [4, function(material, textures) { this.set(material.alphaMapTransform.elements) }], | ||
'normalMap': [4, function(material, textures) { this.set(material.normalMap, textures) }], | ||
'normalScale': [4, function(material, textures) { this.setValue(material.normalScale.x, material.normalScale.y) }], | ||
'bumpMap': [4, function(material, textures) { this.set(material.bumpMap, textures) }], | ||
'bumpScale': [4, function(material, textures) { this.set(material.bumpScale) }], | ||
'cubeMap': [4, function(material, textures) { this.set(material.cubeMap, textures) }], | ||
'u_EnvMap_Intensity': [4, function(material, textures) { this.set(material.envMapIntensity) }], | ||
'u_Specular': [4, function(material, textures) { this.set(material.shininess) }], | ||
'u_SpecularColor': [4, function(material, textures) { const color = material.specular; this.setValue(color.r, color.g, color.b) }], | ||
'specularMap': [4, function(material, textures) { this.set(material.specularMap, textures) }], | ||
'aoMap': [4, function(material, textures) { this.set(material.aoMap, textures) }], | ||
'aoMapIntensity': [4, function(material, textures) { this.set(material.aoMapIntensity) }], | ||
'aoMapUVTransform': [4, function(material, textures) { this.set(material.aoMapTransform.elements) }], | ||
'u_Roughness': [4, function(material, textures) { this.set(material.roughness) }], | ||
'roughnessMap': [4, function(material, textures) { this.set(material.roughnessMap, textures) }], | ||
'u_Metalness': [4, function(material, textures) { this.set(material.metalness) }], | ||
'metalnessMap': [4, function(material, textures) { this.set(material.metalnessMap, textures) }], | ||
'glossiness': [4, function(material, textures) { this.set(material.glossiness) }], | ||
'glossinessMap': [4, function(material, textures) { this.set(material.glossinessMap, textures) }], | ||
'emissive': [4, function(material, textures) { const color = material.emissive; this.setValue(color.r, color.g, color.b) }], | ||
'emissiveMap': [4, function(material, textures) { this.set(material.emissiveMap, textures) }], | ||
'emissiveMapUVTransform': [4, function(material, textures) { this.set(material.emissiveMapTransform.elements) }], | ||
'matcap': [4, function(material, textures) { this.set(material.matcap, textures) }], | ||
'uvTransform': [4, function(material, textures) { this.set(material.diffuseMapTransform.elements) }], | ||
'u_PointSize': [4, function(material, textures) { this.set(material.size) }], | ||
'u_PointScale': [5, null], | ||
'maxMipLevel': [5, function(envMap, textures) { this.set(textures.get(envMap).__maxMipLevel || 8) }], // TODO replace 8 with real mip level | ||
'envMap': [5, function(envMap, textures) { this.set(envMap, textures) }], | ||
'u_EnvMap_Flip': [5, function(envMap, textures) { this.set((envMap.images[0] && envMap.images[0].rtt) ? 1 : -1) }] | ||
}; | ||
// Empty textures | ||
@@ -187,5 +237,7 @@ | ||
uniform.set = function(value) { | ||
if (arraysEqual(cache, value)) return; | ||
gl.uniform2fv(location, value); | ||
copyArray(cache, value); | ||
if (cache[0] !== value[0] || cache[1] !== value[1]) { | ||
gl.uniform2fv(location, value); | ||
cache[0] = value[0]; | ||
cache[1] = value[1]; | ||
} | ||
} | ||
@@ -203,5 +255,7 @@ break; | ||
uniform.set = function(value) { | ||
if (arraysEqual(cache, value)) return; | ||
gl.uniform2iv(location, value); | ||
copyArray(cache, value); | ||
if (cache[0] !== value[0] || cache[1] !== value[1]) { | ||
gl.uniform2iv(location, value); | ||
cache[0] = value[0]; | ||
cache[1] = value[1]; | ||
} | ||
} | ||
@@ -219,5 +273,8 @@ break; | ||
uniform.set = function(value) { | ||
if (arraysEqual(cache, value)) return; | ||
gl.uniform3fv(location, value); | ||
copyArray(cache, value); | ||
if (cache[0] !== value[0] || cache[1] !== value[1] || cache[2] !== value[2]) { | ||
gl.uniform3fv(location, value); | ||
cache[0] = value[0]; | ||
cache[1] = value[1]; | ||
cache[2] = value[2]; | ||
} | ||
} | ||
@@ -236,5 +293,8 @@ break; | ||
uniform.set = function(value) { | ||
if (arraysEqual(cache, value)) return; | ||
gl.uniform3iv(location, value); | ||
copyArray(cache, value); | ||
if (cache[0] !== value[0] || cache[1] !== value[1] || cache[2] !== value[2]) { | ||
gl.uniform3iv(location, value); | ||
cache[0] = value[0]; | ||
cache[1] = value[1]; | ||
cache[2] = value[2]; | ||
} | ||
} | ||
@@ -253,5 +313,9 @@ break; | ||
uniform.set = function(value) { | ||
if (arraysEqual(cache, value)) return; | ||
gl.uniform4fv(location, value); | ||
copyArray(cache, value); | ||
if (cache[0] !== value[0] || cache[1] !== value[1] || cache[2] !== value[2] || cache[3] !== value[3]) { | ||
gl.uniform4fv(location, value); | ||
cache[0] = value[0]; | ||
cache[1] = value[1]; | ||
cache[2] = value[2]; | ||
cache[3] = value[3]; | ||
} | ||
} | ||
@@ -271,5 +335,9 @@ break; | ||
uniform.set = function(value) { | ||
if (arraysEqual(cache, value)) return; | ||
gl.uniform4iv(location, value); | ||
copyArray(cache, value); | ||
if (cache[0] !== value[0] || cache[1] !== value[1] || cache[2] !== value[2] || cache[3] !== value[3]) { | ||
gl.uniform4iv(location, value); | ||
cache[0] = value[0]; | ||
cache[1] = value[1]; | ||
cache[2] = value[2]; | ||
cache[3] = value[3]; | ||
} | ||
} | ||
@@ -280,5 +348,9 @@ break; | ||
uniform.setValue = uniform.set = function(value) { | ||
if (arraysEqual(cache, value)) return; | ||
gl.uniformMatrix2fv(location, false, value); | ||
copyArray(cache, value); | ||
if (cache[0] !== value[0] || cache[1] !== value[1] || cache[2] !== value[2] || cache[3] !== value[3]) { | ||
gl.uniformMatrix2fv(location, false, value); | ||
cache[0] = value[0]; | ||
cache[1] = value[1]; | ||
cache[2] = value[2]; | ||
cache[3] = value[3]; | ||
} | ||
} | ||
@@ -288,5 +360,16 @@ break; | ||
uniform.setValue = uniform.set = function(value) { | ||
if (arraysEqual(cache, value)) return; | ||
gl.uniformMatrix3fv(location, false, value); | ||
copyArray(cache, value); | ||
if (cache[0] !== value[0] || cache[1] !== value[1] || cache[2] !== value[2] | ||
|| cache[3] !== value[3] || cache[4] !== value[4] || cache[5] !== value[5] | ||
|| cache[6] !== value[6] || cache[7] !== value[7] || cache[8] !== value[8]) { | ||
gl.uniformMatrix3fv(location, false, value); | ||
cache[0] = value[0]; | ||
cache[1] = value[1]; | ||
cache[2] = value[2]; | ||
cache[3] = value[3]; | ||
cache[4] = value[4]; | ||
cache[5] = value[5]; | ||
cache[6] = value[6]; | ||
cache[7] = value[7]; | ||
cache[8] = value[8]; | ||
} | ||
} | ||
@@ -296,5 +379,24 @@ break; | ||
uniform.setValue = uniform.set = function(value) { | ||
if (arraysEqual(cache, value)) return; | ||
gl.uniformMatrix4fv(location, false, value); | ||
copyArray(cache, value); | ||
if (cache[0] !== value[0] || cache[1] !== value[1] || cache[2] !== value[2] || cache[3] !== value[3] | ||
|| cache[4] !== value[4] || cache[5] !== value[5] || cache[6] !== value[6] || cache[7] !== value[7] | ||
|| cache[8] !== value[8] || cache[9] !== value[9] || cache[10] !== value[10] || cache[11] !== value[11] | ||
|| cache[12] !== value[12] || cache[13] !== value[13] || cache[14] !== value[14] || cache[15] !== value[15]) { | ||
gl.uniformMatrix4fv(location, false, value); | ||
cache[0] = value[0]; | ||
cache[1] = value[1]; | ||
cache[2] = value[2]; | ||
cache[3] = value[3]; | ||
cache[4] = value[4]; | ||
cache[5] = value[5]; | ||
cache[6] = value[6]; | ||
cache[7] = value[7]; | ||
cache[8] = value[8]; | ||
cache[9] = value[9]; | ||
cache[10] = value[10]; | ||
cache[11] = value[11]; | ||
cache[12] = value[12]; | ||
cache[13] = value[13]; | ||
cache[14] = value[14]; | ||
cache[15] = value[15]; | ||
} | ||
} | ||
@@ -325,2 +427,13 @@ break; | ||
generateSetter(this); | ||
// internal | ||
this.internalGroup = 0; | ||
this.internalFun = null; | ||
const internal = internalUniforms[id]; | ||
if (internal) { | ||
this.internalGroup = internal[0]; | ||
this.internalFun = internal[1]; | ||
} | ||
} | ||
@@ -327,0 +440,0 @@ |
@@ -0,9 +1,13 @@ | ||
import { WebGLProperties } from './WebGLProperties.js'; | ||
const emptyString = ""; | ||
export class WebGLVertexArrayBindings { | ||
export class WebGLVertexArrayBindings extends WebGLProperties { | ||
constructor(gl, properties, capabilities) { | ||
constructor(passId, gl, capabilities, buffers) { | ||
super(passId); | ||
this._gl = gl; | ||
this._properties = properties; | ||
this._capabilities = capabilities; | ||
this._buffers = buffers; | ||
@@ -18,4 +22,2 @@ this._isWebGL2 = capabilities.version >= 2; | ||
setup(object, geometry, program) { | ||
const geometryProperties = this._properties.get(geometry); | ||
if (object.morphTargetInfluences) { | ||
@@ -26,7 +28,11 @@ this.reset(); | ||
} else if (this._isWebGL2 || this._vaoExt) { // use VAO | ||
let vao; | ||
if (!geometryProperties._vaos[program.id]) { | ||
const geometryProperties = this.get(geometry); | ||
if (geometryProperties._vaos === undefined) { | ||
geometryProperties._vaos = {}; | ||
} | ||
let vao = geometryProperties._vaos[program.id]; | ||
if (!vao) { | ||
vao = geometryProperties._vaos[program.id] = { version: -1, object: this._createVAO() }; | ||
} else { | ||
vao = geometryProperties._vaos[program.id]; | ||
} | ||
@@ -49,7 +55,14 @@ | ||
disposeVAO(vao) { | ||
if (this._isWebGL2) { | ||
this._gl.deleteVertexArray(vao); | ||
} else if (this._vaoExt) { | ||
this._vaoExt.deleteVertexArrayOES(vao); | ||
releaseByGeometry(geometry) { | ||
const geometryProperties = this.get(geometry); | ||
if (geometryProperties._vaos) { | ||
for (const key in geometryProperties._vaos) { | ||
const vao = geometryProperties[key]; | ||
if (vao) { | ||
this._disposeVAO(vao.object); | ||
} | ||
} | ||
geometryProperties._vaos = {}; | ||
} | ||
@@ -95,2 +108,10 @@ } | ||
_disposeVAO(vao) { | ||
if (this._isWebGL2) { | ||
this._gl.deleteVertexArray(vao); | ||
} else if (this._vaoExt) { | ||
this._vaoExt.deleteVertexArrayOES(vao); | ||
} | ||
} | ||
_setupVertexAttributes(program, geometry) { | ||
@@ -100,4 +121,4 @@ const gl = this._gl; | ||
const attributes = program.getAttributes(); | ||
const properties = this._properties; | ||
const capabilities = this._capabilities; | ||
const buffers = this._buffers; | ||
@@ -115,3 +136,3 @@ for (const key in attributes) { | ||
const buffer = geometryAttribute.buffer; | ||
const bufferProperties = properties.get(buffer); | ||
const bufferProperties = buffers.get(buffer); | ||
@@ -168,3 +189,3 @@ const type = bufferProperties.type; | ||
if (geometry.index) { | ||
const indexBufferProperties = properties.get(geometry.index.buffer); | ||
const indexBufferProperties = buffers.get(geometry.index.buffer); | ||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBufferProperties.glBuffer); | ||
@@ -171,0 +192,0 @@ } |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2630204
328
62386