glClipPlane - есть ли аналог в webGL?

У меня есть 3D сетка. Есть ли возможность визуализировать вид в разрезе (вырезку) как glClipPlane в OpenGL?

Я использую Three.js r65.

Последний добавленный мной шейдер:
Фрагментный шейдер:

uniform float time;
uniform vec2 resolution; 
varying vec2 vUv; 
void main( void ) 
{ 
vec2 position = -1.0 + 2.0 * vUv; 
float red = abs( sin( position.x * position.y + time / 2.0 ) ); 
float green = abs( cos( position.x * position.y + time / 3.0 ) ); 
float blue = abs( cos( position.x * position.y + time / 4.0 ) ); 
if(position.x > 0.2  && position.y > 0.2 ) 
{  
discard; 
 } 
gl_FragColor = vec4( red, green, blue, 1.0 ); }


Вершинный шейдер:

varying vec2 vUv;
void main() 
{ 
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 ); 
gl_Position = projectionMatrix * mvPosition; 
}

person user2118784    schedule 25.03.2014    source источник
comment
Вы нашли какое-нибудь удовлетворительное решение? Я столкнулся с аналогичным вопросом.   -  person Wilt    schedule 20.01.2015
comment
Еще нет. Все еще сомневаюсь.   -  person user2118784    schedule 21.01.2015
comment
Теперь в three.js есть встроенная поддержка такой функциональности. Проверьте мой ответ ниже!   -  person Wilt    schedule 04.07.2016
comment
Вопрос вводит в заблуждение. Если вы хотите найти ответ на Three.js, укажите это в вопросе. WebGL! === three.js   -  person andrevenancio    schedule 30.11.2017


Ответы (2)


В более новых версиях (> r.76) three.js обрезка поддерживается в _1 _ . - это свойство массива под названием clippingPlanes, куда вы можете добавить свои собственные плоскости отсечения ( THREE.Plane экземпляра).

Для three.js вы можете проверить эти два примера:

1) вырезка WebGL (база кода здесь, на GitHub)

2) расширенные возможности обрезки WebGL (код база здесь, на GitHub)


Простой пример

Чтобы добавить плоскость отсечения к renderer, вы можете:

var normal = new THREE.Vector3( -1, 0, 0 );
var constant = 0;
var plane = new THREE.Plane( normal, constant );
renderer.clippingPlanes = [plane];

Вот скрипка, чтобы продемонстрировать это.


Вы также можете закрепить на уровне объекта, добавив плоскость отсечения к материалу объекта. Чтобы это работало, вы должны установить для свойства Renderer localClippingEnabled значение true.

// set renderer
renderer.localClippingEnabled = true;

// add clipping plane to material
var normal = new THREE.Vector3( -1, 0, 0 );
var constant = 0;
var color = 0xff0000;
var plane = new THREE.Plane( normal, constant );
var material = new THREE.MeshBasicMaterial({ color: color });
material.clippingPlanes = [plane];
var mesh = new THREE.Mesh( geometry, material );

Примечание. В версии 77 некоторые функции отсечения в THREE.WebGLRenderer были перемещены в отдельный класс THREE.WebGLClipping, отметьте здесь для справки в основной ветке three.js.

person Wilt    schedule 29.06.2016

К сожалению, в спецификации OpenGL-ES, для которой был указан WebGL, нет плоскостей отсечения, а на этапе вершинного шейдера отсутствует вывод gl_ClipDistance, с помощью которого отсечение плоскости реализуется в современном OpenGL.

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

Обновлять

Давайте посмотрим, как плоскости отсечения определяются в конвейере фиксированных функций OpenGL:

void ClipPlane( enum p, double eqn[4] );

Значение первого аргумента p является символьной константой CLIP PLANEi, где i - целое число от 0 до n - 1, указывающее на одну из n определяемых клиентом плоскостей отсечения. eqn - это массив из четырех значений с плавающей запятой двойной точности. Это коэффициенты плоского уравнения в координатах объекта: p1, p2, p3 и p4 (в указанном порядке). К этим коэффициентам применяется инверсия текущей матрицы представления модели в момент их определения, что дает

p' = (p'1, p'2, p'3, p'4) = (p1, p2, p3, p4) inv(M)

