|
@@ -17954,15 +17954,17 @@
|
|
|
|
|
|
|
|
|
|
function deallocateMaterial(material) {
|
|
function deallocateMaterial(material) {
|
|
- releaseMaterialProgramReference(material);
|
|
|
|
|
|
+ releaseMaterialProgramReferences(material);
|
|
properties.remove(material);
|
|
properties.remove(material);
|
|
}
|
|
}
|
|
|
|
|
|
- function releaseMaterialProgramReference(material) {
|
|
|
|
- const programInfo = properties.get(material).program;
|
|
|
|
|
|
+ function releaseMaterialProgramReferences(material) {
|
|
|
|
+ const programs = properties.get(material).programs;
|
|
|
|
|
|
- if (programInfo !== undefined) {
|
|
|
|
- programCache.releaseProgram(programInfo);
|
|
|
|
|
|
+ if (programs !== undefined) {
|
|
|
|
+ programs.forEach(function (program) {
|
|
|
|
+ programCache.releaseProgram(program);
|
|
|
|
+ });
|
|
}
|
|
}
|
|
} // Buffer rendering
|
|
} // Buffer rendering
|
|
|
|
|
|
@@ -18128,7 +18130,6 @@
|
|
}
|
|
}
|
|
});
|
|
});
|
|
currentRenderState.setupLights();
|
|
currentRenderState.setupLights();
|
|
- const compiled = new WeakMap();
|
|
|
|
scene.traverse(function (object) {
|
|
scene.traverse(function (object) {
|
|
const material = object.material;
|
|
const material = object.material;
|
|
|
|
|
|
@@ -18136,15 +18137,10 @@
|
|
if (Array.isArray(material)) {
|
|
if (Array.isArray(material)) {
|
|
for (let i = 0; i < material.length; i++) {
|
|
for (let i = 0; i < material.length; i++) {
|
|
const material2 = material[i];
|
|
const material2 = material[i];
|
|
-
|
|
|
|
- if (compiled.has(material2) === false) {
|
|
|
|
- initMaterial(material2, scene, object);
|
|
|
|
- compiled.set(material2);
|
|
|
|
- }
|
|
|
|
|
|
+ getProgram(material2, scene, object);
|
|
}
|
|
}
|
|
- } else if (compiled.has(material) === false) {
|
|
|
|
- initMaterial(material, scene, object);
|
|
|
|
- compiled.set(material);
|
|
|
|
|
|
+ } else {
|
|
|
|
+ getProgram(material, scene, object);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
@@ -18398,7 +18394,7 @@
|
|
object.onAfterRender(_this, scene, camera, geometry, material, group);
|
|
object.onAfterRender(_this, scene, camera, geometry, material, group);
|
|
}
|
|
}
|
|
|
|
|
|
- function initMaterial(material, scene, object) {
|
|
|
|
|
|
+ function getProgram(material, scene, object) {
|
|
if (scene.isScene !== true) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
|
|
if (scene.isScene !== true) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
|
|
|
|
|
|
const materialProperties = properties.get(material);
|
|
const materialProperties = properties.get(material);
|
|
@@ -18407,46 +18403,42 @@
|
|
const lightsStateVersion = lights.state.version;
|
|
const lightsStateVersion = lights.state.version;
|
|
const parameters = programCache.getParameters(material, lights.state, shadowsArray, scene, object);
|
|
const parameters = programCache.getParameters(material, lights.state, shadowsArray, scene, object);
|
|
const programCacheKey = programCache.getProgramCacheKey(parameters);
|
|
const programCacheKey = programCache.getProgramCacheKey(parameters);
|
|
- let program = materialProperties.program;
|
|
|
|
- let programChange = true; // always update environment and fog - changing these trigger an initMaterial call, but it's possible that the program doesn't change
|
|
|
|
|
|
+ let programs = materialProperties.programs; // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change
|
|
|
|
|
|
materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
|
|
materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
|
|
materialProperties.fog = scene.fog;
|
|
materialProperties.fog = scene.fog;
|
|
materialProperties.envMap = cubemaps.get(material.envMap || materialProperties.environment);
|
|
materialProperties.envMap = cubemaps.get(material.envMap || materialProperties.environment);
|
|
|
|
|
|
- if (program === undefined) {
|
|
|
|
|
|
+ if (programs === undefined) {
|
|
// new material
|
|
// new material
|
|
material.addEventListener('dispose', onMaterialDispose);
|
|
material.addEventListener('dispose', onMaterialDispose);
|
|
- } else if (program.cacheKey !== programCacheKey) {
|
|
|
|
- // changed glsl or parameters
|
|
|
|
- releaseMaterialProgramReference(material);
|
|
|
|
- } else if (materialProperties.lightsStateVersion !== lightsStateVersion) {
|
|
|
|
- programChange = false;
|
|
|
|
- } else if (parameters.shaderID !== undefined) {
|
|
|
|
- // same glsl and uniform list
|
|
|
|
- return;
|
|
|
|
- } else {
|
|
|
|
- // only rebuild uniform list
|
|
|
|
- programChange = false;
|
|
|
|
|
|
+ programs = new Map();
|
|
|
|
+ materialProperties.programs = programs;
|
|
}
|
|
}
|
|
|
|
|
|
- if (programChange) {
|
|
|
|
|
|
+ let program = programs.get(programCacheKey);
|
|
|
|
+
|
|
|
|
+ if (program !== undefined) {
|
|
|
|
+ // early out if program and light state is identical
|
|
|
|
+ if (materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion) {
|
|
|
|
+ updateCommonMaterialProperties(material, parameters);
|
|
|
|
+ return program;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
parameters.uniforms = programCache.getUniforms(material);
|
|
parameters.uniforms = programCache.getUniforms(material);
|
|
material.onBeforeCompile(parameters, _this);
|
|
material.onBeforeCompile(parameters, _this);
|
|
program = programCache.acquireProgram(parameters, programCacheKey);
|
|
program = programCache.acquireProgram(parameters, programCacheKey);
|
|
- materialProperties.program = program;
|
|
|
|
|
|
+ programs.set(programCacheKey, program);
|
|
materialProperties.uniforms = parameters.uniforms;
|
|
materialProperties.uniforms = parameters.uniforms;
|
|
- materialProperties.outputEncoding = parameters.outputEncoding;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
const uniforms = materialProperties.uniforms;
|
|
const uniforms = materialProperties.uniforms;
|
|
|
|
|
|
if (!material.isShaderMaterial && !material.isRawShaderMaterial || material.clipping === true) {
|
|
if (!material.isShaderMaterial && !material.isRawShaderMaterial || material.clipping === true) {
|
|
- materialProperties.numClippingPlanes = clipping.numPlanes;
|
|
|
|
- materialProperties.numIntersection = clipping.numIntersection;
|
|
|
|
uniforms.clippingPlanes = clipping.uniform;
|
|
uniforms.clippingPlanes = clipping.uniform;
|
|
- } // store the light setup it was created for
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ updateCommonMaterialProperties(material, parameters); // store the light setup it was created for
|
|
|
|
|
|
materialProperties.needsLights = materialNeedsLights(material);
|
|
materialProperties.needsLights = materialNeedsLights(material);
|
|
materialProperties.lightsStateVersion = lightsStateVersion;
|
|
materialProperties.lightsStateVersion = lightsStateVersion;
|
|
@@ -18473,9 +18465,19 @@
|
|
uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; // TODO (abelnation): add area lights shadow info to uniforms
|
|
uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; // TODO (abelnation): add area lights shadow info to uniforms
|
|
}
|
|
}
|
|
|
|
|
|
- const progUniforms = materialProperties.program.getUniforms();
|
|
|
|
|
|
+ const progUniforms = program.getUniforms();
|
|
const uniformsList = WebGLUniforms.seqWithValue(progUniforms.seq, uniforms);
|
|
const uniformsList = WebGLUniforms.seqWithValue(progUniforms.seq, uniforms);
|
|
|
|
+ materialProperties.currentProgram = program;
|
|
materialProperties.uniformsList = uniformsList;
|
|
materialProperties.uniformsList = uniformsList;
|
|
|
|
+ return program;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function updateCommonMaterialProperties(material, parameters) {
|
|
|
|
+ const materialProperties = properties.get(material);
|
|
|
|
+ materialProperties.outputEncoding = parameters.outputEncoding;
|
|
|
|
+ materialProperties.instancing = parameters.instancing;
|
|
|
|
+ materialProperties.numClippingPlanes = parameters.numClippingPlanes;
|
|
|
|
+ materialProperties.numIntersection = parameters.numClipIntersection;
|
|
}
|
|
}
|
|
|
|
|
|
function setProgram(camera, scene, material, object) {
|
|
function setProgram(camera, scene, material, object) {
|
|
@@ -18497,32 +18499,43 @@
|
|
|
|
|
|
clipping.setState(material, camera, useCache);
|
|
clipping.setState(material, camera, useCache);
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
+ } //
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ let needsProgramChange = false;
|
|
|
|
|
|
if (material.version === materialProperties.__version) {
|
|
if (material.version === materialProperties.__version) {
|
|
- if (material.fog && materialProperties.fog !== fog) {
|
|
|
|
- initMaterial(material, scene, object);
|
|
|
|
- } else if (materialProperties.environment !== environment) {
|
|
|
|
- initMaterial(material, scene, object);
|
|
|
|
- } else if (materialProperties.needsLights && materialProperties.lightsStateVersion !== lights.state.version) {
|
|
|
|
- initMaterial(material, scene, object);
|
|
|
|
- } else if (materialProperties.numClippingPlanes !== undefined && (materialProperties.numClippingPlanes !== clipping.numPlanes || materialProperties.numIntersection !== clipping.numIntersection)) {
|
|
|
|
- initMaterial(material, scene, object);
|
|
|
|
|
|
+ if (materialProperties.needsLights && materialProperties.lightsStateVersion !== lights.state.version) {
|
|
|
|
+ needsProgramChange = true;
|
|
} else if (materialProperties.outputEncoding !== encoding) {
|
|
} else if (materialProperties.outputEncoding !== encoding) {
|
|
- initMaterial(material, scene, object);
|
|
|
|
|
|
+ needsProgramChange = true;
|
|
|
|
+ } else if (object.isInstancedMesh && materialProperties.instancing === false) {
|
|
|
|
+ needsProgramChange = true;
|
|
|
|
+ } else if (!object.isInstancedMesh && materialProperties.instancing === true) {
|
|
|
|
+ needsProgramChange = true;
|
|
} else if (materialProperties.envMap !== envMap) {
|
|
} else if (materialProperties.envMap !== envMap) {
|
|
- initMaterial(material, scene, object);
|
|
|
|
|
|
+ needsProgramChange = true;
|
|
|
|
+ } else if (material.fog && materialProperties.fog !== fog) {
|
|
|
|
+ needsProgramChange = true;
|
|
|
|
+ } else if (materialProperties.numClippingPlanes !== undefined && (materialProperties.numClippingPlanes !== clipping.numPlanes || materialProperties.numIntersection !== clipping.numIntersection)) {
|
|
|
|
+ needsProgramChange = true;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- initMaterial(material, scene, object);
|
|
|
|
|
|
+ needsProgramChange = true;
|
|
materialProperties.__version = material.version;
|
|
materialProperties.__version = material.version;
|
|
|
|
+ } //
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ let program = materialProperties.currentProgram;
|
|
|
|
+
|
|
|
|
+ if (needsProgramChange === true) {
|
|
|
|
+ program = getProgram(material, scene, object);
|
|
}
|
|
}
|
|
|
|
|
|
let refreshProgram = false;
|
|
let refreshProgram = false;
|
|
let refreshMaterial = false;
|
|
let refreshMaterial = false;
|
|
let refreshLights = false;
|
|
let refreshLights = false;
|
|
- const program = materialProperties.program,
|
|
|
|
- p_uniforms = program.getUniforms(),
|
|
|
|
|
|
+ const p_uniforms = program.getUniforms(),
|
|
m_uniforms = materialProperties.uniforms;
|
|
m_uniforms = materialProperties.uniforms;
|
|
|
|
|
|
if (state.useProgram(program.program)) {
|
|
if (state.useProgram(program.program)) {
|