1

我从 OpenGL 开始,我想创建一个色调映射 - 算法。

我知道我的第一步是获取 HDR 图像的最大/最小亮度值。

我在 FBO 的纹理中有图像,但我不知道如何开始。

我认为最好的方法是将tex坐标传递给片段着色器,然后遍历所有像素并生成更小的纹理。

但是,在我拥有 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_0FBO ( ) 中的纹理。我的目标是让我的 FBO 纹理中的图像将其大小减少两倍。layout(location=0)GL_TEXTURE_0layout(binding=0)texHDR

4

1 回答 1

1

对于下采样,您需要在片段着色器中做的就是多个纹理查找,然后将它们组合为输出片段。例如,您可以进行 2x2 查找,因此每次通过都会将 x 和 y 的分辨率降低 2 倍。

假设您要缩小 1024x1024 图像。然后你会将一个四边形渲染成一个 512x512 的图像。设置它,以便您的顶点着色器简单地为 x 和 y 生成 0 到 511 之间的值。然后片段着色器调用texelFetch(tex, ivec2(2*x+i,2*y+j)),其中 i 和 j 从 0 循环到 1。缓存这四个值,在纹理中输出最小值和最大值。

于 2014-11-20T00:45:39.910 回答