123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- THREE.WebGLRenderer.ShaderBuilder = function ( renderer, info ) {
- this.renderer = renderer;
- this.info = info;
- this.programs = [],
- this.programs_counter = 0;
- };
- THREE.extend( THREE.WebGLRenderer.ShaderBuilder.prototype, {
- buildProgram: function ( shaderID, fragmentShader, vertexShader, uniforms, attributes, defines, parameters ) {
- var renderer = this.renderer;
- 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 = this.programs.length; p < pl; p ++ ) {
- var programInfo = this.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 = this.generateDefines( defines );
- //
- var prefix_vertex = [
- "precision " + renderer.precision + " float;",
- customDefines,
- renderer.supportsVertexTextures ? "#define VERTEX_TEXTURES" : "",
- parameters.gammaInput ? "#define GAMMA_INPUT" : "",
- parameters.gammaOutput ? "#define GAMMA_OUTPUT" : "",
- parameters.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
- "#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.boneTextureWidth ? "#define N_BONE_PIXEL_X " + parameters.boneTextureWidth.toFixed( 1 ) : "",
- parameters.boneTextureHeight ? "#define N_BONE_PIXEL_Y " + parameters.boneTextureHeight.toFixed( 1 ) : "",
- parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
- parameters.morphNormals ? "#define USE_MORPHNORMALS" : "",
- parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
- 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 " + renderer.precision + " float;",
- ( 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: "",
- parameters.gammaInput ? "#define GAMMA_INPUT" : "",
- parameters.gammaOutput ? "#define GAMMA_OUTPUT" : "",
- parameters.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
- ( 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.perPixel ? "#define PHONG_PER_PIXEL" : "",
- 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");
- program = renderer.compileShader(prefix_vertex + vertexShader, prefix_fragment + fragmentShader);
- //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' );
- } else {
- identifiers.push( 'boneGlobalMatrices' );
- }
- for ( u in uniforms ) {
- identifiers.push( u );
- }
- this.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 );
- }
- this.cacheAttributeLocations( program, identifiers );
- program.id = this.programs_counter ++;
- this.programs.push( { program: program, code: code, usedTimes: 1 } );
- this.info.memory.programs = this.programs.length;
- return program;
- },
- generateDefines: function ( 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" );
- },
- // Shader parameters cache
- cacheUniformLocations: function ( program, identifiers ) {
- var i, l, id, renderer = this.renderer;
- for ( i = 0, l = identifiers.length; i < l; i ++ ) {
- id = identifiers[ i ];
- program.uniforms[ id ] = renderer.getUniformLocation( program, id );
- }
- },
- cacheAttributeLocations: function ( program, identifiers ) {
- var i, l, id, renderer = this.renderer;
- for( i = 0, l = identifiers.length; i < l; i ++ ) {
- id = identifiers[ i ];
- program.attributes[ id ] = renderer.getAttribLocation( program, id );
- }
- },
- removeProgram: function ( program ) {
- var i, il, programInfo;
- var deleteProgram = false;
- var programs = this.programs;
- for ( i = 0, il = programs.length; i < il; i ++ ) {
- programInfo = programs[ i ];
- if ( programInfo.program === program ) {
- programInfo.usedTimes --;
- if ( programInfo.usedTimes === 0 ) {
- deleteProgram = true;
- }
- break;
- }
- }
- if ( deleteProgram === true ) {
- // avoid using array.splice, this is costlier than creating new array from scratch
- var newPrograms = [];
- for ( i = 0, il = programs.length; i < il; i ++ ) {
- programInfo = programs[ i ];
- if ( programInfo.program !== program ) {
- newPrograms.push( programInfo );
- }
- }
- this.programs = newPrograms;
- this.renderer.deleteProgram( program );
- this.info.memory.programs --;
- }
- }
- } );
|