我正在研究 oculus Rift 失真着色器的 OpenGL 实现。着色器通过获取输入纹理坐标(包含先前渲染场景的纹理)并使用失真系数对其进行变换,然后使用变换后的纹理来确定片段颜色来工作。
我希望通过预先计算失真并将其存储在第二个纹理中来提高性能,但结果实际上比直接计算慢。
直接计算版本基本是这样的:
float distortionFactor(vec2 point) {
float rSq = lengthSquared(point);
float factor = (K[0] + K[1] * rSq + K[2] * rSq * rSq + K[3] * rSq * rSq * rSq);
return factor;
}
void main()
{
vec2 distorted = vRiftTexCoord * distortionFactor(vRiftTexCoord);
vec2 screenCentered = lensToScreen(distorted);
vec2 texCoord = screenToTexture(screenCentered);
vec2 clamped = clamp(texCoord, ZERO, ONE);
if (!all(equal(texCoord, clamped))) {
vFragColor = vec4(0.5, 0.0, 0.0, 1.0);
return;
}
vFragColor = texture(Scene, texCoord);
}
其中 K 是作为统一传入的 vec4。
另一方面,置换贴图查找如下所示:
void main() {
vec2 texCoord = vTexCoord;
if (Mirror) {
texCoord.x = 1.0 - texCoord.x;
}
texCoord = texture(OffsetMap, texCoord).rg;
vec2 clamped = clamp(texCoord, ZERO, ONE);
if (!all(equal(texCoord, clamped))) {
discard;
}
if (Mirror) {
texCoord.x = 1.0 - texCoord.x;
}
FragColor = texture(Scene, texCoord);
}
还有一些其他操作可以校正纵横比并考虑镜头偏移,但它们非常简单。期望它胜过简单的纹理查找真的合理吗?
最佳答案
GDDR 内存具有相当高的延迟,现代 GPU 架构具有大量的数字运算能力。过去情况正好相反,GPU 无法进行计算,以至于通过从立方体贴图获取数据进行归一化的成本更低。
抛出一个事实,即您没有做 普通 这里的纹理查找,而是 受抚养人 查找,这并不奇怪。由于您从中获取的位置取决于另一次获取的结果,因此不可能预取/有效缓存(一种有效的延迟隐藏策略)着色器所需的内存。这不是“简单的纹理查找”。
更重要的是,除了进行依赖纹理查找之外,您的第二个着色器还包括 discard
关键词。这将有效地消除在许多硬件上进行早期深度测试的可能性。
老实说,我不明白你为什么要“优化”distortionFactor (...)
函数进行查找。它使用 平方长度 ,所以你甚至没有处理 sqrt
,只是一堆乘法和加法。
关于performance - 为什么纹理查找比直接计算慢得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20591893/