|
@@ -213,6 +213,7 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
|
var state = new THREE.WebGLState( _gl, extensions, paramThreeToGL );
|
|
|
var properties = new THREE.WebGLProperties();
|
|
|
var objects = new THREE.WebGLObjects( _gl, properties, this.info );
|
|
|
+ var programCache = new THREE.WebGLPrograms( this, capabilities );
|
|
|
|
|
|
var bufferRenderer = new THREE.WebGLBufferRenderer( _gl, extensions, _infoRender );
|
|
|
var indexedBufferRenderer = new THREE.WebGLIndexedBufferRenderer( _gl, extensions, _infoRender );
|
|
@@ -1320,7 +1321,7 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
|
|
|
|
pushImmediateRenderItem( object );
|
|
|
|
|
|
- } else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.PointCloud ){
|
|
|
+ } else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.PointCloud ) {
|
|
|
|
|
|
if ( object instanceof THREE.SkinnedMesh ) {
|
|
|
|
|
@@ -1432,135 +1433,14 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- // Materials
|
|
|
-
|
|
|
- var shaderIDs = {
|
|
|
- MeshDepthMaterial: 'depth',
|
|
|
- MeshNormalMaterial: 'normal',
|
|
|
- MeshBasicMaterial: 'basic',
|
|
|
- MeshLambertMaterial: 'lambert',
|
|
|
- MeshPhongMaterial: 'phong',
|
|
|
- LineBasicMaterial: 'basic',
|
|
|
- LineDashedMaterial: 'dashed',
|
|
|
- PointCloudMaterial: 'particle_basic'
|
|
|
- };
|
|
|
-
|
|
|
function initMaterial( material, lights, fog, object ) {
|
|
|
|
|
|
var materialProperties = properties.get( material );
|
|
|
|
|
|
- var shaderID = shaderIDs[ material.type ];
|
|
|
-
|
|
|
- // heuristics to create shader parameters according to lights in the scene
|
|
|
- // (not to blow over maxLights budget)
|
|
|
-
|
|
|
- var maxLightCount = allocateLights( lights );
|
|
|
- var maxShadows = allocateShadows( lights );
|
|
|
- var maxBones = allocateBones( object );
|
|
|
- var precision = capabilities.precision;
|
|
|
-
|
|
|
- if ( material.precision !== null ) {
|
|
|
-
|
|
|
- precision = capabilities.getMaxPrecision( material.precision );
|
|
|
-
|
|
|
- if ( precision !== material.precision ) {
|
|
|
-
|
|
|
- console.warn( 'THREE.WebGLRenderer.initMaterial:', material.precision, 'not supported, using', precision, 'instead.' );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- var parameters = {
|
|
|
-
|
|
|
- precision: precision,
|
|
|
- supportsVertexTextures: capabilities.vertexTextures,
|
|
|
-
|
|
|
- map: !! material.map,
|
|
|
- envMap: !! material.envMap,
|
|
|
- envMapMode: material.envMap && material.envMap.mapping,
|
|
|
- lightMap: !! material.lightMap,
|
|
|
- aoMap: !! material.aoMap,
|
|
|
- emissiveMap: !! material.emissiveMap,
|
|
|
- bumpMap: !! material.bumpMap,
|
|
|
- normalMap: !! material.normalMap,
|
|
|
- displacementMap: !! material.displacementMap,
|
|
|
- specularMap: !! material.specularMap,
|
|
|
- alphaMap: !! material.alphaMap,
|
|
|
-
|
|
|
- combine: material.combine,
|
|
|
-
|
|
|
- vertexColors: material.vertexColors,
|
|
|
-
|
|
|
- fog: fog,
|
|
|
- useFog: material.fog,
|
|
|
- fogExp: fog instanceof THREE.FogExp2,
|
|
|
-
|
|
|
- flatShading: material.shading === THREE.FlatShading,
|
|
|
-
|
|
|
- sizeAttenuation: material.sizeAttenuation,
|
|
|
- logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
|
|
|
-
|
|
|
- skinning: material.skinning,
|
|
|
- maxBones: maxBones,
|
|
|
- useVertexTexture: capabilities.floatVertexTextures && object && object.skeleton && object.skeleton.useVertexTexture,
|
|
|
-
|
|
|
- morphTargets: material.morphTargets,
|
|
|
- morphNormals: material.morphNormals,
|
|
|
- maxMorphTargets: _this.maxMorphTargets,
|
|
|
- maxMorphNormals: _this.maxMorphNormals,
|
|
|
-
|
|
|
- maxDirLights: maxLightCount.directional,
|
|
|
- maxPointLights: maxLightCount.point,
|
|
|
- maxSpotLights: maxLightCount.spot,
|
|
|
- maxHemiLights: maxLightCount.hemi,
|
|
|
-
|
|
|
- maxShadows: maxShadows,
|
|
|
- shadowMapEnabled: shadowMap.enabled && object.receiveShadow && maxShadows > 0,
|
|
|
- shadowMapType: shadowMap.type,
|
|
|
- shadowMapDebug: shadowMap.debug,
|
|
|
-
|
|
|
- alphaTest: material.alphaTest,
|
|
|
- metal: material.metal,
|
|
|
- doubleSided: material.side === THREE.DoubleSide,
|
|
|
- flipSided: material.side === THREE.BackSide
|
|
|
-
|
|
|
- };
|
|
|
+ var parameters = programCache.getParameters( material, lights, fog, object );
|
|
|
+ var code = programCache.getProgramCode( material, parameters );
|
|
|
|
|
|
- // Generate code
|
|
|
|
|
|
- var chunks = [];
|
|
|
-
|
|
|
- if ( shaderID ) {
|
|
|
-
|
|
|
- chunks.push( shaderID );
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- chunks.push( material.fragmentShader );
|
|
|
- chunks.push( material.vertexShader );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( material.defines !== undefined ) {
|
|
|
-
|
|
|
- for ( var name in material.defines ) {
|
|
|
-
|
|
|
- chunks.push( name );
|
|
|
- chunks.push( material.defines[ name ] );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- for ( var name in parameters ) {
|
|
|
-
|
|
|
- chunks.push( name );
|
|
|
- chunks.push( parameters[ name ] );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- var code = chunks.join();
|
|
|
var programChange = true;
|
|
|
|
|
|
if ( ! materialProperties.program ) {
|
|
@@ -1573,7 +1453,7 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
|
// changed glsl or parameters
|
|
|
releaseMaterialProgramReference( material );
|
|
|
|
|
|
- } else if ( shaderID !== undefined ) {
|
|
|
+ } else if ( parameters.shaderID !== undefined ) {
|
|
|
|
|
|
// same glsl and uniform list
|
|
|
return;
|
|
@@ -1585,9 +1465,9 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- if ( shaderID ) {
|
|
|
+ if ( parameters.shaderID ) {
|
|
|
|
|
|
- var shader = THREE.ShaderLib[ shaderID ];
|
|
|
+ var shader = THREE.ShaderLib[ parameters.shaderID ];
|
|
|
|
|
|
materialProperties.__webglShader = {
|
|
|
name: material.type,
|
|
@@ -1607,37 +1487,13 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- var program;
|
|
|
-
|
|
|
- // Check if code has been already compiled
|
|
|
+ material.__webglShader = materialProperties.__webglShader;
|
|
|
|
|
|
- for ( var p = 0, pl = _programs.length; p < pl; p ++ ) {
|
|
|
+ var program = programCache.getProgram( material, parameters, code );
|
|
|
|
|
|
- var programInfo = _programs[ p ];
|
|
|
+ if ( programChange ) {
|
|
|
|
|
|
- if ( programInfo.code === code ) {
|
|
|
-
|
|
|
- program = programInfo;
|
|
|
-
|
|
|
- if ( programChange ) {
|
|
|
-
|
|
|
- program.usedTimes ++;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( program === undefined ) {
|
|
|
-
|
|
|
- material.__webglShader = materialProperties.__webglShader;
|
|
|
- program = new THREE.WebGLProgram( _this, code, material, parameters );
|
|
|
- _programs.push( program );
|
|
|
-
|
|
|
- _infoMemory.programs = _programs.length;
|
|
|
+ program.usedTimes ++;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -3549,89 +3405,6 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- // Allocations
|
|
|
-
|
|
|
- function allocateBones ( object ) {
|
|
|
-
|
|
|
- if ( capabilities.floatVertexTextures && object && object.skeleton && object.skeleton.useVertexTexture ) {
|
|
|
-
|
|
|
- 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)
|
|
|
-
|
|
|
- var nVertexUniforms = _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS );
|
|
|
- var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
|
|
|
-
|
|
|
- var maxBones = nVertexMatrices;
|
|
|
-
|
|
|
- if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
|
|
|
-
|
|
|
- maxBones = Math.min( object.skeleton.bones.length, maxBones );
|
|
|
-
|
|
|
- if ( maxBones < object.skeleton.bones.length ) {
|
|
|
-
|
|
|
- console.warn( 'WebGLRenderer: too many bones - ' + object.skeleton.bones.length + ', this GPU supports just ' + maxBones + ' (try OpenGL instead of ANGLE)' );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return maxBones;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- function allocateLights( lights ) {
|
|
|
-
|
|
|
- var dirLights = 0;
|
|
|
- var pointLights = 0;
|
|
|
- var spotLights = 0;
|
|
|
- var hemiLights = 0;
|
|
|
-
|
|
|
- for ( var l = 0, ll = lights.length; l < ll; l ++ ) {
|
|
|
-
|
|
|
- var light = lights[ l ];
|
|
|
-
|
|
|
- if ( light.onlyShadow || light.visible === false ) continue;
|
|
|
-
|
|
|
- if ( light instanceof THREE.DirectionalLight ) dirLights ++;
|
|
|
- if ( light instanceof THREE.PointLight ) pointLights ++;
|
|
|
- if ( light instanceof THREE.SpotLight ) spotLights ++;
|
|
|
- if ( light instanceof THREE.HemisphereLight ) hemiLights ++;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return { 'directional': dirLights, 'point': pointLights, 'spot': spotLights, 'hemi': hemiLights };
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- function allocateShadows( lights ) {
|
|
|
-
|
|
|
- var maxShadows = 0;
|
|
|
-
|
|
|
- for ( var l = 0, ll = lights.length; l < ll; l ++ ) {
|
|
|
-
|
|
|
- var light = lights[ l ];
|
|
|
-
|
|
|
- if ( ! light.castShadow ) continue;
|
|
|
-
|
|
|
- if ( light instanceof THREE.SpotLight ) maxShadows ++;
|
|
|
- if ( light instanceof THREE.DirectionalLight ) maxShadows ++;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return maxShadows;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
// DEPRECATED
|
|
|
|
|
|
this.supportsFloatTextures = function () {
|