getProgram method
Implementation
WebGLProgram? getProgram(Material material, Object3D? scene, Object3D object) {
if (scene is! Scene) scene = _emptyScene;
// scene could be a Mesh, Line, Points, ...
var materialProperties = properties.get(material);
var lights = currentRenderState!.state.lights;
var shadowsArray = currentRenderState!.state.shadowsArray;
var lightsStateVersion = lights.state.version;
var parameters = programCache.getParameters(material, lights.state, shadowsArray, scene, object);
var programCacheKey = programCache.getProgramCacheKey(parameters);
Map? 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 is MeshStandardMaterial ? scene.environment : null;
materialProperties["fog"] = scene.fog;
Texture? envMap;
if (material is MeshStandardMaterial) {
envMap = cubeuvmaps.get(material.envMap ?? materialProperties["environment"]);
} else {
envMap = cubemaps.get(material.envMap ?? materialProperties["environment"]);
}
materialProperties["envMap"] = envMap;
if (programs == null) {
// new material
material.addEventListener('dispose', onMaterialDispose);
programs = {};
materialProperties["programs"] = programs;
}
WebGLProgram? program = programs[programCacheKey];
if (program != null) {
// 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);
material.onBuild(parameters, this);
if (material.onBeforeCompile != null) {
material.onBeforeCompile!(parameters, this);
}
program = programCache.acquireProgram(parameters, programCacheKey);
programs[programCacheKey] = program;
materialProperties["uniforms"] = parameters.uniforms;
}
Map<String, dynamic> uniforms = materialProperties["uniforms"];
if ((material is! ShaderMaterial && material is! RawShaderMaterial) || material.clipping == true) {
uniforms["clippingPlanes"] = clipping.uniform;
}
updateCommonMaterialProperties(material, parameters);
// store the light setup it was created for
materialProperties["needsLights"] = materialNeedsLights(material);
materialProperties["lightsStateVersion"] = lightsStateVersion;
if (materialProperties["needsLights"] == true) {
// wire up the material to this renderer's lighting state
uniforms["ambientLightColor"]["value"] = lights.state.ambient;
uniforms["lightProbe"]["value"] = lights.state.probe;
uniforms["directionalLights"]["value"] = lights.state.directional;
uniforms["directionalLightShadows"]["value"] = lights.state.directionalShadow;
uniforms["spotLights"]["value"] = lights.state.spot;
uniforms["spotLightShadows"]["value"] = lights.state.spotShadow;
uniforms["rectAreaLights"]["value"] = lights.state.rectArea;
uniforms["ltc_1"]["value"] = lights.state.rectAreaLTC1;
uniforms["ltc_2"]["value"] = lights.state.rectAreaLTC2;
uniforms["pointLights"]["value"] = lights.state.point;
uniforms["pointLightShadows"]["value"] = lights.state.pointShadow;
uniforms["hemisphereLights"]["value"] = lights.state.hemi;
uniforms["directionalShadowMap"]["value"] = lights.state.directionalShadowMap;
uniforms["directionalShadowMatrix"]["value"] = lights.state.directionalShadowMatrix;
uniforms["spotShadowMap"]["value"] = lights.state.spotShadowMap;
uniforms["spotShadowMatrix"]["value"] = lights.state.spotShadowMatrix;
uniforms["pointShadowMap"]["value"] = lights.state.pointShadowMap;
uniforms["pointShadowMatrix"]["value"] = lights.state.pointShadowMatrix;
// TODO (abelnation): add area lights shadow info to uniforms
}
var progUniforms = program!.getUniforms();
var uniformsList = WebGLUniforms.seqWithValue(progUniforms.seq, uniforms);
materialProperties["currentProgram"] = program;
materialProperties["uniformsList"] = uniformsList;
return program;
}