Mag*_*ick 5 c++ opengl glsl lookup-tables
我开始了解如何实现片段着色器来执行一维 LUT,但我正在努力寻找任何好的资源来告诉您如何在 C++ 中制作一维 LUT,然后对其进行纹理化。
因此,对于给出以下 1D lut 的简单示例:
我会用以下数据制作一个数组吗?
int colorLUT[255] = {255,
254,
253,
...,
...,
...,
3,
2,
1,
0};
Run Code Online (Sandbox Code Playgroud)
或者unsigned char
我想因为我要给它贴图。
如果这是创建 LUT 的方法,那么我将如何将其转换为纹理?我应该使用glTexImage1D
吗?或者有没有更好的方法来做到这一点?我真的很茫然,任何建议都会有所帮助
很抱歉这么简短,但我还没有看到任何关于如何实际制作和链接 LUT 的教程,GLSL 上的每个教程都只告诉您他们总是忽略链接部分的着色器。
我的最终目标是我想知道如何采用如下所示的不同 1D LUT 并将它们全部应用于图像。
是的,您可以使用一维纹理作为查找表。
您可以使用 将数据加载到 1D 纹理中glTexImage1D()
。如果 8 位精度足以满足该值,则使用GL_R8
作为内部纹理格式,并在将数据GL_UNSIGNED_BYTE
传递给 时指定数据,是您的最佳选择。glTexImage1D()
您的调用将如下所示,其中lutData
包含数据的指针/数组GLubyte
以及lutSize
LUT 的大小:
glTexImage1D(GL_TEXTURE_1D, 0, GL_R8, lutSize, 0, GL_RED, GL_UNSIGNED_BYTE, lutData);
Run Code Online (Sandbox Code Playgroud)
如果您需要比 8 位更高的精度,可以使用GL_R16
或 等格式GL_R32F
。
确保您还正确设置纹理参数,例如查找表中的值之间的线性采样:
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Run Code Online (Sandbox Code Playgroud)
然后,您将纹理绑定到sampler1D
着色器中的统一,并使用常规纹理采样函数来检索新值。请记住,纹理坐标的范围是 0.0 到 1.0,因此您需要将原始值的范围映射到 [0.0, 1.0],然后再将其传递到纹理采样函数。从纹理采样函数收到的新值也将在 [0.0, 1.0] 范围内。
请注意,只要您的查找是一个相对简单的函数,在着色器中计算该函数可能会更有效。但如果 LUT 可以包含完全任意的映射,那么使用 1D 纹理是一个好方法。
在没有 1D 纹理的 OpenGL 变体(例如 OpenGL ES)中,您可以使用高度设置为 1 的 2D 纹理。
如果您需要大于支持的最大纹理大小的查找表,您还可以查看缓冲区纹理,正如 Andon 在他的评论中建议的那样。