【问题标题】:GLSL stops renderingGLSL 停止渲染
【发布时间】:2016-10-31 16:06:44
【问题描述】:

我想写一个有符号的距离解释。例如,我正在创建一个体素网格 100*100*100 (如果它正在工作,尺寸会增加)。 现在我的计划是将点云加载到一维纹理中:

glEnable(GL_TEXTURE_1D);
glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_1D, _texture);

glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, pc->pc.size(), 0, GL_RGBA, GL_FLOAT, &pc->pc.front());

glBindTexture(GL_TEXTURE_1D, 0);

'pc' 只是一个包含结构 Point 的向量的类,它只有浮点 x,y,z,w。

比我想渲染洞 100x100x100 网格,所以每个体素并迭代该纹理的所有点,计算到我当前体素的距离并将该距离存储在新纹理 (1000x1000) 中。目前,我正在创建的这个纹理只包含颜色值,它将距离存储在红色和绿色分量中,蓝色设置为 1.0。 所以我可以在屏幕上看到结果。

我现在的问题是,当我的点云中有大约 500 000 个点时,它似乎在几个体素(少于 50 000)后停止渲染。我的猜测是,如果需要很长时间,它就会停下来,然后把它拥有的缓冲区扔掉。 我不知道是不是这样,但如果是的话,我可以做些什么来对付它,或者我可以做些什么来使这个过程更好/更快。

我的第二个猜测是,我没有考虑 1D 纹理。但是有没有更好的方法来传递大量数据?因为我肯定需要几十万点数据。

我不知道如果我显示完整的片段着色器是否有帮助,所以我只会显示一些我认为对这个问题很重要的部分:

通过所有点的距离计算和迭代:

for(int i = 0; i < points; ++i){
        vec4 texInfo = texture(textureImg, getTextCoord(i));
        vec4 pos = position;
        pos.z /= rows*rows;
        vec4 distVector = texInfo-pos;
        float dist = sqrt(distVector.x*distVector.x + distVector.y*distVector.y + distVector.z*distVector.z);
        if(dist < minDist){
            minDist = dist;
        }
    }

函数getTexCoord:

float getTextCoord(float a)
{
    return (a * 2.0f + 1.0f) / (2.0f * points);
}

*编辑:

vec4 newPos = vec4(makeCoord(position.x+Col())-1,
                   makeCoord(position.y+Row())-1,
                   0,
                   1.0);

float makeCoord(float a){
return (a/rows)*2;
}

int Col(){
float a = mod(position.z,rows);
return int(a);
}

int Row()
{
    float a = position.z/rows;
    return int(a);
}

【问题讨论】:

  • 您使用的是哪个操作系统?在 Windows 上,WDDM 可能会强制您的应用退出(尽管它看起来更像是驱动程序恢复而不是着色器退出)
  • OS X El Capitan 版本 10.11.5
  • 那就不可能了。你确定你的音量没有被剔除吗?
  • 我不这么认为,如果我只使用点云中的少量点(例如 1000)它可以正常工作,但如果我使用 10000 则会出现问题。
  • 这永远不会实时工作,除非您采取措施减少每个片段的工作量。现在我向你保证正在发生的事情是你的片段花费了太长时间,它触发了一个看门狗计时器,并且驱动程序重置了 OpenGL 上下文。有一些鲁棒性扩展可以避免杀死冗长的着色器执行,但这只是一个创可贴。考虑使用几何着色器或其他东西将这项工作拆分为多个简单的调用,并在最后合并结果。我真的不明白你在这里想要做什么更具体。

标签: c++ opengl glsl


【解决方案1】:
  1. 您绝对不应该循环遍历片段着色器中的所有点,因为它每帧计算 N 次(其中 N 等于像素数),这实际上给了您 O(N2) 计算复杂度。
  2. 所有纹理对每个维度可以容纳多少数据都有限制。这里最重要的两个值是 GL_MAX_TEXTURE_SIZE 和 GL_MAX_3D_TEXTURE_SIZE。如official docs 中所述,

    纹理大小有一个基于 GL 实现的限制。对于 1D 和 2D 纹理(以及使用类似维度的任何纹理类型,如立方体贴图),任一维度的最大尺寸为 GL_MAX_TEXTURE_SIZE。对于数组纹理,最大数组长度为 GL_MAX_ARRAY_TEXTURE_LAYERS。对于 3D 纹理,尺寸不能大于 GL_MAX_3D_TEXTURE_SIZE。

    在这些限制内,纹理的大小可以是任何值。但是,建议您坚持使用 2 的幂来获取纹理大小,除非您非常需要使用任意大小。

    列出了最典型的值herehere

  3. 如果您确实必须在片段着色器中使用大量数据,请考虑使用已知的 2 次幂维度和 GL_NEAREST / GL_REPEAT 坐标的 2D 或 3D 纹理。这将使您能够计算 2D 纹理坐标,只需将源偏移量乘以预先计算的 1/宽度值(Y 坐标;根据定义,余数小于 1 texel,在存在 GL_NEAREST 的情况下可以安全地忽略)并将其用作- 用于 X 坐标(GL_REPEAT 保证只使用余数)。当我需要将 128 MB 的数据传递给 GLSL 1.20 着色器时,我个人实施了这种方法。

  4. 如果您的目标是足够新的 OpenGL (≥ 3.0),您也可以使用 buffer textures

  5. 最后,但并非最不重要。您不能通过标准 IEEE 浮点数传递大于 224 的整数精度值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-24
    • 2014-07-09
    • 1970-01-01
    • 2021-06-22
    • 2016-12-26
    • 2013-08-06
    • 1970-01-01
    相关资源
    最近更新 更多