【问题标题】:glClipPlane - Is there an equivalent in webGL?glClipPlane - webGL 中是否有等价物?
【发布时间】:2014-05-02 22:02:36
【问题描述】:

我有一个 3D 网格。是否有可能在 OpenGL 中渲染像glClipPlane 这样的剖面图(剪辑)?

我正在使用 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; 
}

【问题讨论】:

  • 您找到满意的解决方案了吗?我遇到了similar question
  • 还没有。我仍然有疑问。
  • 现在在three.js 中有对此类功能的原生支持。在下面检查我的答案!
  • 这个问题具有误导性。如果您正在寻找 Three.js answear,请在问题中指定。 WebGL !=== 三.js

标签: three.js opengl-es-2.0 webgl fragment-shader vertex-shader


【解决方案1】:

不幸的是,在指定了 WebGL 的 OpenGL-ES 规范中没有裁剪平面,并且顶点着色器阶段缺少 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',并在顶点和片段着色器之间添加另一个输出/输入变量对,以传递顶点眼空间位置。然后在片段着色器中,您要做的第一件事就是执行剪辑平面方程测试,如果没有通过,则丢弃片段。

在顶点着色器中

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;
    }
    /* ... */
}

【讨论】:

  • 您好,感谢您的快速回复。你的意思是,在 Three.js 中使用 Raycasting 来实现剖视图?
  • @user2118784:不完全是。您可以在片段级别剪辑图元,而不是剪辑图元几何体。无论如何,您都必须编写片段着色器,因此您要做的第一件事是测试片段的位置(将其作为来自顶点着色器的输入/输出变量传递)是否通过剪辑平面条件。
  • @user2118784:我刚刚用一些示例代码更新了我的答案。
  • 谢谢。我最近更新了我的着色器。这是实现剖面图的正确方法吗?如何通过平面获得剖面图?即针对平面的 3d 对象。
  • 嗨 datenwolf,是否可以使用 clipper.js [sourceforge.net/projects/jsclipper/] 用于 Three.js 对象的 3D 剖面视图?请发送您的cmets。谢谢。
【解决方案2】:

在更新版本 (> r.76) 的 three.js 中,THREE.WebGLRenderer 支持剪辑。 is an array property called clippingPlanes 可以在其中添加自定义剪切平面(THREE.Plane 实例)。

对于three.js,您可以查看以下两个示例:

1) WebGL clipping(代码库here on GitHub

2) WebGL clipping advanced(代码库here on GitHub


一个简单的例子

要将剪切平面添加到renderer,您可以这样做:

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

Here a fiddle 来证明这一点。


您还可以通过向对象材质添加剪切平面来在对象级别进行剪切。为此,您必须将渲染器 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 );

注意:在 r.77 中,THREE.WebGLRenderer 中的一些剪辑功能已移至单独的 THREE.WebGLClipping 类,请检查 here for reference in the three.js master branch

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-29
    • 2013-06-21
    • 2014-01-09
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多