(где M - текущая матрица вида модели; результирующее уравнение плоскости не определено, если M сингулярно, и может быть неточным, если M плохо обусловлено), чтобы получить коэффициенты уравнения плоскости в координатах глаза. Все точки с координатами глаза транспонируются ((x_e, y_e, z_e, w_e)), которые удовлетворяют

(p'1, p'2, p'3, p'4)   x_e  ≥ 0
                      y_e 
                      z_e 
                      w_e 

лежат в полупространстве, определяемом плоскостью; точки, не удовлетворяющие этому условию, не лежат в полупространстве.

Итак, что вы делаете, вы добавляете униформу, с помощью которой вы передаете параметры плоскости отсечения p 'и добавляете еще одну пару переменных out / in между вершинным и фрагментным шейдером, чтобы передать положение вершины в пространстве глаз. Затем во фрагментном шейдере первое, что вы делаете, это выполняете тест уравнения плоскости отсечения, и если он не проходит, вы отбрасываете фрагмент.

В вершинном шейдере

in  vec3 vertex_position;
out vec4 eyespace_pos;

uniform mat4 modelview;

void main()
{
    /* ... */
    eyespace_pos = modelview * vec4(vertex_position, 1);
    /* ... */
}

Во фрагментном шейдере

in vec4 eyespace_pos;

uniform vec4 clipplane;

void main()
{
    if( dot( eyespace_pos, clipplane) < 0 ) {
        discard;
    }
    /* ... */
}
person datenwolf    schedule 25.03.2014
comment
Привет, спасибо за быстрый ответ. Вы имеете в виду использовать Raycasting в Three.js для получения разрезов? - person user2118784; 25.03.2014
comment
@ user2118784: Не совсем. Вы можете обрезать примитивы на уровне фрагментов, вместо того, чтобы обрезать примитивную геометрию. В любом случае вам нужно написать шейдер фрагмента, поэтому первое, что вы делаете, это проверяете, соответствует ли положение фрагмента (передавая его как входную / выходную переменную из вершинного шейдера) условию плоскости отсечения. - person datenwolf; 25.03.2014
comment
@ user2118784: Я только что обновил свой ответ примером кода. - person datenwolf; 25.03.2014
comment
Спасибо. Недавно я обновил свой шейдер. Это правильный способ получить вид в разрезе? Как я могу получить вид в разрезе по плоскости? т.е. 3D-объект против плоскости. - person user2118784; 31.03.2014
comment
Привет, datenwolf! Можно ли использовать clipper.js [sourceforge.net/projects/jsclipper/estive для объектов Three.js для трехмерного разреза? Присылайте свои комментарии. Спасибо. - person user2118784; 09.07.2014
comment
@ user2118784: clipper.js предназначен для предварительной обработки геометрии в автономном режиме и, насколько я могу судить, не использует ускорение графического процессора. Если ваш набор геометрии невелик, вы, конечно, можете злоупотреблять им, но только с плохой производительностью. Вы, шейдеры, что-то делаете, но они не отсекают плоскость отсечения. - person datenwolf; 09.07.2014
comment
Спасибо. Пожалуйста, предложите мне начать с простого примера. т.е. обрезать куб по плоскости с помощью Three.js или чистого WebGL - person user2118784; 11.07.2014
comment
Принципиальный звук. Я не проверял, что у вас правильные данные. В конечном итоге может быть менее запутанным отправить спроектированный самолет в качестве униформы. Сравните это напрямую с позициями осколков, вместо того, чтобы сравнивать непроектируемые позиции и плоскость. Если я отправляю исходные позиции как выходные данные vrtx, это, как правило, временный взлом. Обычно это означает, что я что-то не придумал. например может потребоваться наброски конверта или поиск в Интернете, чтобы убедиться в том, как проецировать плоскость из мирового пространства в пространство отсечения с той же проекцией, что и вершинный шейдер. - person Thomas Poole; 05.04.2017
comment
У меня есть ключ к тому, что я упомянул о преобразовании, которое заключается в проецировании трех копланарных точек в пространство отсечения, и что уравнение плоскости, которое вы ищете, в координатах пространства отсечения, имеет форму Ax + By + Cz + Dw = 0. У меня мало времени, но этого должно быть достаточно, чтобы добраться туда. Ответ, вероятно, проще, чем работа. - person Thomas Poole; 05.04.2017