content/hifi-content/dave/walk-tools/walkTools/libraries/three.js/renderers/webgl/WebGLProgram.js
2022-02-13 22:49:05 +01:00

459 lines
12 KiB
JavaScript

THREE.WebGLProgram = ( function () {
var programIdCount = 0;
var 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' );
};
var cacheUniformLocations = function ( gl, program, identifiers ) {
var uniforms = {};
for ( var i = 0, l = identifiers.length; i < l; i ++ ) {
var id = identifiers[ i ];
uniforms[ id ] = gl.getUniformLocation( program, id );
}
return uniforms;
};
var cacheAttributeLocations = function ( gl, program, identifiers ) {
var attributes = {};
for ( var i = 0, l = identifiers.length; i < l; i ++ ) {
var id = identifiers[ i ];
attributes[ id ] = gl.getAttribLocation( program, id );
}
return attributes;
};
return function ( renderer, code, material, parameters ) {
var _this = renderer;
var _gl = _this.context;
var defines = material.defines;
var uniforms = material.__webglShader.uniforms;
var attributes = material.attributes;
var vertexShader = material.__webglShader.vertexShader;
var fragmentShader = material.__webglShader.fragmentShader;
var index0AttributeName = material.index0AttributeName;
if ( index0AttributeName === undefined && parameters.morphTargets === true ) {
// programs with morphTargets displace position out of attribute 0
index0AttributeName = 'position';
}
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';
}
var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
if ( parameters.envMap ) {
switch ( material.envMap.mapping ) {
case THREE.CubeReflectionMapping:
case THREE.CubeRefractionMapping:
envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
break;
case THREE.EquirectangularReflectionMapping:
case THREE.EquirectangularRefractionMapping:
envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
break;
case THREE.SphericalReflectionMapping:
envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
break;
}
switch ( material.envMap.mapping ) {
case THREE.CubeRefractionMapping:
case THREE.EquirectangularRefractionMapping:
envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
break;
}
switch ( material.combine ) {
case THREE.MultiplyOperation:
envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
break;
case THREE.MixOperation:
envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
break;
case THREE.AddOperation:
envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
break;
}
}
var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
// console.log( 'building new program ' );
//
var customDefines = generateDefines( defines );
//
var program = _gl.createProgram();
var prefix_vertex, prefix_fragment;
if ( material instanceof THREE.RawShaderMaterial ) {
prefix_vertex = '';
prefix_fragment = '';
} else {
prefix_vertex = [
'precision ' + parameters.precision + ' float;',
'precision ' + parameters.precision + ' int;',
customDefines,
parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
_this.gammaInput ? '#define GAMMA_INPUT' : '',
_this.gammaOutput ? '#define GAMMA_OUTPUT' : '',
'#define GAMMA_FACTOR ' + gammaFactorDefine,
'#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.envMap ? '#define ' + envMapModeDefine : '',
parameters.lightMap ? '#define USE_LIGHTMAP' : '',
parameters.bumpMap ? '#define USE_BUMPMAP' : '',
parameters.normalMap ? '#define USE_NORMALMAP' : '',
parameters.specularMap ? '#define USE_SPECULARMAP' : '',
parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
parameters.vertexColors ? '#define USE_COLOR' : '',
parameters.flatShading ? '#define FLAT_SHADED': '',
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' : '',
parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
//_this._glExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '',
'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' );
prefix_fragment = [
'precision ' + parameters.precision + ' float;',
'precision ' + parameters.precision + ' int;',
( parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#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' : '',
'#define GAMMA_FACTOR ' + gammaFactorDefine,
( 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.envMap ? '#define ' + envMapTypeDefine : '',
parameters.envMap ? '#define ' + envMapModeDefine : '',
parameters.envMap ? '#define ' + envMapBlendingDefine : '',
parameters.lightMap ? '#define USE_LIGHTMAP' : '',
parameters.bumpMap ? '#define USE_BUMPMAP' : '',
parameters.normalMap ? '#define USE_NORMALMAP' : '',
parameters.specularMap ? '#define USE_SPECULARMAP' : '',
parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
parameters.vertexColors ? '#define USE_COLOR' : '',
parameters.flatShading ? '#define FLAT_SHADED': '',
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' : '',
parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
//_this._glExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '',
'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 );
if ( index0AttributeName !== undefined ) {
// 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
_gl.bindAttribLocation( program, 0, index0AttributeName );
}
_gl.linkProgram( program );
var programLogInfo = _gl.getProgramInfoLog( program );
if ( _gl.getProgramParameter( program, _gl.LINK_STATUS ) === false ) {
THREE.error( 'THREE.WebGLProgram: shader error: ' + _gl.getError(), 'gl.VALIDATE_STATUS', _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ), 'gl.getPRogramInfoLog', programLogInfo );
}
if ( programLogInfo !== '' ) {
THREE.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()' + programLogInfo );
// THREE.warn( _gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) );
// THREE.warn( _gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) );
}
// clean up
_gl.deleteShader( glVertexShader );
_gl.deleteShader( glFragmentShader );
// cache uniform locations
var identifiers = [
'viewMatrix',
'modelViewMatrix',
'projectionMatrix',
'normalMatrix',
'modelMatrix',
'cameraPosition',
'morphTargetInfluences',
'bindMatrix',
'bindMatrixInverse'
];
if ( parameters.useVertexTexture ) {
identifiers.push( 'boneTexture' );
identifiers.push( 'boneTextureWidth' );
identifiers.push( 'boneTextureHeight' );
} else {
identifiers.push( 'boneGlobalMatrices' );
}
if ( parameters.logarithmicDepthBuffer ) {
identifiers.push('logDepthBufFC');
}
for ( var u in uniforms ) {
identifiers.push( u );
}
this.uniforms = cacheUniformLocations( _gl, program, identifiers );
// cache attributes locations
identifiers = [
'position',
'normal',
'uv',
'uv2',
'tangent',
'color',
'skinIndex',
'skinWeight',
'lineDistance'
];
for ( var i = 0; i < parameters.maxMorphTargets; i ++ ) {
identifiers.push( 'morphTarget' + i );
}
for ( var i = 0; i < parameters.maxMorphNormals; i ++ ) {
identifiers.push( 'morphNormal' + i );
}
for ( var a in attributes ) {
identifiers.push( a );
}
this.attributes = cacheAttributeLocations( _gl, program, identifiers );
this.attributesKeys = Object.keys( this.attributes );
//
this.id = programIdCount ++;
this.code = code;
this.usedTimes = 1;
this.program = program;
this.vertexShader = glVertexShader;
this.fragmentShader = glFragmentShader;
return this;
};
} )();