|
@@ -106,7 +106,6 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
var _this = this,
|
|
var _this = this,
|
|
|
|
|
|
_programs = [],
|
|
_programs = [],
|
|
- _programs_counter = 0,
|
|
|
|
|
|
|
|
// internal state cache
|
|
// internal state cache
|
|
|
|
|
|
@@ -4084,6 +4083,9 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
|
|
|
|
parameters = {
|
|
parameters = {
|
|
|
|
|
|
|
|
+ precision: _precision,
|
|
|
|
+ supportsVertexTextures: _supportsVertexTextures,
|
|
|
|
+
|
|
map: !!material.map,
|
|
map: !!material.map,
|
|
envMap: !!material.envMap,
|
|
envMap: !!material.envMap,
|
|
lightMap: !!material.lightMap,
|
|
lightMap: !!material.lightMap,
|
|
@@ -4127,7 +4129,66 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
- material.program = buildProgram( shaderID, material.fragmentShader, material.vertexShader, material.uniforms, material.attributes, material.defines, parameters, material.index0AttributeName );
|
|
|
|
|
|
+ // Generate code
|
|
|
|
+
|
|
|
|
+ var chunks = [];
|
|
|
|
+
|
|
|
|
+ if ( shaderID ) {
|
|
|
|
+
|
|
|
|
+ chunks.push( shaderID );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ chunks.push( material.fragmentShader );
|
|
|
|
+ chunks.push( material.vertexShader );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for ( var d in material.defines ) {
|
|
|
|
+
|
|
|
|
+ chunks.push( d );
|
|
|
|
+ chunks.push( material.defines[ d ] );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for ( var p in parameters ) {
|
|
|
|
+
|
|
|
|
+ chunks.push( p );
|
|
|
|
+ chunks.push( parameters[ p ] );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var code = chunks.join();
|
|
|
|
+
|
|
|
|
+ var program;
|
|
|
|
+
|
|
|
|
+ // Check if code has been already compiled
|
|
|
|
+
|
|
|
|
+ for ( var p = 0, pl = _programs.length; p < pl; p ++ ) {
|
|
|
|
+
|
|
|
|
+ var programInfo = _programs[ p ];
|
|
|
|
+
|
|
|
|
+ if ( programInfo.code === code ) {
|
|
|
|
+
|
|
|
|
+ program = programInfo;
|
|
|
|
+ program.usedTimes ++;
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ( program === undefined ) {
|
|
|
|
+
|
|
|
|
+ program = new THREE.WebGLProgram( this, code, material, parameters );
|
|
|
|
+ _programs.push( program );
|
|
|
|
+
|
|
|
|
+ _this.info.memory.programs = _programs.length;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ material.program = program;
|
|
|
|
|
|
var attributes = material.program.attributes;
|
|
var attributes = material.program.attributes;
|
|
|
|
|
|
@@ -4218,10 +4279,10 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
p_uniforms = program.uniforms,
|
|
p_uniforms = program.uniforms,
|
|
m_uniforms = material.uniforms;
|
|
m_uniforms = material.uniforms;
|
|
|
|
|
|
- if ( program !== _currentProgram ) {
|
|
|
|
|
|
+ if ( program.id !== _currentProgram ) {
|
|
|
|
|
|
- _gl.useProgram( program );
|
|
|
|
- _currentProgram = program;
|
|
|
|
|
|
+ _gl.useProgram( program.program );
|
|
|
|
+ _currentProgram = program.id;
|
|
|
|
|
|
refreshMaterial = true;
|
|
refreshMaterial = true;
|
|
|
|
|
|
@@ -5357,394 +5418,6 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
- // Defines
|
|
|
|
-
|
|
|
|
- function generateDefines ( defines ) {
|
|
|
|
-
|
|
|
|
- var value, chunk, chunks = [];
|
|
|
|
-
|
|
|
|
- for ( var d in defines ) {
|
|
|
|
-
|
|
|
|
- value = defines[ d ];
|
|
|
|
- if ( value === false ) continue;
|
|
|
|
-
|
|
|
|
- chunk = "#define " + d + " " + value;
|
|
|
|
- chunks.push( chunk );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return chunks.join( "\n" );
|
|
|
|
-
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // Shaders
|
|
|
|
-
|
|
|
|
- function buildProgram( shaderID, fragmentShader, vertexShader, uniforms, attributes, defines, parameters, index0AttributeName ) {
|
|
|
|
-
|
|
|
|
- var p, pl, d, program, code;
|
|
|
|
- var chunks = [];
|
|
|
|
-
|
|
|
|
- // Generate code
|
|
|
|
-
|
|
|
|
- if ( shaderID ) {
|
|
|
|
-
|
|
|
|
- chunks.push( shaderID );
|
|
|
|
-
|
|
|
|
- } else {
|
|
|
|
-
|
|
|
|
- chunks.push( fragmentShader );
|
|
|
|
- chunks.push( vertexShader );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- for ( d in defines ) {
|
|
|
|
-
|
|
|
|
- chunks.push( d );
|
|
|
|
- chunks.push( defines[ d ] );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- for ( p in parameters ) {
|
|
|
|
-
|
|
|
|
- chunks.push( p );
|
|
|
|
- chunks.push( parameters[ p ] );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- code = chunks.join();
|
|
|
|
-
|
|
|
|
- // Check if code has been already compiled
|
|
|
|
-
|
|
|
|
- for ( p = 0, pl = _programs.length; p < pl; p ++ ) {
|
|
|
|
-
|
|
|
|
- var programInfo = _programs[ p ];
|
|
|
|
-
|
|
|
|
- if ( programInfo.code === code ) {
|
|
|
|
-
|
|
|
|
- // console.log( "Code already compiled." /*: \n\n" + code*/ );
|
|
|
|
-
|
|
|
|
- programInfo.usedTimes ++;
|
|
|
|
-
|
|
|
|
- return programInfo.program;
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- var shadowMapTypeDefine = "SHADOWMAP_TYPE_BASIC";
|
|
|
|
-
|
|
|
|
- if ( parameters.shadowMapType === THREE.PCFShadowMap ) {
|
|
|
|
-
|
|
|
|
- shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF";
|
|
|
|
-
|
|
|
|
- } else if ( parameters.shadowMapType === THREE.PCFSoftShadowMap ) {
|
|
|
|
-
|
|
|
|
- shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF_SOFT";
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // console.log( "building new program " );
|
|
|
|
-
|
|
|
|
- //
|
|
|
|
-
|
|
|
|
- var customDefines = generateDefines( defines );
|
|
|
|
-
|
|
|
|
- //
|
|
|
|
-
|
|
|
|
- program = _gl.createProgram();
|
|
|
|
-
|
|
|
|
- var prefix_vertex = [
|
|
|
|
-
|
|
|
|
- "precision " + _precision + " float;",
|
|
|
|
- "precision " + _precision + " int;",
|
|
|
|
-
|
|
|
|
- customDefines,
|
|
|
|
-
|
|
|
|
- _supportsVertexTextures ? "#define VERTEX_TEXTURES" : "",
|
|
|
|
-
|
|
|
|
- _this.gammaInput ? "#define GAMMA_INPUT" : "",
|
|
|
|
- _this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
|
|
|
|
-
|
|
|
|
- "#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
|
|
|
|
- "#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
|
|
|
|
- "#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
|
|
|
|
- "#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
|
|
|
|
-
|
|
|
|
- "#define MAX_SHADOWS " + parameters.maxShadows,
|
|
|
|
-
|
|
|
|
- "#define MAX_BONES " + parameters.maxBones,
|
|
|
|
-
|
|
|
|
- parameters.map ? "#define USE_MAP" : "",
|
|
|
|
- parameters.envMap ? "#define USE_ENVMAP" : "",
|
|
|
|
- parameters.lightMap ? "#define USE_LIGHTMAP" : "",
|
|
|
|
- parameters.bumpMap ? "#define USE_BUMPMAP" : "",
|
|
|
|
- parameters.normalMap ? "#define USE_NORMALMAP" : "",
|
|
|
|
- parameters.specularMap ? "#define USE_SPECULARMAP" : "",
|
|
|
|
- parameters.vertexColors ? "#define USE_COLOR" : "",
|
|
|
|
-
|
|
|
|
- parameters.skinning ? "#define USE_SKINNING" : "",
|
|
|
|
- parameters.useVertexTexture ? "#define BONE_TEXTURE" : "",
|
|
|
|
-
|
|
|
|
- parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
|
|
|
|
- parameters.morphNormals ? "#define USE_MORPHNORMALS" : "",
|
|
|
|
- parameters.wrapAround ? "#define WRAP_AROUND" : "",
|
|
|
|
- parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
|
|
|
|
- parameters.flipSided ? "#define FLIP_SIDED" : "",
|
|
|
|
-
|
|
|
|
- parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
|
|
|
|
- parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
|
|
|
|
- parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
|
|
|
|
- parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
|
|
|
|
-
|
|
|
|
- parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",
|
|
|
|
-
|
|
|
|
- "uniform mat4 modelMatrix;",
|
|
|
|
- "uniform mat4 modelViewMatrix;",
|
|
|
|
- "uniform mat4 projectionMatrix;",
|
|
|
|
- "uniform mat4 viewMatrix;",
|
|
|
|
- "uniform mat3 normalMatrix;",
|
|
|
|
- "uniform vec3 cameraPosition;",
|
|
|
|
-
|
|
|
|
- "attribute vec3 position;",
|
|
|
|
- "attribute vec3 normal;",
|
|
|
|
- "attribute vec2 uv;",
|
|
|
|
- "attribute vec2 uv2;",
|
|
|
|
-
|
|
|
|
- "#ifdef USE_COLOR",
|
|
|
|
-
|
|
|
|
- " attribute vec3 color;",
|
|
|
|
-
|
|
|
|
- "#endif",
|
|
|
|
-
|
|
|
|
- "#ifdef USE_MORPHTARGETS",
|
|
|
|
-
|
|
|
|
- " attribute vec3 morphTarget0;",
|
|
|
|
- " attribute vec3 morphTarget1;",
|
|
|
|
- " attribute vec3 morphTarget2;",
|
|
|
|
- " attribute vec3 morphTarget3;",
|
|
|
|
-
|
|
|
|
- " #ifdef USE_MORPHNORMALS",
|
|
|
|
-
|
|
|
|
- " attribute vec3 morphNormal0;",
|
|
|
|
- " attribute vec3 morphNormal1;",
|
|
|
|
- " attribute vec3 morphNormal2;",
|
|
|
|
- " attribute vec3 morphNormal3;",
|
|
|
|
-
|
|
|
|
- " #else",
|
|
|
|
-
|
|
|
|
- " attribute vec3 morphTarget4;",
|
|
|
|
- " attribute vec3 morphTarget5;",
|
|
|
|
- " attribute vec3 morphTarget6;",
|
|
|
|
- " attribute vec3 morphTarget7;",
|
|
|
|
-
|
|
|
|
- " #endif",
|
|
|
|
-
|
|
|
|
- "#endif",
|
|
|
|
-
|
|
|
|
- "#ifdef USE_SKINNING",
|
|
|
|
-
|
|
|
|
- " attribute vec4 skinIndex;",
|
|
|
|
- " attribute vec4 skinWeight;",
|
|
|
|
-
|
|
|
|
- "#endif",
|
|
|
|
-
|
|
|
|
- ""
|
|
|
|
-
|
|
|
|
- ].join("\n");
|
|
|
|
-
|
|
|
|
- var prefix_fragment = [
|
|
|
|
-
|
|
|
|
- "precision " + _precision + " float;",
|
|
|
|
- "precision " + _precision + " int;",
|
|
|
|
-
|
|
|
|
- ( parameters.bumpMap || parameters.normalMap ) ? "#extension GL_OES_standard_derivatives : enable" : "",
|
|
|
|
-
|
|
|
|
- customDefines,
|
|
|
|
-
|
|
|
|
- "#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
|
|
|
|
- "#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
|
|
|
|
- "#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
|
|
|
|
- "#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
|
|
|
|
-
|
|
|
|
- "#define MAX_SHADOWS " + parameters.maxShadows,
|
|
|
|
-
|
|
|
|
- parameters.alphaTest ? "#define ALPHATEST " + parameters.alphaTest: "",
|
|
|
|
-
|
|
|
|
- _this.gammaInput ? "#define GAMMA_INPUT" : "",
|
|
|
|
- _this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
|
|
|
|
-
|
|
|
|
- ( parameters.useFog && parameters.fog ) ? "#define USE_FOG" : "",
|
|
|
|
- ( parameters.useFog && parameters.fogExp ) ? "#define FOG_EXP2" : "",
|
|
|
|
-
|
|
|
|
- parameters.map ? "#define USE_MAP" : "",
|
|
|
|
- parameters.envMap ? "#define USE_ENVMAP" : "",
|
|
|
|
- parameters.lightMap ? "#define USE_LIGHTMAP" : "",
|
|
|
|
- parameters.bumpMap ? "#define USE_BUMPMAP" : "",
|
|
|
|
- parameters.normalMap ? "#define USE_NORMALMAP" : "",
|
|
|
|
- parameters.specularMap ? "#define USE_SPECULARMAP" : "",
|
|
|
|
- parameters.vertexColors ? "#define USE_COLOR" : "",
|
|
|
|
-
|
|
|
|
- parameters.metal ? "#define METAL" : "",
|
|
|
|
- parameters.wrapAround ? "#define WRAP_AROUND" : "",
|
|
|
|
- parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
|
|
|
|
- parameters.flipSided ? "#define FLIP_SIDED" : "",
|
|
|
|
-
|
|
|
|
- parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
|
|
|
|
- parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
|
|
|
|
- parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
|
|
|
|
- parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
|
|
|
|
-
|
|
|
|
- "uniform mat4 viewMatrix;",
|
|
|
|
- "uniform vec3 cameraPosition;",
|
|
|
|
- ""
|
|
|
|
-
|
|
|
|
- ].join( '\n' );
|
|
|
|
-
|
|
|
|
- var glVertexShader = new THREE.WebGLShader( _gl, _gl.VERTEX_SHADER, prefix_vertex + vertexShader );
|
|
|
|
- var glFragmentShader = new THREE.WebGLShader( _gl, _gl.FRAGMENT_SHADER, prefix_fragment + fragmentShader );
|
|
|
|
-
|
|
|
|
- _gl.attachShader( program, glVertexShader );
|
|
|
|
- _gl.attachShader( program, glFragmentShader );
|
|
|
|
-
|
|
|
|
- // Force a particular attribute to index 0.
|
|
|
|
- // because potentially expensive emulation is done by browser if attribute 0 is disabled.
|
|
|
|
- // And, color, for example is often automatically bound to index 0 so disabling it
|
|
|
|
- if ( index0AttributeName !== undefined ) {
|
|
|
|
-
|
|
|
|
- _gl.bindAttribLocation( program, 0, index0AttributeName );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- _gl.linkProgram( program );
|
|
|
|
-
|
|
|
|
- if ( _gl.getProgramParameter( program, _gl.LINK_STATUS ) === false ) {
|
|
|
|
-
|
|
|
|
- console.error( 'Could not initialise shader' );
|
|
|
|
- console.error( 'gl.VALIDATE_STATUS', _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) );
|
|
|
|
- console.error( 'gl.getError()', _gl.getError() );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if ( _gl.getProgramInfoLog( program ) !== '' ) {
|
|
|
|
-
|
|
|
|
- console.error( 'gl.getProgramInfoLog()', _gl.getProgramInfoLog( program ) );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- program.vertexShader = _gl.getShaderSource( glVertexShader );
|
|
|
|
- program.fragmentShader = _gl.getShaderSource( glFragmentShader );
|
|
|
|
-
|
|
|
|
- // clean up
|
|
|
|
-
|
|
|
|
- _gl.deleteShader( glVertexShader );
|
|
|
|
- _gl.deleteShader( glFragmentShader );
|
|
|
|
-
|
|
|
|
- // console.log( prefix_fragment + fragmentShader );
|
|
|
|
- // console.log( prefix_vertex + vertexShader );
|
|
|
|
-
|
|
|
|
- program.uniforms = {};
|
|
|
|
- program.attributes = {};
|
|
|
|
-
|
|
|
|
- var identifiers, u, a, i;
|
|
|
|
-
|
|
|
|
- // cache uniform locations
|
|
|
|
-
|
|
|
|
- identifiers = [
|
|
|
|
-
|
|
|
|
- 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'modelMatrix', 'cameraPosition',
|
|
|
|
- 'morphTargetInfluences'
|
|
|
|
-
|
|
|
|
- ];
|
|
|
|
-
|
|
|
|
- if ( parameters.useVertexTexture ) {
|
|
|
|
-
|
|
|
|
- identifiers.push( 'boneTexture' );
|
|
|
|
- identifiers.push( 'boneTextureWidth' );
|
|
|
|
- identifiers.push( 'boneTextureHeight' );
|
|
|
|
-
|
|
|
|
- } else {
|
|
|
|
-
|
|
|
|
- identifiers.push( 'boneGlobalMatrices' );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- for ( u in uniforms ) {
|
|
|
|
-
|
|
|
|
- identifiers.push( u );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- cacheUniformLocations( program, identifiers );
|
|
|
|
-
|
|
|
|
- // cache attributes locations
|
|
|
|
-
|
|
|
|
- identifiers = [
|
|
|
|
-
|
|
|
|
- "position", "normal", "uv", "uv2", "tangent", "color",
|
|
|
|
- "skinIndex", "skinWeight", "lineDistance"
|
|
|
|
-
|
|
|
|
- ];
|
|
|
|
-
|
|
|
|
- for ( i = 0; i < parameters.maxMorphTargets; i ++ ) {
|
|
|
|
-
|
|
|
|
- identifiers.push( "morphTarget" + i );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- for ( i = 0; i < parameters.maxMorphNormals; i ++ ) {
|
|
|
|
-
|
|
|
|
- identifiers.push( "morphNormal" + i );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- for ( a in attributes ) {
|
|
|
|
-
|
|
|
|
- identifiers.push( a );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- cacheAttributeLocations( program, identifiers );
|
|
|
|
-
|
|
|
|
- program.id = _programs_counter ++;
|
|
|
|
-
|
|
|
|
- _programs.push( { program: program, code: code, usedTimes: 1 } );
|
|
|
|
-
|
|
|
|
- _this.info.memory.programs = _programs.length;
|
|
|
|
-
|
|
|
|
- return program;
|
|
|
|
-
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // Shader parameters cache
|
|
|
|
-
|
|
|
|
- function cacheUniformLocations ( program, identifiers ) {
|
|
|
|
-
|
|
|
|
- var i, l, id;
|
|
|
|
-
|
|
|
|
- for( i = 0, l = identifiers.length; i < l; i ++ ) {
|
|
|
|
-
|
|
|
|
- id = identifiers[ i ];
|
|
|
|
- program.uniforms[ id ] = _gl.getUniformLocation( program, id );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- function cacheAttributeLocations ( program, identifiers ) {
|
|
|
|
-
|
|
|
|
- var i, l, id;
|
|
|
|
-
|
|
|
|
- for( i = 0, l = identifiers.length; i < l; i ++ ) {
|
|
|
|
-
|
|
|
|
- id = identifiers[ i ];
|
|
|
|
- program.attributes[ id ] = _gl.getAttribLocation( program, id );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
// Textures
|
|
// Textures
|
|
|
|
|
|
function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {
|
|
function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {
|