three.js源码注解-WebGLPrograms-基于r142

128 阅读3分钟

WebGLPrograms

函数作用

提取和整理材质中的配置属性,并记录WebGLProgram

入口函数

/**
*@renderer WebGLRenderer渲染器实例
*@cubemaps cube贴图
*@cubeuvmaps cubeuv
*@extensions 启用一些WebGl上下文扩展。同时将启用的扩展对象储存下来
*@capabilities 维护gl环境中的阈值
*@bindingStates 创建顶点缓冲区状态与几何以及几何与Program的映射,将attribute缓存,并采用一些webgl缓存措施实现性能优化,通过对比新旧attribute去决定是否更新缓冲以及缓存的绑定。同时控制顶点缓冲区对象与WebGL中attribute变量间的数据传输以及更新
*@clipping 管理平面裁剪,通过object3D.material传入裁剪平面信息,该对象负责整理裁剪平面信息,便于后续传入着色器
**/
function WebGLPrograms(renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping) {
    const _programLayers = new Layers();//层级
    const _customShaders = new WebGLShaderCache();//自定义着色器缓存,内部维护一个材质与着色器的映射,记录着每个着色器片段被使用的次数
    const programs = [];//记录WebGLProgram
}

核心函数-getParameters(material, lights, shadows, scene, object)

//从材质中获取配置参数,并将所有参数整合为一个参数 
function getParameters(material, lights, shadows, scene, object) {
        const fog = scene.fog;//场景雾
        const geometry = object.geometry;//Obejct3D的geometry
        const environment = material.isMeshStandardMaterial ? scene.environment : null;//环境
        const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment);//环境贴图
        const envMapCubeUVHeight = (!!envMap) && (envMap.mapping === CubeUVReflectionMapping) ? envMap.image.height : null;//立方体贴图
        const shaderID = shaderIDs[material.type];//材质类型对应的shaderID
        if (material.precision !== null) {
          //控制最大精度...
        }
        //变形相关...
        //
        let vertexShader, fragmentShader;
        let customVertexShaderID, customFragmentShaderID;//缓存的着色器
        if (shaderID) {//这里区分了自定义着色器与内置着色器
            const shader = ShaderLib[shaderID];//内置着色器则直接获取shader对应的着色器片段
            vertexShader = shader.vertexShader;
            fragmentShader = shader.fragmentShader;
        } else {
            vertexShader = material.vertexShader;//自定义着色器则从material中获取
            fragmentShader = material.fragmentShader;
            _customShaders.update(material);//更新一下着色器片段记录缓存
            customVertexShaderID = _customShaders.getVertexShaderID(material);//返回自定义顶点着色器缓存下的ID
            customFragmentShaderID = _customShaders.getFragmentShaderID(material);//返回自定义片元着色器缓存下的ID
        }
        const currentRenderTarget = renderer.getRenderTarget();//当前帧缓冲区
        const useAlphaTest = material.alphaTest > 0;//透明度测试
        const useClearcoat = material.clearcoat > 0;//清漆
        const useIridescence = material.iridescence > 0;//彩虹色
        const parameters = {
            isWebGL2: isWebGL2,
            shaderID: shaderID,
            shaderName: material.type,
            vertexShader: vertexShader,
            fragmentShader: fragmentShader,
            defines: material.defines,
            customVertexShaderID: customVertexShaderID,
            customFragmentShaderID: customFragmentShaderID,
            isRawShaderMaterial: material.isRawShaderMaterial === true,
            glslVersion: material.glslVersion,
            precision: precision,
            instancing: object.isInstancedMesh === true,
            instancingColor: object.isInstancedMesh === true && object.instanceColor !== null,
            supportsVertexTextures: vertexTextures,
            outputEncoding: (currentRenderTarget === null) ? renderer.outputEncoding : (currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding),
            map: !!material.map,
            matcap: !!material.matcap,
            envMap: !!envMap,
            //一系列配置参数...
            fog: !!fog,
            useFog: material.fog === true,
            fogExp2: (fog && fog.isFogExp2),
            flatShading: !!material.flatShading,
            sizeAttenuation: material.sizeAttenuation,
            logarithmicDepthBuffer: logarithmicDepthBuffer,
            //一系列配置参数...
            customProgramCacheKey: material.customProgramCacheKey()//在使用 onBeforeCompile 的情况下,此回调可用于识别 onBeforeCompile 中使用的设置值
        };
        return parameters;//返回材质的参数
    }

核心函数-getProgramCacheKey(parameters)

function getProgramCacheKey(parameters) {//作为dui'yprogram的key值
    const array = [];
    if (parameters.shaderID) {
        array.push(parameters.shaderID);
    } else {
        array.push(parameters.customVertexShaderID);
        array.push(parameters.customFragmentShaderID);
    }
    if (parameters.defines !== undefined) {//用于着色器中的defined
        for (const name in parameters.defines) {
            array.push(name);
            array.push(parameters.defines[name]);
        }
    }
    if (parameters.isRawShaderMaterial === false) {//是否采用原生着色器
        getProgramCacheKeyParameters(array, parameters);//获取parameters的一些信息
        getProgramCacheKeyBooleans(array, parameters);//获取parameters的一些配置的使用情况
        array.push(renderer.outputEncoding);
    }
    array.push(parameters.customProgramCacheKey);//在使用 onBeforeCompile 的情况下,此回调可用于识别 onBeforeCompile 中使用的设置值,这里是获取回调的函数字符串
    return array.join();
}

核心函数-acquireProgram(parameters, cacheKey)

//记录单个的WebGLProgram
function acquireProgram(parameters, cacheKey) {
    let program;
    for (let p = 0, pl = programs.length; p < pl; p++) {
        const preexistingProgram = programs[p];
        if (preexistingProgram.cacheKey === cacheKey) {
            program = preexistingProgram;
            ++program.usedTimes;
            break;
        }
    }
    if (program === undefined) {
        program = new WebGLProgram(renderer, cacheKey, parameters, bindingStates);
        programs.push(program);
    }
    return program;
}

销毁

function releaseProgram(program) {
    if (--program.usedTimes === 0) {
        // Remove from unordered set
        const i = programs.indexOf(program);
        programs[i] = programs[programs.length - 1];
        programs.pop();
        // Free WebGL resources
        program.destroy();
    }
}
function releaseShaderCache(material) {
    _customShaders.remove(material);
}
function dispose() {
    _customShaders.dispose();
/** 
dispose() {
   this.shaderCache.clear();
   this.materialCache.clear();
}*/
}

返回值

return {
    getParameters: getParameters,
    getProgramCacheKey: getProgramCacheKey,
    getUniforms: getUniforms,
    acquireProgram: acquireProgram,
    releaseProgram: releaseProgram,
    releaseShaderCache: releaseShaderCache,
    programs: programs,
    dispose: dispose
};