2014-01-17 5 views
5

Сценарий:
В моей сцене я применил вершинный шейдер, который позиционирует плоскость сетки по оси xz в положении камеры. Итак, если камера движется, плоскость сетки перемещается вместе с ней. Это приводит к визуальному эффекту, что при перемещении камеры плоскостная сетка остается неподвижной. Кажется, это работает правильно.

Сетка внезапно исчезает в три раза. Отсечение?

Проблема:
Если переместить камеру (и, следовательно, плоскость сетки) в определенной степени, сетка внезапно исчезает.
Я понял, что, по-видимому, существует связь между исчезновением и размером плоскости, т. Е. Чем больше плоскость, тем больше я могу перемещать камеру до исчезновения плоскости сетки.

Кроме того, на моей тестовой сцене плоская сетка исчезает только при движении по отрицательной оси х, положительной оси х или отрицательной оси z. Он не исчезает при движении по положительной оси z.

Я предполагаю, что это как-то связано с каким-то отсечением, но может быть и неправильным. Пересчет ограничивающей рамки плоской сетки не имел никакого эффекта.

Любые идеи?

Приветствие

Fiddle:
Я создал скрипку, которая показывает проблему: http://jsfiddle.net/p8wZ6/10/

В скрипке я добавил дополнительную сетку коробки, чтобы лучше визуализировать, что камера на самом деле двигается.
- Чтобы изменить ось, по которой камера перемещается (по умолчанию отрицательная ось Z) (не), прокомментируйте соответствующую строку кода в методе тика.
- Чтобы изменить размер плоскости, измените значение размера в методе createPlane.

Sourcecode Shader:

<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> 


Sourcecode 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(); 
+1

Самолет не перемещается, а камера. Поэтому, в конечном счете, самолет выходит за пределы усеченного участка камеры и подрезается - как и должно быть. – WestLangley

+0

Хм, на самом деле я перемещаю камеру и самолет. Камера перемещается, устанавливая свое свойство положения, плоскость перемещается исключительно в вершинном шейдере. Поэтому мне кажется, что камера не принимает во внимание репозициюg в вершинном шейдере. – padde

+0

Итак, в основном мне интересно, есть ли способ избежать этого (неправильного?) Обрезания при перемещении геометрии в вершинном шейдере. Или я делаю что-то совершенно неправильное здесь? – padde

ответ

15

У вас есть фундаментальное непонимание.

Вы перемещаете камеру в CPU. Вы перемещаете вершины плоскости в графическом процессоре.

Расчет усечения камеры не знает ничего о смещениях вершин в вершинном шейдере.

Как обходного, вы можете установить

planeMesh.frustumCulled = false; 

лучшее решение, чтобы просто добавить самолет, как ребенок камеры, и опускаем вершинные перемещения.

planeMesh.position.set(0, -1, 0); 
camera.add(planeMesh); 
scene.add(camera); 

Вы должны добавить камеру на график сцены, в которой вы используете второй подход.

Three.js R.65

+0

Спасибо, что прояснил это. Я не был уверен в том, где/когда на самом деле выполняется отсечение: на CPU или GPU. Как-то я предположил, что это будет на GPU. Как это делается на процессоре, для камеры самолет действительно неподвижен и поэтому обрезается. Полностью имеет смысл. Я знаю ваше второе предложение, просто хотел проверить, могу ли я сделать это на стороне GPU. Однако не знал о собственности frustumCulled. Приветствия. – padde

+0

Это действительно помогает ... спасибо –

0

Когда вы определяете камеру в R73 последние два параметра позволяют указать ближнего и дальнего расстояния г подрезки камеры.

Взятые по этой ссылке: http://threejs.org/docs/#Manual/Introduction/Creating_a_scene

var camera = 
new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); 

Третий параметр определяет Three.PerspectiveCamera близкого расстояния подрезки камеры и четвертый параметр определяет расстояние далеко подрезки камеры.

Смежные вопросы