提交 a7eed9d6 编写于 作者: M mkkellogg

Updated cubeToUV() to a reduced-instruction version with minimal branching,...

Updated cubeToUV() to a reduced-instruction version with minimal branching, and updated near plane values for shadow map cameras to be at least 1.
上级 4f4fdc11
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - Omni-directional Shadow map viewer example </title>
<meta charset="utf-8">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 100;
display:block;
}
#info a { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
</style>
</head>
<body>
<div id="info">
<a href="http://threejs.org" target="_blank">three.js</a> - Omni-directional Shadow map viewer example by <a href="https://github.com/mkkellogg">mkkellogg</a>
</div>
<script src="../build/three.min.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var camera, scene, renderer, clock, stats;
var dirLight, pointLight;
var pointLightParent;
var torusKnot, cube, cube2, cube3, cube4;
var cubeMaterial;
var wallMaterial;
var ground;
init();
animate();
function init() {
initScene();
initMisc();
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function initScene() {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.01, 1000 );
camera.position.set( 0, 15, 35 );
scene = new THREE.Scene();
// Lights
var ambient = new THREE.AmbientLight( 0x404040 );
scene.add( ambient );
pointLight = new THREE.PointLight( 0xffffff );
pointLight.position.set( 0, 11, 4 );
pointLight.castShadow = true;
pointLight.shadowCameraNear = 1;
pointLight.shadowCameraFar = 30;
pointLight.shadowDarkness = 0.5;
pointLight.shadowCameraVisible = true;
pointLight.shadowMapWidth = 2048;
pointLight.shadowMapHeight = 1024;
pointLight.name = 'Point Light';
scene.add( pointLight );
/*dirLight = new THREE.DirectionalLight( 0xffffff, 1 );
dirLight.position.set( 0, 50, 0 );
dirLight.castShadow = true;
dirLight.shadowCameraNear = 0.01;
dirLight.shadowCameraFar = 100;
dirLight.shadowCameraRight = 15;
dirLight.shadowCameraLeft = -15;
dirLight.shadowCameraTop = 15;
dirLight.shadowCameraBottom = -15;
dirLight.shadowDarkness = 0.5;
dirLight.shadowCameraVisible = true;
dirLight.shadowMapWidth = 1024;
dirLight.shadowMapHeight = 1024;
dirLight.name = 'Dir. Light';
scene.add( dirLight );*/
cubeMaterial = new THREE.MeshPhongMaterial( {
color: 0xff0000,
shininess: 150,
specular: 0x222222,
shading: THREE.SmoothShading,
} );
var cubeGeometry = new THREE.BoxGeometry( 3, 3, 3 );
cube = new THREE.Mesh( cubeGeometry, cubeMaterial );
cube.name = "cube 1";
cube.position.set( 8, 3, 6 );
cube.castShadow = true;
cube.receiveShadow = true;
scene.add( cube );
cube2 = new THREE.Mesh( cubeGeometry, cubeMaterial );
cube2.name = "cube 2";
cube2.position.set( -8, 3, 4 );
cube2.castShadow = true;
cube2.receiveShadow = true;
scene.add( cube2 );
cube3 = new THREE.Mesh( cubeGeometry, cubeMaterial );
cube3.name = "cube 3";
cube3.position.set( -4, 15, -6 );
cube3.castShadow = true;
cube3.receiveShadow = true;
scene.add( cube3 );
var torusGeometry = new THREE.TorusKnotGeometry( 25, 8, 75, 20 );
torusKnot = new THREE.Mesh( torusGeometry, cubeMaterial );
torusKnot.scale.multiplyScalar( 1 / 18 );
torusKnot.position.set( -1, 3, -4 );
torusKnot.castShadow = true;
torusKnot.receiveShadow = true;
scene.add( torusKnot );
wallMaterial = new THREE.MeshPhongMaterial( {
color: 0xa0adaf,
shininess: 10,
specular: 0x111111,
shading: THREE.SmoothShading
} );
var wallGeometry = new THREE.BoxGeometry( 10, 0.15, 10 );
ground = new THREE.Mesh( wallGeometry, wallMaterial );
ground.name = "ground";
ground.scale.multiplyScalar( 3 );
ground.castShadow = false;
ground.receiveShadow = true;
scene.add( ground );
ground.position.set( 0, -5, 0 );
var ceiling = new THREE.Mesh( wallGeometry, wallMaterial );
ceiling.name = "ceiling";
ceiling.scale.multiplyScalar( 3 );
ceiling.castShadow = false;
ceiling.receiveShadow = true;
scene.add( ceiling );
ceiling.position.set( 0, 24, 0 );
var wall = new THREE.Mesh( wallGeometry, wallMaterial );
wall.name = "left wall";
wall.scale.multiplyScalar( 3 );
wall.castShadow = false;
wall.receiveShadow = true;
scene.add( wall );
wall.position.set( -14, 10, 0 );
wall.rotation.z = Math.PI / 2;
wall = new THREE.Mesh( wallGeometry, wallMaterial );
wall.name = "right wall";
wall.scale.multiplyScalar( 3 );
wall.castShadow = false;
wall.receiveShadow = true;
scene.add( wall );
wall.position.set(14,10,0);
wall.rotation.z = Math.PI / 2;
wall = new THREE.Mesh( wallGeometry, wallMaterial );
wall.name = "back wall";
wall.scale.multiplyScalar( 3 );
wall.castShadow = false;
wall.receiveShadow = true;
scene.add( wall );
wall.position.set( 0, 10, -14 );
wall.rotation.y = Math.PI / 2;
wall.rotation.z = Math.PI / 2;
/*wall = new THREE.Mesh( wallGeometry, wallMaterial );
wall.name = "front wall";
wall.scale.multiplyScalar( 3 );
wall.castShadow = false;
wall.receiveShadow = true;
scene.add( wall );
wall.position.set( 0, 10, 14 );
wall.rotation.y = Math.PI / 2;
wall.rotation.z = Math.PI / 2;*/
var sphereGeometry = new THREE.SphereGeometry( 1, 32, 32 );
var material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
var sphere = new THREE.Mesh( sphereGeometry, material );
sphere.castShadow = false;
sphere.receiveShadow = false;
sphere.position.set( 0, 11, 4 );
scene.add( sphere );
pointLightParent = new THREE.Object3D();
pointLightParent.add( pointLight );
pointLightParent.add( sphere );
scene.add( pointLightParent );
}
function initMisc() {
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x000000 );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
// Mouse control
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.target.set( 0, 2, 0 );
controls.update();
clock = new THREE.Clock();
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.right = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild( stats.domElement );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function renderScene() {
renderer.render( scene, camera );
}
function render() {
var delta = clock.getDelta();
pointLightParent.rotation.y += delta * 2;
renderScene();
cube.rotation.x += 0.25 * delta;
cube.rotation.y += 2 * delta;
cube.rotation.z += 1 * delta;
cube2.rotation.x += 0.25 * delta;
cube2.rotation.y += 2 * delta;
cube2.rotation.z += 1 * delta;
cube3.rotation.x += 0.25 * delta;
cube3.rotation.y += 2 * delta;
cube3.rotation.z += 1 * delta;
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - Omni-directional Shadow map viewer example </title>
<meta charset="utf-8">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 100;
display:block;
}
#info a { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
</style>
</head>
<body>
<div id="info">
<a href="http://threejs.org" target="_blank">three.js</a> - Omni-directional Shadow map viewer example by <a href="https://github.com/mkkellogg">mkkellogg</a>
</div>
<script src="../build/three.min.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var camera, scene, renderer, clock, stats;
var dirLight, pointLight;
var pointLightParent;
var torusKnot, cube, cube2, cube3, cube4;
var cubeMaterial;
var wallMaterial;
var ground;
init();
animate();
function init() {
initScene();
initMisc();
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function initScene() {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 15, 35 );
scene = new THREE.Scene();
// Lights
var ambient = new THREE.AmbientLight( 0x404040 );
scene.add( ambient );
pointLight = new THREE.PointLight( 0xffffff );
pointLight.position.set( 0, 11, 4 );
pointLight.castShadow = true;
pointLight.shadowCameraNear = 1;
pointLight.shadowCameraFar = 30;
pointLight.shadowDarkness = 0.5;
pointLight.shadowCameraVisible = true;
pointLight.shadowMapWidth = 2048;
pointLight.shadowMapHeight = 1024;
pointLight.shadowBias = 0.1;
pointLight.name = 'Point Light';
scene.add( pointLight );
/*dirLight = new THREE.DirectionalLight( 0xffffff, 1 );
dirLight.position.set( 0, 50, 0 );
dirLight.castShadow = true;
dirLight.shadowCameraNear = 1;
dirLight.shadowCameraFar = 100;
dirLight.shadowCameraRight = 15;
dirLight.shadowCameraLeft = -15;
dirLight.shadowCameraTop = 15;
dirLight.shadowCameraBottom = -15;
dirLight.shadowDarkness = 0.5;
dirLight.shadowCameraVisible = true;
dirLight.shadowMapWidth = 1024;
dirLight.shadowMapHeight = 1024;
dirLight.name = 'Dir. Light';
scene.add( dirLight );*/
cubeMaterial = new THREE.MeshPhongMaterial( {
color: 0xff0000,
shininess: 150,
specular: 0x222222,
shading: THREE.SmoothShading,
} );
var cubeGeometry = new THREE.BoxGeometry( 3, 3, 3 );
cube = new THREE.Mesh( cubeGeometry, cubeMaterial );
cube.name = "cube 1";
cube.position.set( 8, 3, 6 );
cube.castShadow = true;
cube.receiveShadow = true;
scene.add( cube );
cube2 = new THREE.Mesh( cubeGeometry, cubeMaterial );
cube2.name = "cube 2";
cube2.position.set( -8, 3, 4 );
cube2.castShadow = true;
cube2.receiveShadow = true;
scene.add( cube2 );
cube3 = new THREE.Mesh( cubeGeometry, cubeMaterial );
cube3.name = "cube 3";
cube3.position.set( -4, 15, -6 );
cube3.castShadow = true;
cube3.receiveShadow = true;
scene.add( cube3 );
var torusGeometry = new THREE.TorusKnotGeometry( 25, 8, 75, 20 );
torusKnot = new THREE.Mesh( torusGeometry, cubeMaterial );
torusKnot.scale.multiplyScalar( 1 / 18 );
torusKnot.position.set( -1, 3, -4 );
torusKnot.castShadow = true;
torusKnot.receiveShadow = true;
scene.add( torusKnot );
wallMaterial = new THREE.MeshPhongMaterial( {
color: 0xa0adaf,
shininess: 10,
specular: 0x111111,
shading: THREE.SmoothShading
} );
var wallGeometry = new THREE.BoxGeometry( 10, 0.15, 10 );
ground = new THREE.Mesh( wallGeometry, wallMaterial );
ground.name = "ground";
ground.scale.multiplyScalar( 3 );
ground.castShadow = false;
ground.receiveShadow = true;
scene.add( ground );
ground.position.set( 0, -5, 0 );
var ceiling = new THREE.Mesh( wallGeometry, wallMaterial );
ceiling.name = "ceiling";
ceiling.scale.multiplyScalar( 3 );
ceiling.castShadow = false;
ceiling.receiveShadow = true;
scene.add( ceiling );
ceiling.position.set( 0, 24, 0 );
var wall = new THREE.Mesh( wallGeometry, wallMaterial );
wall.name = "left wall";
wall.scale.multiplyScalar( 3 );
wall.castShadow = false;
wall.receiveShadow = true;
scene.add( wall );
wall.position.set( -14, 10, 0 );
wall.rotation.z = Math.PI / 2;
wall = new THREE.Mesh( wallGeometry, wallMaterial );
wall.name = "right wall";
wall.scale.multiplyScalar( 3 );
wall.castShadow = false;
wall.receiveShadow = true;
scene.add( wall );
wall.position.set(14,10,0);
wall.rotation.z = Math.PI / 2;
wall = new THREE.Mesh( wallGeometry, wallMaterial );
wall.name = "back wall";
wall.scale.multiplyScalar( 3 );
wall.castShadow = false;
wall.receiveShadow = true;
scene.add( wall );
wall.position.set( 0, 10, -14 );
wall.rotation.y = Math.PI / 2;
wall.rotation.z = Math.PI / 2;
/*wall = new THREE.Mesh( wallGeometry, wallMaterial );
wall.name = "front wall";
wall.scale.multiplyScalar( 3 );
wall.castShadow = false;
wall.receiveShadow = true;
scene.add( wall );
wall.position.set( 0, 10, 14 );
wall.rotation.y = Math.PI / 2;
wall.rotation.z = Math.PI / 2;*/
var sphereGeometry = new THREE.SphereGeometry( 1, 32, 32 );
var material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
var sphere = new THREE.Mesh( sphereGeometry, material );
sphere.castShadow = false;
sphere.receiveShadow = false;
sphere.position.set( 0, 11, 4 );
scene.add( sphere );
pointLightParent = new THREE.Object3D();
pointLightParent.add( pointLight );
pointLightParent.add( sphere );
scene.add( pointLightParent );
}
function initMisc() {
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x000000 );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.BasicShadowMap;
// Mouse control
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.target.set( 0, 2, 0 );
controls.update();
clock = new THREE.Clock();
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.right = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild( stats.domElement );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function renderScene() {
renderer.render( scene, camera );
}
function render() {
var delta = clock.getDelta();
pointLightParent.rotation.y += delta * 2;
renderScene();
cube.rotation.x += 0.25 * delta;
cube.rotation.y += 2 * delta;
cube.rotation.z += 1 * delta;
cube2.rotation.x += 0.25 * delta;
cube2.rotation.y += 2 * delta;
cube2.rotation.z += 1 * delta;
cube3.rotation.x += 0.25 * delta;
cube3.rotation.y += 2 * delta;
cube3.rotation.z += 1 * delta;
}
</script>
</body>
</html>
......@@ -65,7 +65,7 @@
function initScene() {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.01, 1000 );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 15, 35 );
scene = new THREE.Scene();
......@@ -89,7 +89,7 @@
dirLight = new THREE.DirectionalLight( 0xffffff, 1 );
dirLight.position.set( 0, 10, 0 );
dirLight.castShadow = true;
dirLight.shadowCameraNear = 0.01;
dirLight.shadowCameraNear = 1;
dirLight.shadowCameraFar = 10;
dirLight.shadowCameraRight = 15;
dirLight.shadowCameraLeft = -15;
......
......@@ -18,8 +18,8 @@ THREE.PointLight = function ( color, intensity, distance, decay ) {
//
this.shadowCameraNear = 0;
this.shadowCameraFar = 5000;
this.shadowCameraNear = 1;
this.shadowCameraFar = 500;
this.shadowCameraFov = 90;
this.shadowCameraVisible = false;
......
......@@ -28,10 +28,10 @@
/**
* cubeToUV() maps a 3D direction vector suitable for cube texture mapping to a 2D
* vector suitable for 2D texture mapping. This code uses the following layout for the
* 2D texture:
*
* Y y
* 2D texture:
*
* xzXZ
* y Y
*
* Y - Positive y direction
* y - Negative y direction
......@@ -40,73 +40,61 @@
* Z - Positive z direction
* z - Negative z direction
*
* Alternate code for different layouts, more compact code arrangement, and seam
* skipping can be found here: https://gist.github.com/tschw/da10c43c467ce8afd0c4
* Alternate code for a horizontal cross layout can be found here:
* https://gist.github.com/tschw/da10c43c467ce8afd0c4
*/
vec2 cubeToUV( vec3 v, float texelSizeX, float texelSizeY ) {
// Horizontal cross layout:
const vec2 Squares = vec2( 4.0, 2.0 );
const vec2 Center = vec2( 1.0, 0.0 );
// Number of texels to avoid at the edge of each square
// Size of a square in UV space:
const vec2 TexSquareSize = 1.0 / Squares;
vec3 absV = abs( v );
// UV space offset of the center of the center square of the cross:
const vec2 TexCoordOffs = TexSquareSize * ( 0.5 + Center );
// Intersect unit cube
// Factors to scale square space (-1..+1 per square) to UV space:
const vec2 TexSquareScale = TexSquareSize * 0.5;
float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );
absV *= scaleToCube;
// Just less than a texel in square space when divided by resolution:
const float TexEps = 1.5; // = min(Squares.x, Squares.y) - 0.5;
// Apply scale to avoid seams
vec3 absV = abs( v );
vec3 sgnV = sign( v );
// two texels less per square (one texel will do for NEAREST)
v *= scaleToCube * ( 1.0 - 4.0 * texelSizeY );
// Intersect unit cube
// Unwrap
float scale = 1.0 / max( absV.x, max( absV.y, absV.z ) );
// space: -1 ... 1 range for each square
//
// #X## dim := ( 4 , 2 )
// # # center := ( 1 , 1 )
v *= scale;
absV *= scale;
vec2 planar = v.xy;
// Determine gate factors
float almostATexel = 1.5 * texelSizeY;
float almostOne = 1.0 - almostATexel;
// gate.? is one when on left / right, bottom / top, back
float eps = TexEps * texelSizeY;
vec3 gate = step( 1.0 - eps, vec3( absV.xy, v.z ) );
if ( absV.z >= almostOne ) {
// prefer any square over bottom / top
float notX = 1. - gate.x;
float notZ = 1. - gate.z;
gate.y *= notX * notZ;
// prefer back over side
gate.x *= notZ;
if ( v.z > 0.0 )
planar.x = 4.0 - v.x;
// Unwrap
} else if ( absV.x >= almostOne ) {
// start with xy coordinates
vec2 planar = v.xy;
float signX = sign( v.x );
planar.x = v.z * signX + 2.0 * signX;
// stop at the last texel (can use a factor of 1.0 for NEAREST)
float yTexelSize = 2.0 * Squares.y * texelSizeY;
float yAdjusted = planar.y * ( 1.0 - yTexelSize );
planar.y = yAdjusted;
planar.y -= gate.y * yAdjusted;
} else if ( absV.y >= almostOne ) {
// unwrap left / right, top / bottom
planar.x += gate.x * ( sgnV.x + v.z * sgnV.x );
float signY = sign( v.y );
planar.x = v.x + 2.0 * signY + 2.0;
planar.y = v.z * signY - 2.0;
planar.x += gate.y * ( -sgnV.y * 2.0 );
planar.y += gate.y * ( 2.0 + ( v.z * sgnV.y ) );
}
// unwrap back
planar.x += gate.z * ( 4.0 - 2.0 * planar.x );
// Transform to UV space
// adjust to UV space
return TexCoordOffs + planar * TexSquareScale;
// scale := 0.5 / dim
// translate := ( center + 0.5 ) / dim
return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );
}
......
......@@ -160,18 +160,35 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
var vpWidth = light.shadowMapWidth / 4.0;
var vpHeight = light.shadowMapHeight / 2.0;
/*
*
* These viewports map a cube-map onto a 2D texture with the
* following orientation:
*
* xzXZ
* y Y
*
* Y - Positive y direction
* y - Negative y direction
* X - Positive x direction
* x - Negative x direction
* Z - Positive z direction
* z - Negative z direction
*
*/
// positive X
cube2DViewPorts[ 0 ].set( vpWidth * 2, 0, vpWidth, vpHeight );
cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
// negative X
cube2DViewPorts[ 1 ].set( 0, 0, vpWidth, vpHeight );
cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
// positive Z
cube2DViewPorts[ 2 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
// negative Z
cube2DViewPorts[ 3 ].set( vpWidth, 0, vpWidth, vpHeight );
cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
// positive Y
cube2DViewPorts[ 4 ].set( 0, vpHeight, vpWidth, vpHeight );
cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
// negative Y
cube2DViewPorts[ 5 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );
} else {
......@@ -186,7 +203,7 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
var shadowFilter = THREE.LinearFilter;
if ( scope.type === THREE.PCFSoftShadowMap || light instanceof THREE.PointLight ) {
if ( scope.type === THREE.PCFSoftShadowMap) {
shadowFilter = THREE.NearestFilter;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册