我从OpenGL开始,我想创建一个色调映射算法。
我知道我的第一步是获取HDR图像的最大/最小亮度值。
我在FBO的纹理中有图像,我不知道如何开始。
我认为最好的方法是将tex coords传递给片段着色器然后遍历所有像素并生成某种较小的纹理。
但是,我不知道如何手动下采样,直到我有1x1纹理;我应该有很多FBO吗?我在哪里创建每个新纹理?
我搜索了很多信息,但我几乎没有任何明确的信息。
我很感激帮助自己定位并开始。
编辑1.这是我的着色器,以及如何将纹理坐标传递给顶点着色器:
要传递纹理坐标和顶点位置,我使用VBO绘制四边形:
void drawQuad(Shaders* shad){
// coords: vertex (3) + texture (2)
std::vector<GLfloat> quadVerts = {
-1, 1, 0, 0, 0,
-1, -1, 0, 0, 1,
1, 1, 0, 1, 0,
1, -1, 0, 1, 1};
GLuint quadVbo;
glGenBuffers(1, &quadVbo);
glBindBuffer(GL_ARRAY_BUFFER, quadVbo);
glBufferData(GL_ARRAY_BUFFER, 4 * 5 * sizeof(GLfloat), &quadVerts[0], GL_STATIC_DRAW);
// Shader attributes
GLuint vVertex = shad->getLocation("vVertex");
GLuint vUV = shad->getLocation("vUV");
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 3 * sizeof(GLfloat), NULL);
// Set attribs
glEnableVertexAttribArray(vVertex);
glVertexAttribPointer(vVertex, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, 0);
glEnableVertexAttribArray(vUV);
glVertexAttribPointer(vUV, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (void*)(3 * sizeof(GLfloat)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // Draw
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(vVertex);
glDisableVertexAttribArray(vUV);
}
顶点着色器:
#version 420
in vec2 vUV;
in vec4 vVertex;
smooth out vec2 vTexCoord;
uniform mat4 MVP;
void main()
{
vTexCoord = vec2(vUV.x * 1024,vUV.y * 512);
gl_Position = MVP * vVertex;
}
片段着色器:
#version 420
smooth in vec2 vTexCoord;
layout(binding=0) uniform sampler2D texHDR; // Tex image unit binding
layout(location=0) out vec4 color; //Frag data output location
vec4[4] col;
void main(void)
{
for(int i=0;i<=1;++i){
for(int j=0;j<=1;++j){
col[(2*i+j)] = texelFetch(texHDR, ivec2(2*vTexCoord.x+i,2*vTexCoord.y+j),0);
}
}
color = (col[0]+col[1]+col[2]+col[3])/4;
}
在这个测试代码中,我有一个大小为1024 * 512的纹理。我的想法是使用此着色器和GL_ATTACHMENT_0
中绑定了具有图像(layout(location=0)
)的纹理,在FBO(GL_TEXTURE_0
)中渲染附加到layout(binding=0)
的纹理。
我的目标是让我的FBO纹理中的texHDR
图像缩小两倍。
答案 0 :(得分:1)
对于下采样,片段着色器中您需要做的就是多次纹理查找,然后将它们组合成输出片段。例如,您可以执行2x2查找,因此每次传递都会将x和y的分辨率降低2倍。
假设您要缩小1024x1024图像。然后,您将四边形渲染为512x512图像。设置它,使你的顶点着色器只生成0到511之间的x和y值。片段着色器然后调用texelFetch(tex, ivec2(2*x+i,2*y+j))
,其中i和j从0循环到1.缓存这四个值,输出min和max in你的纹理。