// some definitions
void main() {
float seed = uSeed;
float x = vPos.x;
float y = vPos.y;
float value = 1.0;
// Nothing to see here...
gl_FragColor = vec4(value, value, value, 1.0);
}
所以这只是呈现白色的帆布。在我的机器上,它的平均速度约为30 fps。 =“ lang-cplusplus prettyprint-override”>
void main() {
float seed = uSeed;
float x = vPos.x;
float y = vPos.y;
float value = 1.0;
float noise;
for ( int j=0; j<10; ++j)
{
noise = 0.0;
for ( int i=4; i>0; i-- )
{
float oct = pow(2.0,float(i));
noise += snoise(vec2(mod(seed,13.0)+x*oct,mod(seed*seed,11.0)+y*oct))/oct*4.0;
}
}
value = noise/2.0+0.5;
gl_FragColor = vec4(value, value, value, 1.0);
}
如果要运行上面的代码,我一直在使用
snoise
的此实现。这样会将fps降低到大约7。这很有意义。在以下条件中:
if (int(mod(x*512.0,4.0)) == 0 && int(mod(y*512.0,4.0)) == 0)) {
// same noise computation
}
您希望它会更快,但是仍然只有7 fps。
对于另一个测试,让我们使用以下条件过滤像素:
if (x > 0.5 && y > 0.5) {
// same noise computation
}
这将提供与以前完全相同的噪声像素数量,但是n现在我们可以恢复到近30 fps。
这是怎么回事?两种滤除第16个像素的方式不应该给出完全相同的周期数吗?为什么较慢的像素像渲染所有像素一样慢?
奖金问题:我该怎么办?如果我确实确实想只用一些昂贵的片段来散布我的画布,有什么方法可以解决这个可怕的性能?
(可以肯定的是,通过将第16个像素渲染为黑色而不是白色,我已经确认了实际的模运算根本不影响帧速率。)
#1 楼
像素被分组为小方块(大小取决于硬件),并在单个SIMD管道中一起计算。 (SIMD数组类型的结构)此管道(根据供应商的不同,具有几种不同的名称:扭曲,波阵面)将以锁步方式对每个像素/片段执行操作。这意味着如果1个像素需要完成计算,则所有像素都将对其进行计算,而不需要结果的像素将丢弃它。其他分支将不会执行。
这意味着您计算第16个像素的第一种方法是最坏情况的分支。
如果要缩小图像尺寸,只需渲染为较小的纹理,然后进行放大。
评论
$ \ begingroup $
渲染较小的纹理并进行升采样是一种很好的方法。但是,如果由于某些原因您确实需要写入大纹理的每个第16个像素,则使用对每个第16个像素加上一个调用的计算着色器,再加上图像加载/存储以将写入分散到渲染目标中,可能是一个不错的选择。
$ \ endgroup $
–内森·里德(Nathan Reed)
15年8月16日在0:28