Spaces:
Running
Running
| import { | |
| BackSide, | |
| DoubleSide, | |
| CubeUVRefractionMapping, | |
| CubeUVReflectionMapping, | |
| ObjectSpaceNormalMap, | |
| TangentSpaceNormalMap, | |
| NoToneMapping, | |
| LinearEncoding, | |
| sRGBEncoding, | |
| } from '../../constants.js'; | |
| import { Layers } from '../../core/Layers.js'; | |
| import { WebGLProgram } from './WebGLProgram.js'; | |
| import { WebGLShaderCache } from './WebGLShaderCache.js'; | |
| import { ShaderLib } from '../shaders/ShaderLib.js'; | |
| import { UniformsUtils } from '../shaders/UniformsUtils.js'; | |
| function WebGLPrograms(renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping) { | |
| const _programLayers = new Layers(); | |
| const _customShaders = new WebGLShaderCache(); | |
| const programs = []; | |
| const isWebGL2 = capabilities.isWebGL2; | |
| const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; | |
| const floatVertexTextures = capabilities.floatVertexTextures; | |
| const maxVertexUniforms = capabilities.maxVertexUniforms; | |
| const vertexTextures = capabilities.vertexTextures; | |
| let precision = capabilities.precision; | |
| const shaderIDs = { | |
| MeshDepthMaterial: 'depth', | |
| MeshDistanceMaterial: 'distanceRGBA', | |
| MeshNormalMaterial: 'normal', | |
| MeshBasicMaterial: 'basic', | |
| MeshLambertMaterial: 'lambert', | |
| MeshPhongMaterial: 'phong', | |
| MeshToonMaterial: 'toon', | |
| MeshStandardMaterial: 'physical', | |
| MeshPhysicalMaterial: 'physical', | |
| MeshMatcapMaterial: 'matcap', | |
| LineBasicMaterial: 'basic', | |
| LineDashedMaterial: 'dashed', | |
| PointsMaterial: 'points', | |
| ShadowMaterial: 'shadow', | |
| SpriteMaterial: 'sprite', | |
| }; | |
| function getMaxBones(object) { | |
| const skeleton = object.skeleton; | |
| const bones = skeleton.bones; | |
| if (floatVertexTextures) { | |
| return 1024; | |
| } else { | |
| // default for when object is not specified | |
| // ( for example when prebuilding shader to be used with multiple objects ) | |
| // | |
| // - leave some extra space for other uniforms | |
| // - limit here is ANGLE's 254 max uniform vectors | |
| // (up to 54 should be safe) | |
| const nVertexUniforms = maxVertexUniforms; | |
| const nVertexMatrices = Math.floor((nVertexUniforms - 20) / 4); | |
| const maxBones = Math.min(nVertexMatrices, bones.length); | |
| if (maxBones < bones.length) { | |
| console.warn('THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.'); | |
| return 0; | |
| } | |
| return maxBones; | |
| } | |
| } | |
| function getParameters(material, lights, shadows, scene, object) { | |
| const fog = scene.fog; | |
| const environment = material.isMeshStandardMaterial ? scene.environment : null; | |
| const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment); | |
| const shaderID = shaderIDs[material.type]; | |
| // heuristics to create shader parameters according to lights in the scene | |
| // (not to blow over maxLights budget) | |
| const maxBones = object.isSkinnedMesh ? getMaxBones(object) : 0; | |
| if (material.precision !== null) { | |
| precision = capabilities.getMaxPrecision(material.precision); | |
| if (precision !== material.precision) { | |
| console.warn('THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.'); | |
| } | |
| } | |
| let vertexShader, fragmentShader; | |
| let customVertexShaderID, customFragmentShaderID; | |
| if (shaderID) { | |
| const shader = ShaderLib[shaderID]; | |
| vertexShader = shader.vertexShader; | |
| fragmentShader = shader.fragmentShader; | |
| } else { | |
| vertexShader = material.vertexShader; | |
| fragmentShader = material.fragmentShader; | |
| _customShaders.update(material); | |
| customVertexShaderID = _customShaders.getVertexShaderID(material); | |
| customFragmentShaderID = _customShaders.getFragmentShaderID(material); | |
| } | |
| const currentRenderTarget = renderer.getRenderTarget(); | |
| const useAlphaTest = material.alphaTest > 0; | |
| const useClearcoat = material.clearcoat > 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 : LinearEncoding, | |
| map: !!material.map, | |
| matcap: !!material.matcap, | |
| envMap: !!envMap, | |
| envMapMode: envMap && envMap.mapping, | |
| envMapCubeUV: !!envMap && (envMap.mapping === CubeUVReflectionMapping || envMap.mapping === CubeUVRefractionMapping), | |
| lightMap: !!material.lightMap, | |
| aoMap: !!material.aoMap, | |
| emissiveMap: !!material.emissiveMap, | |
| bumpMap: !!material.bumpMap, | |
| normalMap: !!material.normalMap, | |
| objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap, | |
| tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap, | |
| decodeVideoTexture: !!material.map && material.map.isVideoTexture === true && material.map.encoding === sRGBEncoding, | |
| clearcoat: useClearcoat, | |
| clearcoatMap: useClearcoat && !!material.clearcoatMap, | |
| clearcoatRoughnessMap: useClearcoat && !!material.clearcoatRoughnessMap, | |
| clearcoatNormalMap: useClearcoat && !!material.clearcoatNormalMap, | |
| displacementMap: !!material.displacementMap, | |
| roughnessMap: !!material.roughnessMap, | |
| metalnessMap: !!material.metalnessMap, | |
| specularMap: !!material.specularMap, | |
| specularIntensityMap: !!material.specularIntensityMap, | |
| specularColorMap: !!material.specularColorMap, | |
| alphaMap: !!material.alphaMap, | |
| alphaTest: useAlphaTest, | |
| alphaWrite: material.alphaWrite || material.transparent, | |
| gradientMap: !!material.gradientMap, | |
| sheen: material.sheen > 0, | |
| sheenColorMap: !!material.sheenColorMap, | |
| sheenRoughnessMap: !!material.sheenRoughnessMap, | |
| transmission: material.transmission > 0, | |
| transmissionMap: !!material.transmissionMap, | |
| thicknessMap: !!material.thicknessMap, | |
| combine: material.combine, | |
| vertexTangents: !!material.normalMap && !!object.geometry && !!object.geometry.attributes.tangent, | |
| vertexColors: material.vertexColors, | |
| vertexAlphas: | |
| material.vertexColors === true && !!object.geometry && !!object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4, | |
| vertexUvs: | |
| !!material.map || | |
| !!material.bumpMap || | |
| !!material.normalMap || | |
| !!material.specularMap || | |
| !!material.alphaMap || | |
| !!material.emissiveMap || | |
| !!material.roughnessMap || | |
| !!material.metalnessMap || | |
| !!material.clearcoatMap || | |
| !!material.clearcoatRoughnessMap || | |
| !!material.clearcoatNormalMap || | |
| !!material.displacementMap || | |
| !!material.transmissionMap || | |
| !!material.thicknessMap || | |
| !!material.specularIntensityMap || | |
| !!material.specularColorMap || | |
| !!material.sheenColorMap || | |
| !!material.sheenRoughnessMap, | |
| uvsVertexOnly: | |
| !( | |
| !!material.map || | |
| !!material.bumpMap || | |
| !!material.normalMap || | |
| !!material.specularMap || | |
| !!material.alphaMap || | |
| !!material.emissiveMap || | |
| !!material.roughnessMap || | |
| !!material.metalnessMap || | |
| !!material.clearcoatNormalMap || | |
| material.transmission > 0 || | |
| !!material.transmissionMap || | |
| !!material.thicknessMap || | |
| !!material.specularIntensityMap || | |
| !!material.specularColorMap || | |
| material.sheen > 0 || | |
| !!material.sheenColorMap || | |
| !!material.sheenRoughnessMap | |
| ) && !!material.displacementMap, | |
| fog: !!fog, | |
| useFog: material.fog, | |
| fogExp2: fog && fog.isFogExp2, | |
| flatShading: !!material.flatShading, | |
| sizeAttenuation: material.sizeAttenuation, | |
| logarithmicDepthBuffer: logarithmicDepthBuffer, | |
| skinning: object.isSkinnedMesh === true && maxBones > 0, | |
| maxBones: maxBones, | |
| useVertexTexture: floatVertexTextures, | |
| morphTargets: !!object.geometry && !!object.geometry.morphAttributes.position, | |
| morphNormals: !!object.geometry && !!object.geometry.morphAttributes.normal, | |
| morphTargetsCount: !!object.geometry && !!object.geometry.morphAttributes.position ? object.geometry.morphAttributes.position.length : 0, | |
| numDirLights: lights.directional.length, | |
| numPointLights: lights.point.length, | |
| numSpotLights: lights.spot.length, | |
| numRectAreaLights: lights.rectArea.length, | |
| numHemiLights: lights.hemi.length, | |
| numDirLightShadows: lights.directionalShadowMap.length, | |
| numPointLightShadows: lights.pointShadowMap.length, | |
| numSpotLightShadows: lights.spotShadowMap.length, | |
| numClippingPlanes: clipping.numPlanes, | |
| numClipIntersection: clipping.numIntersection, | |
| dithering: material.dithering, | |
| shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0, | |
| shadowMapType: renderer.shadowMap.type, | |
| toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping, | |
| physicallyCorrectLights: renderer.physicallyCorrectLights, | |
| premultipliedAlpha: material.premultipliedAlpha, | |
| doubleSided: material.side === DoubleSide, | |
| flipSided: material.side === BackSide, | |
| depthPacking: material.depthPacking !== undefined ? material.depthPacking : false, | |
| index0AttributeName: material.index0AttributeName, | |
| extensionDerivatives: material.extensions && material.extensions.derivatives, | |
| extensionFragDepth: material.extensions && material.extensions.fragDepth, | |
| extensionDrawBuffers: material.extensions && material.extensions.drawBuffers, | |
| extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD, | |
| rendererExtensionFragDepth: isWebGL2 || extensions.has('EXT_frag_depth'), | |
| rendererExtensionDrawBuffers: isWebGL2 || extensions.has('WEBGL_draw_buffers'), | |
| rendererExtensionShaderTextureLod: isWebGL2 || extensions.has('EXT_shader_texture_lod'), | |
| customProgramCacheKey: material.customProgramCacheKey(), | |
| }; | |
| return parameters; | |
| } | |
| function getProgramCacheKey(parameters) { | |
| const array = []; | |
| if (parameters.shaderID) { | |
| array.push(parameters.shaderID); | |
| } else { | |
| array.push(parameters.customVertexShaderID); | |
| array.push(parameters.customFragmentShaderID); | |
| } | |
| if (parameters.defines !== undefined) { | |
| for (const name in parameters.defines) { | |
| array.push(name); | |
| array.push(parameters.defines[name]); | |
| } | |
| } | |
| if (parameters.isRawShaderMaterial === false) { | |
| getProgramCacheKeyParameters(array, parameters); | |
| getProgramCacheKeyBooleans(array, parameters); | |
| array.push(renderer.outputEncoding); | |
| } | |
| array.push(parameters.customProgramCacheKey); | |
| return array.join(); | |
| } | |
| function getProgramCacheKeyParameters(array, parameters) { | |
| array.push(parameters.precision); | |
| array.push(parameters.outputEncoding); | |
| array.push(parameters.envMapMode); | |
| array.push(parameters.combine); | |
| array.push(parameters.vertexUvs); | |
| array.push(parameters.fogExp2); | |
| array.push(parameters.sizeAttenuation); | |
| array.push(parameters.maxBones); | |
| array.push(parameters.morphTargetsCount); | |
| array.push(parameters.numDirLights); | |
| array.push(parameters.numPointLights); | |
| array.push(parameters.numSpotLights); | |
| array.push(parameters.numHemiLights); | |
| array.push(parameters.numRectAreaLights); | |
| array.push(parameters.numDirLightShadows); | |
| array.push(parameters.numPointLightShadows); | |
| array.push(parameters.numSpotLightShadows); | |
| array.push(parameters.shadowMapType); | |
| array.push(parameters.toneMapping); | |
| array.push(parameters.numClippingPlanes); | |
| array.push(parameters.numClipIntersection); | |
| array.push(parameters.alphaWrite); | |
| } | |
| function getProgramCacheKeyBooleans(array, parameters) { | |
| _programLayers.disableAll(); | |
| if (parameters.isWebGL2) _programLayers.enable(0); | |
| if (parameters.supportsVertexTextures) _programLayers.enable(1); | |
| if (parameters.instancing) _programLayers.enable(2); | |
| if (parameters.instancingColor) _programLayers.enable(3); | |
| if (parameters.map) _programLayers.enable(4); | |
| if (parameters.matcap) _programLayers.enable(5); | |
| if (parameters.envMap) _programLayers.enable(6); | |
| if (parameters.envMapCubeUV) _programLayers.enable(7); | |
| if (parameters.lightMap) _programLayers.enable(8); | |
| if (parameters.aoMap) _programLayers.enable(9); | |
| if (parameters.emissiveMap) _programLayers.enable(10); | |
| if (parameters.bumpMap) _programLayers.enable(11); | |
| if (parameters.normalMap) _programLayers.enable(12); | |
| if (parameters.objectSpaceNormalMap) _programLayers.enable(13); | |
| if (parameters.tangentSpaceNormalMap) _programLayers.enable(14); | |
| if (parameters.clearcoat) _programLayers.enable(15); | |
| if (parameters.clearcoatMap) _programLayers.enable(16); | |
| if (parameters.clearcoatRoughnessMap) _programLayers.enable(17); | |
| if (parameters.clearcoatNormalMap) _programLayers.enable(18); | |
| if (parameters.displacementMap) _programLayers.enable(19); | |
| if (parameters.specularMap) _programLayers.enable(20); | |
| if (parameters.roughnessMap) _programLayers.enable(21); | |
| if (parameters.metalnessMap) _programLayers.enable(22); | |
| if (parameters.gradientMap) _programLayers.enable(23); | |
| if (parameters.alphaMap) _programLayers.enable(24); | |
| if (parameters.alphaTest) _programLayers.enable(25); | |
| if (parameters.vertexColors) _programLayers.enable(26); | |
| if (parameters.vertexAlphas) _programLayers.enable(27); | |
| if (parameters.vertexUvs) _programLayers.enable(28); | |
| if (parameters.vertexTangents) _programLayers.enable(29); | |
| if (parameters.uvsVertexOnly) _programLayers.enable(30); | |
| if (parameters.fog) _programLayers.enable(31); | |
| array.push(_programLayers.mask); | |
| _programLayers.disableAll(); | |
| if (parameters.useFog) _programLayers.enable(0); | |
| if (parameters.flatShading) _programLayers.enable(1); | |
| if (parameters.logarithmicDepthBuffer) _programLayers.enable(2); | |
| if (parameters.skinning) _programLayers.enable(3); | |
| if (parameters.useVertexTexture) _programLayers.enable(4); | |
| if (parameters.morphTargets) _programLayers.enable(5); | |
| if (parameters.morphNormals) _programLayers.enable(6); | |
| if (parameters.premultipliedAlpha) _programLayers.enable(7); | |
| if (parameters.shadowMapEnabled) _programLayers.enable(8); | |
| if (parameters.physicallyCorrectLights) _programLayers.enable(9); | |
| if (parameters.doubleSided) _programLayers.enable(10); | |
| if (parameters.flipSided) _programLayers.enable(11); | |
| if (parameters.depthPacking) _programLayers.enable(12); | |
| if (parameters.dithering) _programLayers.enable(13); | |
| if (parameters.specularIntensityMap) _programLayers.enable(14); | |
| if (parameters.specularColorMap) _programLayers.enable(15); | |
| if (parameters.transmission) _programLayers.enable(16); | |
| if (parameters.transmissionMap) _programLayers.enable(17); | |
| if (parameters.thicknessMap) _programLayers.enable(18); | |
| if (parameters.sheen) _programLayers.enable(19); | |
| if (parameters.sheenColorMap) _programLayers.enable(20); | |
| if (parameters.sheenRoughnessMap) _programLayers.enable(21); | |
| if (parameters.decodeVideoTexture) _programLayers.enable(22); | |
| array.push(_programLayers.mask); | |
| } | |
| function getUniforms(material) { | |
| const shaderID = shaderIDs[material.type]; | |
| let uniforms; | |
| if (shaderID) { | |
| const shader = ShaderLib[shaderID]; | |
| uniforms = UniformsUtils.clone(shader.uniforms); | |
| } else { | |
| uniforms = material.uniforms; | |
| } | |
| return uniforms; | |
| } | |
| function acquireProgram(parameters, cacheKey) { | |
| let program; | |
| // Check if code has been already compiled | |
| 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(); | |
| } | |
| return { | |
| getParameters: getParameters, | |
| getProgramCacheKey: getProgramCacheKey, | |
| getUniforms: getUniforms, | |
| acquireProgram: acquireProgram, | |
| releaseProgram: releaseProgram, | |
| releaseShaderCache: releaseShaderCache, | |
| // Exposed for resource monitoring & error feedback via renderer.info: | |
| programs: programs, | |
| dispose: dispose, | |
| }; | |
| } | |
| export { WebGLPrograms }; | |