【问题标题】:WebGL - discard fragments marked by vertex shaderWebGL - 丢弃由顶点着色器标记的片段
【发布时间】:2014-08-17 16:33:20
【问题描述】:

我有一个使用 Three.js 创建的粒子系统,其中每个粒子都有一组相关的参数(x、y、z、成本、炒作等),我还保留了这些参数每个的最小值/最大值。我已将这些定义为属性并创建了统一的最小/最大条目。通过滑块修改统一值以充当范围过滤器。

attributes["aGain"] = { type: "f", value: [] };

uniforms["uGainMin"] = { type: "f", value: 10.0 };
uniforms["uGainMax"] = { type: "f", value: 15.0 };

在顶点着色器中,我声明了属性和变量作为 FS 的标志。 1.0 表示可见,0.0 表示丢弃。

varying float vectorVisible;
attribute float again;

然后我将每个属性与相应的统一值进行比较。

if (aGain < uGainMin || aGain > uGainMax) { vectorVisible = 0.0; }
else { vectorVisible = 1.0; }

if 块对每个属性/统一配对都有一个条件。

在片段着色器中,我检查了vertexVisible 的值。

if (vectorVisible == 0.0) discard;

发生的情况是,一旦任何过滤器滑块值大于 0,我的整个粒子系统就会消失。

作为健全性检查,如果 VS 中的 gl_Position.x 组件小于 0 并且确实会导致这些片段被丢弃,我尝试将 vertexVisible 设置为 0.0。

if (gl_Position.x < 0.0) vectorVisible = 0.0;
else vectorVisible = 1.0;

我的属性数组已正确填充,并且在编译或运行时没有收到任何警告。那么,这整件事是不是我离题了?

My related initial question regarding filtering by parameters

更新:顶点着色器

这是整个顶点着色器。我不得不在 THREE.js particle basic 着色器中处理这个问题,这就是为什么它在 main 函数的前面设置了 gl_Position

uniform float size;
uniform float scale;
attribute float ay;
uniform float uyMin;
uniform float uyMax;
attribute float ax;
uniform float uxMin;
uniform float uxMax;
attribute float az;
uniform float uzMin;
uniform float uzMax;
attribute float again;
uniform float ugainMin;
uniform float ugainMax;
#ifdef USE_COLOR
    varying vec3 vColor;
#endif
#ifdef USE_SHADOWMAP
    varying vec4 vShadowCoord[ MAX_SHADOWS ];
    uniform mat4 shadowMatrix[ MAX_SHADOWS ];
#endif
void main() {
    #ifdef USE_COLOR
        #ifdef GAMMA_INPUT
            vColor = color * color;
        #else
            vColor = color;
        #endif
    #endif
    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
    #ifdef USE_SIZEATTENUATION
        gl_PointSize = size * ( scale / length( mvPosition.xyz ) );
    #else
        gl_PointSize = size;
    #endif
    gl_Position = projectionMatrix * mvPosition;
    #if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined (         USE_SHADOWMAP )
        #ifdef USE_SKINNING
            vec4 worldPosition = modelMatrix * skinned;
        #endif
        #if defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )
            vec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );
        #endif
        #if ! defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )
            vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
        #endif
    #endif
    #ifdef USE_SHADOWMAP
        for( int i = 0; i < MAX_SHADOWS; i ++ ) {
            vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;
        }
    #endif

    /***** Filters *****/
    if (ay < uyMin || ay > uyMax) gl_Position.xyz = vec3(2.);
    else if (ax < uxMin || ax > uxMax) gl_Position.xyz = vec3(2.);
    else if (az < uzMin || az > uzMax) gl_Position.xyz = vec3(2.);
    else if (again < ugainMin || again > ugainMax) gl_Position.xyz = vec3(2.);
}

JSFiddle

看到它(不)工作here

【问题讨论】:

  • 这些是点精灵?你需要所有这些阴影和变形的东西吗?这真的可以编译吗?我不确定最后发生了什么,但我会用代码更新答案。
  • 我过滤上面的所有代码都来自 THREE.js 着色器。它肯定会编译,我在控制台中没有收到任何错误或警告。
  • 你可以试试 gl_Position.xyz = vec3(2.);在 if else 链中?
  • 哈,我刚刚看到我没有设置 gl_Position。我添加了gl_Position.xyz = vec3(2.);,但这并没有改变行为;整个粒子系统仍然消失。
  • meh :( 剩下要做的唯一一件事就是使用颜色进行调试,例如,当它通过你给它的测试时,你可以点亮一个粒子,至少你会看到发生了什么那里

标签: opengl-es three.js webgl shader


【解决方案1】:

根据新信息:

添加这个:

var material = new THREE.ShaderMaterial({
    attributes:{
        aGain:{
            type:"f",
            value:null
        }
    },
    fragmentShader: fs_source....

我无法解释原因,但它应该可以工作。 :)

没有它,我根本无法显示 aGain(就 gpu 而言,它们都是 0)。

我不知道答案的正确程序是什么。另一个答案是关于剪裁的,这是给

“为什么我的自定义 three.js 属性缓冲区没有显示在着色器材质中?”。

【讨论】:

  • 不客气!你不知道这在过去让我有多头疼 :) 很高兴我能为你节省一些。
【解决方案2】:

我认为你又做错了:)

尝试将此作为片段着色器

void main(){
    gl_FragColor = vec4(1.);
}

为了模拟剪辑,在你的顶点着色器中尝试这样的方法:

if (aGain < uGainMin || aGain > uGainMax) {
    gl_Position = vec4(vec3(2.),1.0);//this might work, move it out of NDC and clip
} else {
    gl_Position = yourlogic; // for example: projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

如果您已经知道需要丢弃此对象,为什么要对其进行光栅化并进行测试。想象一下,如果这是一个占据大部分屏幕的大粒子。您至少要做的是运行片段着色器并测试每个像素。虽然你可以通过移动一个或四个顶点来摆脱它,比如粒子。

【讨论】:

  • 觉得你可能会回答这个问题 ;) 将顶点移出 NDC 仍然会使整个粒子系统消失。
  • 嗯,这不应该发生。你能用整个着色器代码更新问题吗?
  • 另外,试着找到属性数组,看看你实际上得到了什么样的值到数组中(如果有的话?)。这可能很棘手。
  • 更新了着色器。我的数组实际上填充了ints,但我看不出这是一个问题,因为我没有进行相等比较。但是,每个数组中都有预期的值数量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-06
  • 2011-05-24
  • 1970-01-01
  • 2019-01-24
  • 1970-01-01
相关资源
最近更新 更多