提交 133895ce 编写于 作者: A alteredq

WebGLDeferredRenderer: merged with @MPanknin's spotlights.

Todo:

- physically based specular
- wrap around lighting
- light cone proxy instead of fullscreen quad
- light distance attenuation
- move spot angle cos out of shader
- move light direction out of shader
- shadow maps

See #2624
上级 ded31965
......@@ -483,7 +483,7 @@ THREE.ShaderDeferred = {
// simple specular
//"vec3 specular = specularIntensity * max( pow( dotNormalHalf, shininess ), 0.0 ) * diffuse;",
//"vec3 specular = max( pow( dotNormalHalf, shininess ), 0.0 ) * diffuse;",
// physically based specular
......@@ -506,7 +506,6 @@ THREE.ShaderDeferred = {
"}",
"}"
].join("\n"),
......@@ -531,6 +530,174 @@ THREE.ShaderDeferred = {
},
"spotLight" : {
uniforms: {
samplerNormalDepth: { type: "t", value: null },
samplerColor: { type: "t", value: null },
matView: { type: "m4", value: new THREE.Matrix4() },
matProjInverse: { type: "m4", value: new THREE.Matrix4() },
viewWidth: { type: "f", value: 800 },
viewHeight: { type: "f", value: 600 },
lightPositionWS:{ type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
lightTargetWS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
lightIntensity: { type: "f", value: 1.0 },
lightDistance: { type: "f", value: 1.0 },
lightAngle: { type: "f", value: 1.0 }
},
fragmentShader : [
"uniform sampler2D samplerColor;",
"uniform sampler2D samplerNormalDepth;",
"uniform float viewHeight;",
"uniform float viewWidth;",
"uniform float lightAngle;"+
"uniform float lightIntensity;"+
"uniform vec3 lightColor;",
"uniform mat4 matProjInverse;",
"varying vec3 vLightPositionVS;",
"varying vec3 vLightDirectionVS;",
"vec3 float_to_vec3( float data ) {",
"vec3 uncompressed;",
"uncompressed.x = fract( data );",
"float zInt = floor( data / 255.0 );",
"uncompressed.z = fract( zInt / 255.0 );",
"uncompressed.y = fract( floor( data - ( zInt * 255.0 ) ) / 255.0 );",
"return uncompressed;",
"}",
"void main() {",
"vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );",
"vec4 normalDepth = texture2D( samplerNormalDepth, texCoord );",
"float z = normalDepth.w;",
"if ( z == 0.0 ) discard;",
"float x = texCoord.x * 2.0 - 1.0;",
"float y = texCoord.y * 2.0 - 1.0;",
"vec4 projectedPos = vec4( x, y, z, 1.0 );",
"vec4 positionVS = matProjInverse * projectedPos;",
"positionVS.xyz /= positionVS.w;",
"positionVS.w = 1.0;",
// normal
"vec3 normal = normalDepth.xyz * 2.0 - 1.0;",
// color
"vec4 colorMap = texture2D( samplerColor, texCoord );",
"vec3 albedo = float_to_vec3( abs( colorMap.x ) );",
"vec3 specularColor = float_to_vec3( abs( colorMap.y ) );",
"float shininess = abs( colorMap.z );",
"float wrapAround = sign( colorMap.z );",
"float additiveSpecular = sign( colorMap.y );",
//
"vec3 surfToLight = normalize( vLightPositionVS.xyz - positionVS.xyz );",
"float dotProduct = max( dot( normal, surfToLight ), 0.0 );",
"float rho = dot( vLightDirectionVS, -surfToLight );",
"float rhoMax = cos( lightAngle * 0.5 );",
"if ( rho > rhoMax ) {",
"float theta = rhoMax + 0.0001;",
"float phi = rhoMax + 0.05;",
"float falloff = 4.0;",
"float spot = 0.0;",
"if ( rho >= phi ) {",
"spot = 1.0;",
"} else if ( rho <= theta ) {",
"spot = 0.0;",
"} else { ",
"spot = pow( ( rho - theta ) / ( phi - theta ), falloff );",
"}",
"float diffuse = spot * dotProduct;",
"vec3 halfVector = normalize( surfToLight - normalize( positionVS.xyz ) );",
"float dotNormalHalf = max( dot( normal, halfVector ), 0.0 );",
// simple specular
"vec3 specular = max( pow( dotNormalHalf, shininess ), 0.0 ) * spot * diffuse * specularColor;",
// combine
"vec3 light = lightIntensity * lightColor;",
"if ( additiveSpecular < 0.0 ) {",
"gl_FragColor = vec4( light * ( albedo * diffuse + specular ), 1.0 );",
"} else {",
"gl_FragColor = vec4( light * albedo * ( diffuse + specular ), 1.0 );",
"}",
"return;",
"}",
"gl_FragColor = vec4( 0.0 );",
"}"
].join("\n"),
vertexShader : [
"uniform vec3 lightPositionWS;",
"uniform vec3 lightTargetWS;",
"uniform mat4 matView;",
"varying vec3 vLightPositionVS;",
"varying vec3 vLightDirectionVS;",
"void main() { ",
"vec4 quadPosition = vec4( sign( position.xy ), 0.0, 1.0 );",
"gl_Position = quadPosition;",
"vLightPositionVS = vec3( matView * vec4( lightPositionWS, 1.0 ) );",
"vec3 lightDirectionWS = lightTargetWS - lightPositionWS;"+
"vLightDirectionVS = normalize( mat3( matView ) * lightDirectionWS );",
"}"
].join("\n")
},
"directionalLight" : {
uniforms: {
......
......@@ -49,6 +49,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
var emissiveLightShader = THREE.ShaderDeferred[ "emissiveLight" ];
var pointLightShader = THREE.ShaderDeferred[ "pointLight" ];
var spotLightShader = THREE.ShaderDeferred[ "spotLight" ];
var directionalLightShader = THREE.ShaderDeferred[ "directionalLight" ];
var compositeShader = THREE.ShaderDeferred[ "composite" ];
......@@ -379,6 +380,56 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
};
var createDeferredSpotLight = function ( light ) {
// setup light material
var materialLight = new THREE.ShaderMaterial( {
uniforms: THREE.UniformsUtils.clone( spotLightShader.uniforms ),
vertexShader: spotLightShader.vertexShader,
fragmentShader: spotLightShader.fragmentShader,
blending: THREE.AdditiveBlending,
depthWrite: false,
depthTest: false,
transparent: true
} );
// linear space
var intensity = light.intensity * light.intensity;
materialLight.uniforms[ "lightPositionWS" ].value.copy( light.matrixWorld.getPosition() );
materialLight.uniforms[ "lightTargetWS" ].value.copy( light.target.matrixWorld.getPosition() );
materialLight.uniforms[ "lightIntensity" ].value = intensity;
materialLight.uniforms[ "lightAngle" ].value = light.angle;
materialLight.uniforms[ "lightDistance" ].value = light.distance;
materialLight.uniforms[ "lightColor" ].value.copyGammaToLinear( light.color );
materialLight.uniforms[ "viewWidth" ].value = scaledWidth;
materialLight.uniforms[ "viewHeight" ].value = scaledHeight;
materialLight.uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
materialLight.uniforms[ 'samplerNormalDepth' ].value = compNormalDepth.renderTarget2;
// create light proxy mesh
var meshLight = new THREE.Mesh( geometryLightPlane, materialLight );
// keep reference for color and intensity updates
meshLight.properties.originalLight = light;
// keep reference for size reset
resizableMaterials.push( materialLight );
return meshLight;
};
var createDeferredDirectionalLight = function ( light ) {
// setup light material
......@@ -479,6 +530,11 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
}
} else if ( object instanceof THREE.SpotLight ) {
var meshLight = createDeferredSpotLight( object );
lightSceneFullscreen.add( meshLight );
} else if ( object instanceof THREE.DirectionalLight ) {
var meshLight = createDeferredDirectionalLight( object );
......@@ -635,6 +691,12 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
}
} else if ( originalLight instanceof THREE.SpotLight ) {
uniforms[ "lightPositionWS" ].value.copy( originalLight.matrixWorld.getPosition() );
uniforms[ "lightTargetWS" ].value.copy( originalLight.target.matrixWorld.getPosition() );
uniforms[ "lightAngle" ].value = originalLight.angle;
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册