Three.JS Обрезка объектов?

Я пытаюсь разделить свои 3D-модели с помощью three.js так, как это делает Unity:

Я играл с элементами управления камерой и, конечно, я могу отрегулировать поля ближнего / дальнего поля, чтобы обрезать в направлении камеры, но что, если я хочу просто обрезать в плоскости X или Y? Я рассмотрел возможность добавления большого прозрачного блока, который мог бы скользить по этой оси, а затем использовать двоичные операции для слияния / вычитания там, где он пересекается с объектом, но в итоге инструменты создали новую сетку вдоль новой плоскости, а не фактически удалили все вдоль нее. ось.

Нужно ли работать с несколькими областями просмотра или есть более простой способ?

2 ответа

Решение

Отсечение теперь поддерживается.

Вот образец для подражания. Адаптируйте его в соответствии с вашим вариантом использования.

var localPlane = new THREE.Plane( new THREE.Vector3( 0, - 1, 0 ), 1 );

var globalPlane = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 1 );

renderer.clippingPlanes = [ globalPlane ];

renderer.localClippingEnabled = true;

var material = new THREE.MeshPhongMaterial( {
    clippingPlanes: [ localPlane ],
    clipShadows: true
} );

Посмотрите эти примеры three.js:

https://threejs.org/examples/webgl_clipping.html https://threejs.org/examples/webgl_clipping_advanced.html

three.js r.85

Отсечение может быть легко сделано в шейдере. Используя некоторые расчеты, вы можете даже получить, например, сферу, как область отсечения. Отсечение в плоскости, ортогональной системе координат, является самым простым. В вершинном шейдере вычисляем мировую позицию пикселя:

worldPosition = modelMatrix * vec4( position, 1.0 );

В фрагментном шейдере отбросьте рисунок пикселя, если он выходит за пределы ограничения:

if ( worldPosition.x > clippingLimitX ) {
    discard;
}

Это, однако, оставит сетку открытой на краю отсечения. Чтобы закрыть его, используйте трафаретный буфер. Украсьте трафарет сценой с задними гранями. Затем увеличьте трафарет сценой, показывающей обрезанные передние грани. Материалы, используемые в этих сценах, не должны быть видны, поэтому отключите их цвет и глубину записи:

new THREE.ShaderMaterial( { colorWrite: false, depthWrite: false, ... } );

Используйте трафарет, чтобы визуализировать плоскость, которая находится в позиции плоскостей отсечения. После отключения трафарета визуализируйте обрезанные лицевые грани.

renderer.autoClear = false;
renderer.clear();

var gl = renderer.context;

renderer.state.setStencilTest( true );

renderer.state.setStencilFunc( gl.ALWAYS, 1, 0xff );
renderer.state.setStencilOp( gl.KEEP, gl.KEEP, gl.INCR );
renderer.render( backStencilScene, camera );

renderer.state.setStencilFunc( gl.ALWAYS, 1, 0xff );
renderer.state.setStencilOp( gl.KEEP, gl.KEEP, gl.DECR );
renderer.render( frontStencilScene, camera );

renderer.state.setStencilFunc( gl.EQUAL, 1, 0xff );
renderer.state.setStencilOp( gl.KEEP, gl.KEEP, gl.KEEP );
renderer.render( capsScene, camera );

renderer.state.setStencilTest( false );

renderer.render( scene, camera );

Я сделал демонстрацию, показывающую, как обрезать несколько плоскостей одновременно:

http://daign.github.io/clipping-with-caps/

Я не использовал встроенные плоскости отсечения three.js, потому что для работы этой демонстрации мне нужно отрисовать трафарет с помощью шейдера, который определяет, направлена ​​ли плоскость отсечения в сторону от камеры или нет, и только обрезать эти плоскости лицом к камере.

Другие вопросы по тегам