ThreeJS initMaterial

198 阅读1分钟
function initMaterial(material, scene, object) {
        if (scene.isScene !== true) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
        //获取材质的属性
        const materialProperties = properties.get(material);

        const lights = currentRenderState.state.lights;
        const shadowsArray = currentRenderState.state.shadowsArray;

        const lightsStateVersion = lights.state.version;
        //返回所有参数
        const parameters = programCache.getParameters(
                material,
                lights.state,
                shadowsArray,
                scene,
                _clipping.numPlanes,
                _clipping.numIntersection,
                object
        );
        //返回字符串 用来对比的
        const programCacheKey = programCache.getProgramCacheKey(parameters);

        //program 这个储存的是啥
        let program = materialProperties.program;
        let programChange = true;

        if (program === undefined) {
                // new material
                material.addEventListener('dispose', onMaterialDispose);
        } else if (program.cacheKey !== programCacheKey) {
                // changed glsl or parameters
                releaseMaterialProgramReference(material);
        } else if (materialProperties.lightsStateVersion !== lightsStateVersion) {
                materialProperties.lightsStateVersion = lightsStateVersion;

                programChange = false;
        } else if (parameters.shaderID !== undefined) {
                // same glsl and uniform list
                return;
        } else {
                // only rebuild uniform list
                programChange = false;
        }

        //获取到program
        if (programChange) {
                parameters.uniforms = programCache.getUniforms(material, parameters);

                material.onBeforeCompile(parameters, _this);
                // D4_Added
                if(material.onBeforeOITCompile) material.onBeforeOITCompile(parameters, _this);

                program = programCache.acquireProgram(parameters, programCacheKey);

                materialProperties.program = program;
                materialProperties.uniforms = parameters.uniforms;
                materialProperties.outputEncoding = parameters.outputEncoding;
        }

        const programAttributes = program.getAttributes();

        if (material.morphTargets) {
                material.numSupportedMorphTargets = 0;

                for (let i = 0; i < _this.maxMorphTargets; i++) {
                        if (programAttributes['morphTarget' + i] >= 0) {
                                material.numSupportedMorphTargets++;
                        }
                }
        }

        if (material.morphNormals) {
                material.numSupportedMorphNormals = 0;

                for (let i = 0; i < _this.maxMorphNormals; i++) {
                        if (programAttributes['morphNormal' + i] >= 0) {
                                material.numSupportedMorphNormals++;
                        }
                }
        }

        const uniforms = materialProperties.uniforms;

        if ((!material.isShaderMaterial && !material.isRawShaderMaterial) || material.clipping === true) {
                materialProperties.numClippingPlanes = _clipping.numPlanes;
                materialProperties.numIntersection = _clipping.numIntersection;
                uniforms.clippingPlanes = _clipping.uniform;
        }

        materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
        materialProperties.fog = scene.fog;

        // store the light setup it was created for

        materialProperties.needsLights = materialNeedsLights(material);
        materialProperties.lightsStateVersion = lightsStateVersion;

        if (materialProperties.needsLights) {
                // 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.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
        }

        const progUniforms = materialProperties.program.getUniforms(),
                uniformsList = WebGLUniforms.seqWithValue(progUniforms.seq, uniforms);

        materialProperties.uniformsList = uniformsList;
}