获得纹理OpenGL的最大/最小亮度

时间:2014-11-19 20:45:12

标签: opengl mapping shader hdr luminance

我从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图像缩小两倍。

1 个答案:

答案 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你的纹理。