情境:
在我的场景中,我实现了一个顶点着色器,它将xz轴上的平面网格定位在摄像机的位置。
因此,如果相机移动,平面网格随之移动。这导致视觉效果,即在移动相机时,平面网格似乎保持固定在适当位置。这似乎工作正常。
问题:
如果我将相机(以及平面网格)移动到一定范围,网格会突然消失
我意识到平面的消失和大小之间似乎存在关系,即平面越大,我就越能在平面网格消失之前移动相机。
此外,在我的测试场景中,平面网格仅在负x轴,正x轴或负z轴上移动时消失。在正z轴上移动时不会消失。
我认为它与某种裁剪有关,但可能是错误的。重新计算平面网格的边界框无效。
有什么想法吗?
干杯
小提琴:
我创建了一个显示问题的小提琴:http://jsfiddle.net/p8wZ6/10/
在小提琴中,我添加了一个额外的盒子网格,以更好地显示相机实际移动
- 要更改摄像机移动的轴(默认为负z轴)(取消)勾选方法中的相应代码行。
- 要更改平面的大小,请更改createPlane方法中的大小值。
源代码着色器:
<script id="vertexShader" type="x-shader/x-vertex">
void main() {
vec4 pos = vec4( position, 1.0 );
vec4 wPos = modelMatrix * pos;
wPos.x += cameraPosition.x;
wPos.z += cameraPosition.z;
// standard
// vec4 pPos = projectionMatrix * modelViewMatrix * pos;
// keep fixed
vec4 pPos = projectionMatrix * viewMatrix * wPos;
gl_Position = pPos;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
void main() {
gl_FragColor.rgb = vec3(0.7, 0.7, 0.7);
gl_FragColor.a = 1.0;
}
</script>
源代码JS:
var scene;
var camera;
var light;
var renderer;
var controls;
var onTick;
var planeMesh;
var boxMesh;
var heightmap;
var clock;
function createPlane(){
// disappearance seems related to size of geometry.
// the larger the longer it takes until disappearance.
var size = 20;
var geom = new THREE.PlaneGeometry(size, size, 20, 20);
return geom;
}
function createBox(){
var geom = new THREE.CubeGeometry(2, 2, 4);
return geom;
}
function createMesh(){
// plane
var geom = createPlane();
var shaderMaterial = new THREE.ShaderMaterial({
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
side: THREE.DoubleSide,
wireframe: true
});
planeMesh = new THREE.Mesh(geom, shaderMaterial);
var axis = new THREE.AxisHelper(4);
planeMesh.rotation.x = -90 * (Math.PI / 180);
planeMesh.add(axis);
scene.add(planeMesh);
// box
geom = createBox();
var material = new THREE.MeshBasicMaterial( {
color: 0xff00ff,
});
boxMesh = new THREE.Mesh(geom, material);
boxMesh.position.x = 5;
boxMesh.position.z = -15;
axis = new THREE.AxisHelper(4);
boxMesh.add(axis);
scene.add(boxMesh);
}
function startRendering(){
onTick();
};
function onTick(){
// move camera
// causes disappearance
// neg. z
camera.position.z -= .1;
// pos. x
// camera.position.x += .1;
// neg. x
// camera.position.x -= .1;
// causes no disappearance
// pos. z
// camera.position.z += .1;
requestAnimationFrame(onTick);
//controls.update(clock.getDelta());
renderer.render(scene, camera);
}
function init(){
renderer = new THREE.WebGLRenderer();
renderer.setClearColor( 0xffffff, 1 );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
scene.add(new THREE.AxisHelper(4));
camera = new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 1, 0);
light = new THREE.DirectionalLight(0xffffff, 1);
light.shadowCameraVisible = true;
light.position.set(0, 0, 100);
scene.add(light);
//clock = new THREE.Clock();
//controls = new THREE.FirstPersonControls(camera);
//controls.movementSpeed = 20;
//controls.lookSpeed = .1;
}
init();
createMesh();
startRendering();
答案 0 :(得分:16)
你有一个根本的误解。
您正在CPU中移动相机。您正在GPU中移动平面的顶点。
相机的平截头体计算对顶点着色器中的顶点位移一无所知。
作为解决方法,您可以设置
planeMesh.frustumCulled = false;
更好的解决方案是将平面添加为相机的子级,并省略顶点位移。
planeMesh.position.set( 0, -1, 0 );
camera.add( planeMesh );
scene.add( camera );
您必须将相机添加到使用第二种方法的场景图中。
three.js r.65
答案 1 :(得分:1)
在r73中定义相机时,最后两个参数允许您指定相机的近距离和远距离z剪裁距离。
取自此链接:http://threejs.org/docs/#Manual/Introduction/Creating_a_scene
var camera =
new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
Three.PerspectiveCamera的第三个参数定义了摄像机的近剪裁距离,第四个参数定义了摄像机的远剪裁距离。