提交 34dcfcb0 编写于 作者: A alteredq

Merge branch 'morph_normals' into dev

此差异已折叠。
此差异已折叠。
因为 它太大了无法显示 source diff 。你可以改为 查看blob
此差异已折叠。
因为 它太大了无法显示 source diff 。你可以改为 查看blob
<!doctype html>
<html lang="en">
<head>
<title>three.js webgl - morph normals - horse</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #111;
color: #fff;
margin: 0px;
overflow: hidden;
}
a { color: #f00 }
</style>
</head>
<body>
<script src="../build/Three.js"></script>
<script src="js/Detector.js"></script>
<script src="js/Stats.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var container, stats;
var camera, scene1, scene2, renderer;
var morphs = [];
var clock = new THREE.Clock();
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = '<a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> webgl - morph normals - model by <a href="http://mirada.com/">mirada</a> from <a href="http://ro.me">rome</a>';
container.appendChild( info );
//
scene1 = new THREE.Scene();
scene2 = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 40, 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
camera.position.y = 300;
scene1.add( camera );
camera.target = new THREE.Vector3( 0, 150, 0 );
//
var light = new THREE.DirectionalLight( 0xffffff, 1.3 );
light.position.set( 1, 1, 1 );
scene1.add( light );
var light = new THREE.DirectionalLight( 0xffffff, 0.1 );
light.position.set( 0.25, -1, 0 );
scene1.add( light );
//
var light = new THREE.DirectionalLight( 0xffffff, 1.3 );
light.position.set( 1, 1, 1 );
scene2.add( light );
var light = new THREE.DirectionalLight( 0xffffff, 0.1 );
light.position.set( 0.25, -1, 0 );
scene2.add( light );
//
var loader = new THREE.JSONLoader();
loader.load( "models/animated/flamingo.js", function( geometry ) {
morphColorsToFaceColors( geometry );
geometry.computeVertexNormals();
var material = new THREE.MeshLambertMaterial( { color: 0xffffff, morphTargets: true, morphNormals: true, vertexColors: THREE.FaceColors, shading: THREE.FlatShading } );
var meshAnim = new THREE.MorphAnimMesh( geometry, material );
meshAnim.duration = 5000;
meshAnim.scale.set( 1.5, 1.5, 1.5 );
meshAnim.position.y = 150;
scene1.add( meshAnim );
morphs.push( meshAnim );
} );
loader.load( "models/animated/flamingo.js", function( geometry ) {
morphColorsToFaceColors( geometry );
geometry.computeVertexNormals();
var material = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0xffffff, shininess: 20, morphTargets: true, morphNormals: true, vertexColors: THREE.FaceColors, shading: THREE.SmoothShading, perPixel: false } );
var meshAnim = new THREE.MorphAnimMesh( geometry, material );
meshAnim.duration = 5000;
meshAnim.scale.set( 1.5, 1.5, 1.5 );
meshAnim.position.y = 150;
scene2.add( meshAnim );
morphs.push( meshAnim );
} );
//
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.sortObjects = false;
renderer.autoClear = false;
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
container.appendChild( renderer.domElement );
//
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.children[ 0 ].children[ 0 ].style.color = "#666";
stats.domElement.children[ 0 ].style.background = "transparent";
stats.domElement.children[ 0 ].children[ 1 ].style.display = "none";
container.appendChild( stats.domElement );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function morphColorsToFaceColors( geometry ) {
if ( geometry.morphColors && geometry.morphColors.length ) {
var colorMap = geometry.morphColors[ 0 ];
for ( var i = 0; i < colorMap.colors.length; i ++ ) {
geometry.faces[ i ].color = colorMap.colors[ i ];
THREE.ColorUtils.adjustHSV( geometry.faces[ i ].color, 0, 0.125, 0 );
}
}
}
//
function onWindowResize( event ) {
SCREEN_WIDTH = window.innerWidth;
SCREEN_HEIGHT = window.innerHeight;
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
camera.aspect = 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT;
camera.updateProjectionMatrix();
}
//
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
var radius = 600;
var theta = 0;
function render() {
theta += 0.2;
camera.position.x = radius * Math.sin( theta * Math.PI / 360 );
camera.position.z = radius * Math.cos( theta * Math.PI / 360 );
camera.lookAt( camera.target );
var delta = clock.getDelta();
for ( var i = 0; i < morphs.length; i ++ ) {
morph = morphs[ i ];
morph.updateAnimation( 1000 * delta );
}
renderer.clear();
renderer.setViewport( 0, 0, SCREEN_WIDTH/2, SCREEN_HEIGHT );
renderer.render( scene1, camera );
renderer.setViewport( SCREEN_WIDTH/2, 0, SCREEN_WIDTH/2, SCREEN_HEIGHT );
renderer.render( scene2, camera );
}
</script>
</body>
</html>
......@@ -22,6 +22,7 @@ THREE.Geometry = function () {
this.morphTargets = [];
this.morphColors = [];
this.morphNormals = [];
this.skinWeights = [];
this.skinIndices = [];
......@@ -225,6 +226,86 @@ THREE.Geometry.prototype = {
},
computeMorphNormals: function () {
var i, il, f, fl, face;
// save original vertex normals
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
face = this.faces[ f ];
face.__originalVertexNormals = [];
for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
}
}
// use temp geometry to compute face and vertex normals for each morph
var tmpGeo = new THREE.Geometry();
tmpGeo.faces = this.faces;
for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
var morphNormals = this.morphNormals[ i ];
// set vertices to morph target
tmpGeo.vertices = this.morphTargets[ i ].vertices;
// compute morph normals
tmpGeo.computeFaceNormals();
tmpGeo.computeVertexNormals();
// store morph normals
var faceNormal, vertexNormals;
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
face = this.faces[ f ];
faceNormal = morphNormals.faceNormals[ f ];
vertexNormals = morphNormals.vertexNormals[ f ];
faceNormal.copy( face.normal );
if ( face instanceof THREE.Face3 ) {
vertexNormals.a.copy( face.vertexNormals[ 0 ] );
vertexNormals.b.copy( face.vertexNormals[ 1 ] );
vertexNormals.c.copy( face.vertexNormals[ 2 ] );
} else {
vertexNormals.a.copy( face.vertexNormals[ 0 ] );
vertexNormals.b.copy( face.vertexNormals[ 1 ] );
vertexNormals.c.copy( face.vertexNormals[ 2 ] );
vertexNormals.d.copy( face.vertexNormals[ 3 ] );
}
}
}
// restore original vertex normals
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
face = this.faces[ f ];
face.vertexNormals = face.__originalVertexNormals;
}
},
computeTangents: function () {
// based on http://www.terathon.com/code/tangent.html
......
......@@ -50,7 +50,7 @@ THREE.JSONLoader.prototype.loadAjaxJSON = function( context, url, callback, text
try {
var jsonObject = JSON.parse( xhr.responseText );
var json = JSON.parse( xhr.responseText );
} catch ( error ) {
......@@ -58,7 +58,7 @@ THREE.JSONLoader.prototype.loadAjaxJSON = function( context, url, callback, text
}
context.createModel( jsonObject, callback, texturePath );
context.createModel( json, callback, texturePath );
context.onLoadComplete();
} else {
......@@ -110,6 +110,7 @@ THREE.JSONLoader.prototype.createModel = function ( json, callback, texture_path
parseMorphing( scale );
geometry.computeCentroids();
geometry.computeMorphNormals();
geometry.computeFaceNormals();
if ( this.hasNormals( geometry ) ) geometry.computeTangents();
......@@ -384,17 +385,25 @@ THREE.JSONLoader.prototype.createModel = function ( json, callback, texture_path
if ( json.morphTargets !== undefined ) {
var i, l, v, vl, x, y, z, dstVertices, srcVertices;
var i, l, v, vl, x, y, z, dstVertices, srcVertices,
f, fl, face, dstNormalsFace, dstNormalsVertex,
faceNormal, vertexNormals;
for ( i = 0, l = json.morphTargets.length; i < l; i++ ) {
for ( i = 0, l = json.morphTargets.length; i < l; i ++ ) {
geometry.morphTargets[ i ] = {};
geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
geometry.morphTargets[ i ].vertices = [];
geometry.morphNormals[ i ] = {};
geometry.morphNormals[ i ].faceNormals = [];
geometry.morphNormals[ i ].vertexNormals = [];
dstVertices = geometry.morphTargets[ i ].vertices;
srcVertices = json.morphTargets [ i ].vertices;
dstNormalsFace = geometry.morphNormals[ i ].faceNormals;
dstNormalsVertex = geometry.morphNormals[ i ].vertexNormals;
for( v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
......@@ -406,6 +415,27 @@ THREE.JSONLoader.prototype.createModel = function ( json, callback, texture_path
}
for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
face = geometry.faces[ f ];
faceNormal = new THREE.Vector3();
if ( face instanceof THREE.Face3 ) {
vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
} else {
vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3(), d: new THREE.Vector3() };
}
dstNormalsFace.push( faceNormal );
dstNormalsVertex.push( vertexNormals );
}
}
}
......
......@@ -21,7 +21,7 @@ THREE.SceneLoader.prototype.load = function( url, callbackFinished ) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
xhr.onreadystatechange = function () {
if ( xhr.readyState == 4 ) {
......@@ -31,22 +31,14 @@ THREE.SceneLoader.prototype.load = function( url, callbackFinished ) {
var json = JSON.parse( xhr.responseText );
if ( json.metadata === undefined || json.metadata.formatVersion === undefined || json.metadata.formatVersion !== 3 ) {
console.error( 'Deprecated file format.' );
return;
}
context.createScene( json, callbackFinished, url );
} catch ( error ) {
console.error( error );
console.warn( "DEPRECATED: [" + url + "] seems to be using old model format" );
}
context.createScene( json, callbackFinished, url );
} else {
console.error( "Couldn't load [" + url + "] [" + xhr.status + "]" );
......@@ -572,6 +564,9 @@ THREE.SceneLoader.prototype.createScene = function ( json, callbackFinished, url
var modelJson = data.embeds[ g.id ],
texture_path = "";
// Pass metadata along to jsonLoader so it knows the format version.
modelJson.metadata = data.metadata;
if ( modelJson ) {
......
......@@ -9,7 +9,10 @@ THREE.ShadowMapPlugin = function ( ) {
_depthMaterial, _depthMaterialMorph,
_frustum = new THREE.Frustum(),
_projScreenMatrix = new THREE.Matrix4();
_projScreenMatrix = new THREE.Matrix4(),
_min = new THREE.Vector3(),
_max = new THREE.Vector3();
this.init = function ( renderer ) {
......@@ -37,14 +40,16 @@ THREE.ShadowMapPlugin = function ( ) {
this.update = function ( scene, camera ) {
var i, il, j, jl,
var i, il, j, jl, n,
shadowMap, shadowMatrix, shadowCamera,
program, buffer, material,
webglObject, object, light,
renderList,
lights = scene.lights,
lights = [],
k = 0,
fog = null;
// set GL state for depth map
......@@ -55,14 +60,67 @@ THREE.ShadowMapPlugin = function ( ) {
_renderer.setDepthTest( true );
// preprocess lights
// - skip lights that are not casting shadows
// - create virtual lights for cascaded shadow maps
for ( i = 0, il = scene.lights.length; i < il; i ++ ) {
light = scene.lights[ i ];
if ( ! light.castShadow ) continue;
if ( ( light instanceof THREE.DirectionalLight ) && light.shadowCascade ) {
for ( n = 0; n < light.shadowCascadeCount; n ++ ) {
var virtualLight;
if ( ! light.shadowCascadeArray[ n ] ) {
virtualLight = createVirtualLight( light, n );
virtualLight.originalCamera = camera;
var gyro = new THREE.Gyroscope();
gyro.position = light.shadowCascadeOffset;
gyro.add( virtualLight );
gyro.add( virtualLight.target );
camera.add( gyro );
light.shadowCascadeArray[ n ] = virtualLight;
console.log( "Created virtualLight", virtualLight );
} else {
virtualLight = light.shadowCascadeArray[ n ];
}
updateVirtualLight( light, n );
lights[ k ] = virtualLight;
k ++;
}
} else {
lights[ k ] = light;
k ++;
}
}
// render depth map
for ( i = 0, il = lights.length; i < il; i ++ ) {
light = lights[ i ];
if ( ! light.castShadow ) continue;
if ( ! light.shadowMap ) {
var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
......@@ -97,7 +155,6 @@ THREE.ShadowMapPlugin = function ( ) {
}
if ( light.shadowCameraVisible && ! light.cameraHelper ) {
light.cameraHelper = new THREE.CameraHelper( light.shadowCamera );
......@@ -105,6 +162,12 @@ THREE.ShadowMapPlugin = function ( ) {
}
if ( light.isVirtual && virtualLight.originalCamera == camera ) {
updateShadowCamera( camera, light );
}
shadowMap = light.shadowMap;
shadowMatrix = light.shadowMatrix;
shadowCamera = light.shadowCamera;
......@@ -197,11 +260,11 @@ THREE.ShadowMapPlugin = function ( ) {
if ( buffer instanceof THREE.BufferGeometry ) {
_renderer.renderBufferDirect( shadowCamera, lights, fog, material, buffer, object );
_renderer.renderBufferDirect( shadowCamera, scene.lights, fog, material, buffer, object );
} else {
_renderer.renderBuffer( shadowCamera, lights, fog, material, buffer, object );
_renderer.renderBuffer( shadowCamera, scene.lights, fog, material, buffer, object );
}
......@@ -228,7 +291,7 @@ THREE.ShadowMapPlugin = function ( ) {
object._modelViewMatrix.multiplyToArray( shadowCamera.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
_renderer.renderImmediateObject( shadowCamera, lights, fog, _depthMaterial, object );
_renderer.renderImmediateObject( shadowCamera, scene.lights, fog, _depthMaterial, object );
}
......@@ -247,4 +310,137 @@ THREE.ShadowMapPlugin = function ( ) {
};
};
\ No newline at end of file
function createVirtualLight( light, cascade ) {
var virtualLight = new THREE.DirectionalLight();
virtualLight.isVirtual = true;
virtualLight.onlyShadow = true;
virtualLight.castShadow = true;
virtualLight.shadowCameraNear = light.shadowCameraNear;
virtualLight.shadowCameraFar = light.shadowCameraFar;
virtualLight.shadowCameraLeft = light.shadowCameraLeft;
virtualLight.shadowCameraRight = light.shadowCameraRight;
virtualLight.shadowCameraBottom = light.shadowCameraBottom;
virtualLight.shadowCameraTop = light.shadowCameraTop;
virtualLight.shadowCameraVisible = light.shadowCameraVisible;
virtualLight.shadowDarkness = light.shadowDarkness;
virtualLight.shadowBias = light.shadowCascadeBias[ cascade ];
virtualLight.shadowMapWidth = light.shadowCascadeWidth[ cascade ];
virtualLight.shadowMapHeight = light.shadowCascadeHeight[ cascade ];
virtualLight.pointsWorld = [];
virtualLight.pointsFrustum = [];
var pointsWorld = virtualLight.pointsWorld,
pointsFrustum = virtualLight.pointsFrustum;
for ( var i = 0; i < 8; i ++ ) {
pointsWorld[ i ] = new THREE.Vector3();
pointsFrustum[ i ] = new THREE.Vector3();
}
var nearZ = light.shadowCascadeNearZ[ cascade ];
var farZ = light.shadowCascadeFarZ[ cascade ];
pointsFrustum[ 0 ].set( -1, -1, nearZ );
pointsFrustum[ 1 ].set( 1, -1, nearZ );
pointsFrustum[ 2 ].set( -1, 1, nearZ );
pointsFrustum[ 3 ].set( 1, 1, nearZ );
pointsFrustum[ 4 ].set( -1, -1, farZ );
pointsFrustum[ 5 ].set( 1, -1, farZ );
pointsFrustum[ 6 ].set( -1, 1, farZ );
pointsFrustum[ 7 ].set( 1, 1, farZ );
return virtualLight;
}
// Synchronize virtual light with the original light
function updateVirtualLight( light, cascade ) {
var virtualLight = light.shadowCascadeArray[ cascade ];
virtualLight.position.copy( light.position );
virtualLight.target.position.copy( light.target.position );
virtualLight.lookAt( virtualLight.target );
virtualLight.shadowCameraVisible = light.shadowCameraVisible;
virtualLight.shadowDarkness = light.shadowDarkness;
virtualLight.shadowBias = light.shadowCascadeBias[ cascade ];
var nearZ = light.shadowCascadeNearZ[ cascade ];
var farZ = light.shadowCascadeFarZ[ cascade ];
var pointsFrustum = virtualLight.pointsFrustum;
pointsFrustum[ 0 ].z = nearZ;
pointsFrustum[ 1 ].z = nearZ;
pointsFrustum[ 2 ].z = nearZ;
pointsFrustum[ 3 ].z = nearZ;
pointsFrustum[ 4 ].z = farZ;
pointsFrustum[ 5 ].z = farZ;
pointsFrustum[ 6 ].z = farZ;
pointsFrustum[ 7 ].z = farZ;
}
// Fit shadow camera's ortho frustum to camera frustum
function updateShadowCamera( camera, light ) {
var shadowCamera = light.shadowCamera,
pointsFrustum = light.pointsFrustum,
pointsWorld = light.pointsWorld;
_min.set( Infinity, Infinity, Infinity );
_max.set( -Infinity, -Infinity, -Infinity );
for ( var i = 0; i < 8; i ++ ) {
var p = pointsWorld[ i ];
p.copy( pointsFrustum[ i ] );
THREE.ShadowMapPlugin.__projector.unprojectVector( p, camera );
shadowCamera.matrixWorldInverse.multiplyVector3( p );
if ( p.x < _min.x ) _min.x = p.x;
if ( p.x > _max.x ) _max.x = p.x;
if ( p.y < _min.y ) _min.y = p.y;
if ( p.y > _max.y ) _max.y = p.y;
if ( p.z < _min.z ) _min.z = p.z;
if ( p.z > _max.z ) _max.z = p.z;
}
shadowCamera.left = _min.x;
shadowCamera.right = _max.x;
shadowCamera.top = _max.y;
shadowCamera.bottom = _min.y;
// can't really fit near/far
//shadowCamera.near = _min.z;
//shadowCamera.far = _max.z;
shadowCamera.updateProjectionMatrix();
}
};
THREE.ShadowMapPlugin.__projector = new THREE.Projector();
\ No newline at end of file
......@@ -36,6 +36,22 @@ THREE.DirectionalLight = function ( hex, intensity, distance ) {
//
this.shadowCascade = false;
this.shadowCascadeOffset = new THREE.Vector3( 0, 0, -1000 );
this.shadowCascadeCount = 2;
this.shadowCascadeBias = [];
this.shadowCascadeWidth = [];
this.shadowCascadeHeight = [];
this.shadowCascadeNearZ = [ -1.000, 0.990, 0.998 ];
this.shadowCascadeFarZ = [ 0.990, 0.998, 1.000 ];
this.shadowCascadeArray = [];
//
this.shadowMap = null;
this.shadowMapSize = null;
this.shadowCamera = null;
......
......@@ -64,6 +64,7 @@ THREE.MeshLambertMaterial = function ( parameters ) {
this.skinning = parameters.skinning !== undefined ? parameters.skinning : false;
this.morphTargets = parameters.morphTargets !== undefined ? parameters.morphTargets : false;
this.morphNormals = parameters.morphNormals !== undefined ? parameters.morphNormals : false;
};
......
......@@ -71,6 +71,7 @@ THREE.MeshPhongMaterial = function ( parameters ) {
this.skinning = parameters.skinning !== undefined ? parameters.skinning : false;
this.morphTargets = parameters.morphTargets !== undefined ? parameters.morphTargets : false;
this.morphNormals = parameters.morphNormals !== undefined ? parameters.morphNormals : false;
};
......
......@@ -57,10 +57,13 @@ THREE.WebGLRenderer = function ( parameters ) {
this.shadowMapAutoUpdate = true;
this.shadowMapSoft = true;
this.shadowMapCullFrontFaces = true;
this.shadowMapDebug = false;
this.shadowMapCascade = false;
// morphs
this.maxMorphTargets = 8;
this.maxMorphNormals = 4;
// flags
......@@ -397,10 +400,12 @@ THREE.WebGLRenderer = function ( parameters ) {
var m, ml;
geometryGroup.__webglMorphTargetsBuffers = [];
geometryGroup.__webglMorphNormalsBuffers = [];
for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
geometryGroup.__webglMorphTargetsBuffers.push( _gl.createBuffer() );
geometryGroup.__webglMorphNormalsBuffers.push( _gl.createBuffer() );
}
......@@ -461,6 +466,7 @@ THREE.WebGLRenderer = function ( parameters ) {
for ( var m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
_gl.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] );
_gl.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] );
}
......@@ -639,10 +645,12 @@ THREE.WebGLRenderer = function ( parameters ) {
if ( geometryGroup.numMorphTargets ) {
geometryGroup.__morphTargetsArrays = [];
geometryGroup.__morphNormalsArrays = [];
for ( var m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) );
geometryGroup.__morphNormalsArrays.push( new Float32Array( nvertices * 3 ) );
}
......@@ -1329,7 +1337,7 @@ THREE.WebGLRenderer = function ( parameters ) {
vertexNormals, faceNormal, normal,
vertexColors, faceColor,
vertexTangents,
uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4,
uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, n1, n2, n3, n4,
c1, c2, c3, c4,
sw1, sw2, sw3, sw4,
si1, si2, si3, si4,
......@@ -1338,6 +1346,7 @@ THREE.WebGLRenderer = function ( parameters ) {
m, ml, i, il,
vn, uvi, uv2i,
vk, vkl, vka,
nka, chf, faceVertexNormals,
a,
vertexIndex = 0,
......@@ -1370,6 +1379,7 @@ THREE.WebGLRenderer = function ( parameters ) {
skinWeightArray = geometryGroup.__skinWeightArray,
morphTargetsArrays = geometryGroup.__morphTargetsArrays,
morphNormalsArrays = geometryGroup.__morphNormalsArrays,
customAttributes = geometryGroup.__webglCustomAttributesList,
customAttribute,
......@@ -1402,7 +1412,8 @@ THREE.WebGLRenderer = function ( parameters ) {
obj_skinIndices = geometry.skinIndices,
obj_skinWeights = geometry.skinWeights,
morphTargets = geometry.morphTargets;
morphTargets = geometry.morphTargets,
morphNormals = geometry.morphNormals;
if ( dirtyVertices ) {
......@@ -1472,7 +1483,10 @@ THREE.WebGLRenderer = function ( parameters ) {
for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
face = obj_faces[ chunk_faces3[ f ] ];
chf = chunk_faces3[ f ];
face = obj_faces[ chf ];
// morph positions
v1 = morphTargets[ vk ].vertices[ face.a ].position;
v2 = morphTargets[ vk ].vertices[ face.b ].position;
......@@ -1492,13 +1506,54 @@ THREE.WebGLRenderer = function ( parameters ) {
vka[ offset_morphTarget + 7 ] = v3.y;
vka[ offset_morphTarget + 8 ] = v3.z;
// morph normals
if ( material.morphNormals ) {
if ( needsSmoothNormals ) {
faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
n1 = faceVertexNormals.a;
n2 = faceVertexNormals.b;
n3 = faceVertexNormals.c;
} else {
n1 = morphNormals[ vk ].faceNormals[ chf ];
n2 = n1;
n3 = n1;
}
nka = morphNormalsArrays[ vk ];
nka[ offset_morphTarget ] = n1.x;
nka[ offset_morphTarget + 1 ] = n1.y;
nka[ offset_morphTarget + 2 ] = n1.z;
nka[ offset_morphTarget + 3 ] = n2.x;
nka[ offset_morphTarget + 4 ] = n2.y;
nka[ offset_morphTarget + 5 ] = n2.z;
nka[ offset_morphTarget + 6 ] = n3.x;
nka[ offset_morphTarget + 7 ] = n3.y;
nka[ offset_morphTarget + 8 ] = n3.z;
}
//
offset_morphTarget += 9;
}
for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
face = obj_faces[ chunk_faces4[ f ] ];
chf = chunk_faces4[ f ];
face = obj_faces[ chf ];
// morph positions
v1 = morphTargets[ vk ].vertices[ face.a ].position;
v2 = morphTargets[ vk ].vertices[ face.b ].position;
......@@ -1523,6 +1578,50 @@ THREE.WebGLRenderer = function ( parameters ) {
vka[ offset_morphTarget + 10 ] = v4.y;
vka[ offset_morphTarget + 11 ] = v4.z;
// morph normals
if ( material.morphNormals ) {
if ( needsSmoothNormals ) {
faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
n1 = faceVertexNormals.a;
n2 = faceVertexNormals.b;
n3 = faceVertexNormals.c;
n4 = faceVertexNormals.d;
} else {
n1 = morphNormals[ vk ].faceNormals[ chf ];
n2 = n1;
n3 = n1;
n4 = n1;
}
nka = morphNormalsArrays[ vk ];
nka[ offset_morphTarget ] = n1.x;
nka[ offset_morphTarget + 1 ] = n1.y;
nka[ offset_morphTarget + 2 ] = n1.z;
nka[ offset_morphTarget + 3 ] = n2.x;
nka[ offset_morphTarget + 4 ] = n2.y;
nka[ offset_morphTarget + 5 ] = n2.z;
nka[ offset_morphTarget + 6 ] = n3.x;
nka[ offset_morphTarget + 7 ] = n3.y;
nka[ offset_morphTarget + 8 ] = n3.z;
nka[ offset_morphTarget + 9 ] = n4.x;
nka[ offset_morphTarget + 10 ] = n4.y;
nka[ offset_morphTarget + 11 ] = n4.z;
}
//
offset_morphTarget += 12;
}
......@@ -1530,6 +1629,13 @@ THREE.WebGLRenderer = function ( parameters ) {
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ vk ] );
_gl.bufferData( _gl.ARRAY_BUFFER, morphTargetsArrays[ vk ], hint );
if ( material.morphNormals ) {
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ vk ] );
_gl.bufferData( _gl.ARRAY_BUFFER, morphNormalsArrays[ vk ], hint );
}
}
}
......@@ -3041,6 +3147,13 @@ THREE.WebGLRenderer = function ( parameters ) {
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ order[ m ] ] );
_gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
if ( material.morphNormals ) {
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ order[ m ] ] );
_gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
}
object.__webglMorphTargetInfluences[ m ] = influences[ order[ m ] ];
m ++;
......@@ -3079,6 +3192,13 @@ THREE.WebGLRenderer = function ( parameters ) {
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ candidate ] );
_gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
if ( material.morphNormals ) {
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ candidate ] );
_gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
}
object.__webglMorphTargetInfluences[ m ] = candidateInfluence;
used[ candidate ] = 1;
......@@ -4044,11 +4164,15 @@ THREE.WebGLRenderer = function ( parameters ) {
sizeAttenuation: material.sizeAttenuation,
skinning: material.skinning,
morphTargets: material.morphTargets,
morphNormals: material.morphNormals,
maxMorphTargets: this.maxMorphTargets,
maxMorphNormals: this.maxMorphNormals,
maxDirLights: maxLightCount.directional, maxPointLights: maxLightCount.point,
maxBones: maxBones,
shadowMapEnabled: this.shadowMapEnabled && object.receiveShadow,
shadowMapSoft: this.shadowMapSoft,
shadowMapDebug: this.shadowMapDebug,
shadowMapCascade: this.shadowMapCascade,
maxShadows: maxShadows,
alphaTest: material.alphaTest,
metal: material.metal,
......@@ -4108,6 +4232,27 @@ THREE.WebGLRenderer = function ( parameters ) {
}
if ( material.morphNormals ) {
material.numSupportedMorphNormals = 0;
var id, base = "morphNormal";
for ( i = 0; i < this.maxMorphNormals; i ++ ) {
id = base + i;
if ( attributes[ id ] >= 0 ) {
_gl.enableVertexAttribArray( attributes[ id ] );
material.numSupportedMorphNormals ++;
}
}
}
material.uniformsList = [];
for ( u in material.uniforms ) {
......@@ -4453,7 +4598,7 @@ THREE.WebGLRenderer = function ( parameters ) {
if ( ! light.castShadow ) continue;
if ( light instanceof THREE.SpotLight || light instanceof THREE.DirectionalLight ) {
if ( light instanceof THREE.SpotLight || ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) ) {
uniforms.shadowMap.texture[ j ] = light.shadowMap;
uniforms.shadowMapSize.value[ j ] = light.shadowMapSize;
......@@ -5105,11 +5250,14 @@ THREE.WebGLRenderer = function ( parameters ) {
parameters.vertexColors ? "#define USE_COLOR" : "",
parameters.skinning ? "#define USE_SKINNING" : "",
parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
parameters.morphNormals ? "#define USE_MORPHNORMALS" : "",
parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
parameters.wrapAround ? "#define WRAP_AROUND" : "",
parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",
......@@ -5137,10 +5285,22 @@ THREE.WebGLRenderer = function ( parameters ) {
"attribute vec3 morphTarget1;",
"attribute vec3 morphTarget2;",
"attribute vec3 morphTarget3;",
"attribute vec3 morphTarget4;",
"attribute vec3 morphTarget5;",
"attribute vec3 morphTarget6;",
"attribute vec3 morphTarget7;",
"#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",
......@@ -5186,6 +5346,8 @@ THREE.WebGLRenderer = function ( parameters ) {
parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
"uniform mat4 viewMatrix;",
"uniform vec3 cameraPosition;",
......@@ -5244,6 +5406,12 @@ THREE.WebGLRenderer = function ( parameters ) {
}
for ( i = 0; i < parameters.maxMorphNormals; i ++ ) {
identifiers.push( "morphNormal" + i );
}
for ( a in attributes ) {
identifiers.push( a );
......@@ -5788,7 +5956,8 @@ THREE.WebGLRenderer = function ( parameters ) {
if ( ! light.castShadow ) continue;
if ( light instanceof THREE.SpotLight || light instanceof THREE.DirectionalLight ) maxShadows ++;
if ( light instanceof THREE.SpotLight ) maxShadows ++;
if ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) maxShadows ++;
}
......
......@@ -287,6 +287,8 @@ THREE.ShaderChunk = {
"vLightWeighting = vec3( 0.0 );",
"transformedNormal = normalize( transformedNormal );",
"#if MAX_DIR_LIGHTS > 0",
"for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
......@@ -681,8 +683,16 @@ THREE.ShaderChunk = {
"#ifdef USE_MORPHTARGETS",
"#ifndef USE_MORPHNORMALS",
"uniform float morphTargetInfluences[ 8 ];",
"#else",
"uniform float morphTargetInfluences[ 4 ];",
"#endif",
"#endif"
].join("\n"),
......@@ -691,15 +701,21 @@ THREE.ShaderChunk = {
"#ifdef USE_MORPHTARGETS",
"vec3 morphed = vec3( 0.0, 0.0, 0.0 );",
"vec3 morphed = vec3( 0.0 );",
"morphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];",
"morphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];",
"morphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];",
"morphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];",
"#ifndef USE_MORPHNORMALS",
"morphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];",
"morphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];",
"morphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];",
"morphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];",
"#endif",
"morphed += position;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );",
......@@ -720,6 +736,29 @@ THREE.ShaderChunk = {
].join("\n"),
morphnormal_vertex: [
"#ifdef USE_MORPHNORMALS",
"vec3 morphedNormal = vec3( 0.0 );",
"morphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];",
"morphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];",
"morphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];",
"morphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];",
"morphedNormal += normal;",
"vec3 transformedNormal = normalMatrix * morphedNormal;",
"#else",
"vec3 transformedNormal = normalMatrix * normal;",
"#endif"
].join("\n"),
// SHADOW MAP
// based on SpiderGL shadow map and Fabien Sanglard's GLSL shadow mapping examples
......@@ -754,123 +793,158 @@ THREE.ShaderChunk = {
"#ifdef USE_SHADOWMAP",
"vec3 shadowColor = vec3( 1.0 );",
"#ifdef SHADOWMAP_DEBUG",
"vec3 frustumColors[3];",
"frustumColors[0] = vec3( 1.0, 0.5, 0.0 );",
"frustumColors[1] = vec3( 0.0, 1.0, 0.8 );",
"frustumColors[2] = vec3( 0.0, 0.5, 1.0 );",
"#endif",
"#ifdef SHADOWMAP_CASCADE",
"int inFrustumCount = 0;",
"#endif",
"float fDepth;",
"vec3 shadowColor = vec3( 1.0 );",
"for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
"vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;",
// "if ( something && something )" breaks ATI OpenGL shader compiler
// "if ( all( something, something ) )" using this instead
"bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );",
"bool inFrustum = all( inFrustumVec );",
// don't shadow pixels outside of light frustum
// use just first frustum (for cascades)
// don't shadow pixels behind far plane of light frustum
"if ( shadowCoord.z <= 1.0 ) {",
"#ifdef SHADOWMAP_CASCADE",
"shadowCoord.z += shadowBias[ i ];",
"inFrustumCount += int( inFrustum );",
"bvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );",
// using "if ( all )" for ATI OpenGL shader compiler
// "if ( something && something )" breaks it
"#else",
"bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );",
// don't shadow pixels outside of light frustum
"#endif",
"bvec4 shadowTest = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );",
"bool frustumTest = all( frustumTestVec );",
"if ( all( shadowTest ) ) {",
"if ( frustumTest ) {",
"#ifdef SHADOWMAP_SOFT",
"shadowCoord.z += shadowBias[ i ];",
// Percentage-close filtering
// (9 pixel kernel)
// http://fabiensanglard.net/shadowmappingPCF/
"#ifdef SHADOWMAP_SOFT",
"float shadow = 0.0;",
// Percentage-close filtering
// (9 pixel kernel)
// http://fabiensanglard.net/shadowmappingPCF/
/*
// this breaks shader compiler / validator on some ATI cards when using OpenGL
// must enroll loop manually
"float shadow = 0.0;",
"for ( float y = -1.25; y <= 1.25; y += 1.25 )",
"for ( float x = -1.25; x <= 1.25; x += 1.25 ) {",
/*
// nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
// must enroll loop manually
"vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );",
"for ( float y = -1.25; y <= 1.25; y += 1.25 )",
"for ( float x = -1.25; x <= 1.25; x += 1.25 ) {",
// doesn't seem to produce any noticeable visual difference compared to simple "texture2D" lookup
//"vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );",
"vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );",
"float fDepth = unpackDepth( rgbaDepth );",
// doesn't seem to produce any noticeable visual difference compared to simple "texture2D" lookup
//"vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );",
"if ( fDepth < shadowCoord.z )",
"shadow += 1.0;",
"float fDepth = unpackDepth( rgbaDepth );",
"}",
"if ( fDepth < shadowCoord.z )",
"shadow += 1.0;",
"shadow /= 9.0;",
"}",
*/
"shadow /= 9.0;",
"const float shadowDelta = 1.0 / 9.0;",
*/
"float xPixelOffset = 1.0 / shadowMapSize[ i ].x;",
"float yPixelOffset = 1.0 / shadowMapSize[ i ].y;",
"const float shadowDelta = 1.0 / 9.0;",
"float dx0 = -1.25 * xPixelOffset;",
"float dy0 = -1.25 * yPixelOffset;",
"float dx1 = 1.25 * xPixelOffset;",
"float dy1 = 1.25 * yPixelOffset;",
"float xPixelOffset = 1.0 / shadowMapSize[ i ].x;",
"float yPixelOffset = 1.0 / shadowMapSize[ i ].y;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"float dx0 = -1.25 * xPixelOffset;",
"float dy0 = -1.25 * yPixelOffset;",
"float dx1 = 1.25 * xPixelOffset;",
"float dy1 = 1.25 * yPixelOffset;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );",
"fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );",
"if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
"#else",
"shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );",
"vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );",
"float fDepth = unpackDepth( rgbaDepth );",
"#else",
"if ( fDepth < shadowCoord.z )",
"vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );",
"float fDepth = unpackDepth( rgbaDepth );",
// spot with multiple shadows is darker
"if ( fDepth < shadowCoord.z )",
"shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );",
// spot with multiple shadows is darker
// spot with multiple shadows has the same color as single shadow spot
"shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );",
//"shadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );",
// spot with multiple shadows has the same color as single shadow spot
"#endif",
//"shadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );",
"}",
"#endif",
"}",
// uncomment to see light frustum boundaries
//"if ( !( shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0 ) )",
// "gl_FragColor.xyz = gl_FragColor.xyz * vec3( 1.0, 0.0, 0.0 );",
"#ifdef SHADOWMAP_DEBUG",
"#ifdef SHADOWMAP_CASCADE",
"if ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];",
"#else",
"if ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];",
"#endif",
"#endif",
"}",
......@@ -1267,7 +1341,7 @@ THREE.ShaderLib = {
THREE.ShaderChunk[ "envmap_vertex" ],
THREE.ShaderChunk[ "color_vertex" ],
"vec3 transformedNormal = normalize( normalMatrix * normal );",
THREE.ShaderChunk[ "morphnormal_vertex" ],
THREE.ShaderChunk[ "lights_lambert_vertex" ],
THREE.ShaderChunk[ "skinning_vertex" ],
......@@ -1366,7 +1440,8 @@ THREE.ShaderLib = {
"vViewPosition = -mvPosition.xyz;",
"vec3 transformedNormal = normalMatrix * normal;",
THREE.ShaderChunk[ "morphnormal_vertex" ],
"vNormal = transformedNormal;",
THREE.ShaderChunk[ "lights_phong_vertex" ],
......
......@@ -362,6 +362,7 @@ WEBGL_FILES = [
'renderers/renderables/RenderableParticle.js',
'renderers/renderables/RenderableLine.js',
'extras/core/BufferGeometry.js',
'extras/core/Gyroscope.js',
'extras/helpers/CameraHelper.js',
'extras/objects/LensFlare.js',
'extras/objects/MarchingCubes.js',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册