【问题标题】:Create and use floating point texture in OpenGL在 OpenGL 中创建和使用浮点纹理
【发布时间】:2014-03-12 09:36:24
【问题描述】:

我正在尝试在 OpenGL 中创建浮点纹理。 我有 4 个顶点(2 个多边形)形成正方形:

                  -------
                  |\    |
                  |  \  |
                  |    \|
                  -------

现在我想用浮点值创建纹理,每个纹理值代表每个像素的基本颜色强度。

我想像这样在片段着色器中计算像素颜色:

color = texture2D(texture, coordinates).r * vec4(0.4, 1.0, 0.8, 1.0);

vec4(0.4, 1.0, 0.8, 1.0) 只是我使用的基本颜色

当我准备这样的数据时:

int width, height;
width = 16;
height = 16;
float data[16][16];
for(int i = 0; i < width; i++){
    for(int j = 0; j < height; j++){
        data[i][j] = 0.5f;
    }
}

GLuint n_tex_surface;
glGenTextures(1, &n_tex_surface);
glBindTexture(GL_TEXTURE_2D, n_tex_surface);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, data);
glGenerateMipmap(GL_TEXTURE_2D);

编辑:

初始化

vertices[] = {
0, 1, -1, -1, 1, /**/1, 1, 1, -1, 1,/**/ 1, 0, 1, 1, 1,/**/ 0, 0, -1, 1, 1};
indices[] = {   
    0, 1, 2, 0, 2, 3};

glGenBuffers(1, &n_vertex_buffer_object);
glBindBuffer(GL_ARRAY_BUFFER, n_vertex_buffer_object);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glGenBuffers(1, &n_index_buffer_object);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, n_index_buffer_object);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

glGenVertexArrays(1, &n_vertex_array_object);
glBindVertexArray(n_vertex_array_object);
{
    glBindBuffer(GL_ARRAY_BUFFER, n_vertex_buffer_object);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), p_OffsetInVBO(0));
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), p_OffsetInVBO(2 * sizeof(float)));   

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, n_index_buffer_object);
}
glBindVertexArray(0);

绘画

glBindVertexArray(n_vertex_array_object);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, p_OffsetInVBO(0));
glBindVertexArray(0);

我的结果如下所示:

我得到的不是只有一种颜色强度的正方形。似乎纹理太小,不适合正方形。应该是什么尺寸的纹理?我怎么知道的? 我是否以正确的方式创建纹理?

尺寸为 128x128:

有了 64x64 我得到了这个列,这就是我想要的,但为什么它没有覆盖整个正方形?

这是在我电脑上的 OpenGL 3.3 中。

你能帮帮我吗?

编辑:

当我用 Addison Wesley OpenGL 编程指南中的示例替换我的纹理创建代码时,它工作得很好,为什么我的代码不能呢?

GLuint n_tex_surface;
GLubyte checkImage[dataheight][datawidth][4];
 int i, j, c;
for (i = 0; i < dataheight; i++) {
  for (j = 0; j < datawidth; j++) {
     c = (((i&0x8)==0)^((j&0x8))==0)*255;
     checkImage[i][j][0] = (GLubyte) c;
     checkImage[i][j][1] = (GLubyte) c;
     checkImage[i][j][2] = (GLubyte) c;
     checkImage[i][j][3] = (GLubyte) 255;
  }
}

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &n_tex_surface);
glBindTexture(GL_TEXTURE_2D, n_tex_surface);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
               GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
               GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, datawidth, 
            dataheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 
            checkImage);

编辑: 顶点着色器

#version 330
in vec2 v_tex;
in vec3 v_pos;
uniform mat4 t_modelview_projection_matrix;
out vec2 v_texcoord;
void main()
{
gl_Position = t_modelview_projection_matrix * vec4(v_pos, 1.0);
v_texcoord = v_tex;
} 

片段着色器

#version 330
in vec2 v_texcoord;
out vec4 color;

uniform sampler2D n_box_tex;

void main()
{
frag_color = texture2D(n_box_tex, v_texcoord).r * vec4(0.4, 1.0, 0.8, 1.0);
}

【问题讨论】:

  • 请显示绘制三角形的代码,包括。顶点的纹理坐标。
  • p_OffsetInVbo 是做什么的?
  • #define p_OffsetInVBO(off) ((void*)(off))
  • 好的,最后,如何访问着色器中的纹理坐标?
  • 如果将这两行代码放入代码中会发生什么? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

标签: c++ opengl floating-point textures


【解决方案1】:

您只为 1/4 个纹理分配了足够的存储空间。

您需要使用float data[16][16][4],然后为纹理的每个组件分配0.5f的值:

int width, height;
width = 16;
height = 16;
float data[16][16][4];
for(int i = 0; i < width; i++){
    for(int j = 0; j < height; j++){
        data[i][j][0] = 0.5f;
        data[i][j][1] = 0.5f;
        data[i][j][2] = 0.5f;
        data[i][j][3] = 0.5f;
    }
}

您实际上很幸运,您最初尝试的操作并未使您的软件崩溃。您正在/正在强制 GL 在读取纹理图像数据时超出您分配的存储空间。

【讨论】:

  • 但我想创建每个像素只有一个浮点值的纹理。所以它不会是RGBA纹理。只有..可以说...带有浮点值的红色通道。我该怎么做?
  • @Pan.student 好吧,那么使用单通道纹理,即GL_R32F 代替GL_RGBA32FGL_RED 代替GL_RGBA。您认为GL_RGBA32F 纹理包含多少个通道,或者 OpenGL 如何通过查看您提供的数据太短来确定您想要的内部格式?
【解决方案2】:

谢谢大家,问题出在 GL_ 常量上! 这按预期工作:

GLuint n_tex_surface;
GLfloat checkImage[dataheight][datawidth];

for (int i = 0; i < dataheight; i++) {
    for (int j = 0; j < datawidth; j++) {
        float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX); = r + 0.01f;
        checkImage[i][j] = (GLfloat) r;
    }
}

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &n_tex_surface);
glBindTexture(GL_TEXTURE_2D, n_tex_surface);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

这里我们有 GL_RED(单通道纹理),它是 GL_FLOAT:

 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, datawidth, dataheight, 0, GL_RED, GL_FLOAT, checkImage);

其余代码和着色器保持不变。

【讨论】:

  • 错误答案。 GL_RED创建浮点纹理。它获取您的浮点数据并将其转换 为标准化的定点格式(除此之外,它也是一种未调整大小的格式,因此已弃用)。你要的是GL_R32F(对于内部格式,当然CPU格式还是GL_RED)。
  • 所以应该是:glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, datawidth, dataheight, 0, GL_RED, GL_FLOAT, checkImage); ?
  • 没错。无论输入数据的类型如何,GL_RGBAGL_RGBA8 等纹理格式始终是标准化的定点。对于整数和浮点纹理,您需要在内部格式的某处显式地使用 FIUI
  • 接受已对原始问题给出正确答案的答案,并删除未解决原始问题的答案如问题所述 i> 已经足够了。 ;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-08
  • 1970-01-01
  • 2016-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多