OpenGL3显示错误的纹理
我正在尝试为我的程序添加第二个sampler2DRect纹理。 我为第二个纹理使用单独的着色器文件,否则我使用的是用于显示第一个纹理的相同代码。 但是,当我尝试显示第二个纹理时,它会显示第一个纹理,而我似乎无法弄清楚原因。 我可能做了一个错误的API调用,或者可能省略了一些重要的东西,但我没有尝试修复这个问题。
没有GL错误报告,并且gDEBugger不显示任何可疑内容。
我猜这个问题可能在我的代码中的其他地方,但这里是我用来绘制第二个纹理(与绘制第一个纹理的代码几乎相同)的部分:
Test_World_Pause_Menu::Test_World_Pause_Menu(int resolution_width, int resolution_height)
: _shaders("shaders/pause_menu.vert", "shaders/pause_menu.frag"),
_vao_id( new GLuint[1] ),
_mvp_id( new GLint[1] ),
_pm_tex_id( new GLuint[1] ),
_mvp( glm::ortho(0.0f, (GLfloat)resolution_width, 0.0f, (GLfloat)resolution_height, -1.0f, 1.0f) ),
_pm_vertices_buffer( new GLuint[1] ),
_pm_vertices( new GLfloat[12] ),
_pm_colors_buffer( new GLuint[1] ),
_pm_colors( new GLfloat[16] ),
_pm_tex_coords_buffer( new GLuint[1] ),
_pm_tex_coords( new GLfloat[8] ),
_pm_normals_buffer( new GLuint[1] ),
_pm_normals( new GLfloat[12] )
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // set alpha blending mode
// begin pause menu initialization
_pm_image.loadFromFile("resources/levels/test_00/pause_menu/pause_menu.png");
_pm_image.flipVertically();
unsigned int pm_location_x = 0;
unsigned int pm_location_y = _pm_image.getSize().y;
unsigned int pm_width = _pm_image.getSize().x;
unsigned int pm_height = _pm_image.getSize().y;
_pm_vertices[0] = pm_location_x; _pm_vertices[1] = pm_location_y; _pm_vertices[2] = 0.0f;
_pm_vertices[3] = pm_location_x; _pm_vertices[4] = pm_location_y - pm_height; _pm_vertices[5] = 0.0f;
_pm_vertices[6] = pm_location_x + pm_width; _pm_vertices[7] = pm_location_y - pm_height; _pm_vertices[8] = 0.0f;
_pm_vertices[9] = pm_location_x + pm_width; _pm_vertices[10] = pm_location_y; _pm_vertices[11] = 0.0f;
_pm_colors[0] = 1.0f; _pm_colors[1] = 1.0f; _pm_colors[2] = 1.0f; _pm_colors[3] = 0.0f;
_pm_colors[4] = 1.0f; _pm_colors[5] = 1.0f; _pm_colors[6] = 1.0f; _pm_colors[7] = 0.0f;
_pm_colors[8] = 1.0f; _pm_colors[9] = 1.0f; _pm_colors[10] = 1.0f; _pm_colors[11] = 0.0f;
_pm_colors[12] = 1.0f; _pm_colors[13] = 1.0f; _pm_colors[14] = 1.0f; _pm_colors[15] = 0.0f;
_pm_tex_coords[0] = 0.0f; _pm_tex_coords[1] = pm_height;
_pm_tex_coords[2] = 0.0f; _pm_tex_coords[3] = 0.0f;
_pm_tex_coords[4] = pm_width; _pm_tex_coords[5] = 0.0f;
_pm_tex_coords[6] = pm_width; _pm_tex_coords[7] = pm_height;
_pm_normals[0] = 0.0f; _pm_normals[1] = 0.0f; _pm_normals[2] = 0.0f;
_pm_normals[3] = 0.0f; _pm_normals[4] = 0.0f; _pm_normals[5] = 0.0f;
_pm_normals[6] = 0.0f; _pm_normals[7] = 0.0f; _pm_normals[8] = 0.0f;
_pm_normals[9] = 0.0f; _pm_normals[10] = 0.0f; _pm_normals[11] = 0.0f;
glGenVertexArrays(1, &_vao_id[0]); // generate VAO
glBindVertexArray(_vao_id[0]); // bind VAO
// vertices
glEnableVertexAttribArray((GLuint)0);
glGenBuffers(1, &_pm_vertices_buffer[0]);
glBindBuffer(GL_ARRAY_BUFFER, _pm_vertices_buffer[0]);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), _pm_vertices.get(), GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(0);
// normals (inexplicably needed even though it won't be used in the shaders)
glEnableVertexAttribArray((GLuint)1);
glGenBuffers(1, &_pm_normals_buffer[0]);
glBindBuffer(GL_ARRAY_BUFFER, _pm_normals_buffer[0]);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), _pm_normals.get(), GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(0);
// texture
glEnableVertexAttribArray((GLuint)2);
glGenBuffers(1, &_pm_tex_coords_buffer[0]);
glBindBuffer(GL_ARRAY_BUFFER, _pm_tex_coords_buffer[0]);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), _pm_tex_coords.get(), GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)2, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenTextures(1, &_pm_tex_id[0]);
glBindTexture(GL_TEXTURE_RECTANGLE, _pm_tex_id[0]);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, pm_width, pm_height,
0, GL_RGBA, GL_UNSIGNED_BYTE, _pm_image.getPixelsPtr());
glEnableVertexAttribArray(0);
// colors
glEnableVertexAttribArray((GLuint)3);
glGenBuffers(1, &_pm_colors_buffer[0]);
glBindBuffer(GL_ARRAY_BUFFER, _pm_colors_buffer[0]);
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(GLfloat), _pm_colors.get(), GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)3, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(0);
// unbind buffers
glBindVertexArray(0);
_mvp_id[0] = glGetUniformLocation(_shaders.id(), "mvpMatrix");
_pm_tex_id[0] = glGetUniformLocation(_shaders.id(), "pauseMenuTex");
// end pause menu initialization
}
void Test_World_Pause_Menu::display()
{
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
_shaders.bind();
glUniformMatrix4fv(_mvp_id[0], 1, GL_FALSE, &_mvp[0][0]);
// begin pause menu rendering
glUniform1i(_pm_tex_id[0], 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _pm_tex_id[0]);
glBindVertexArray(_vao_id[0]); // bind the VAO
// draw the contents of the bound VAO
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glBindVertexArray(0); // unbind the VAO
// end pause menu rendering
_shaders.unbind();
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
return;
}
以下是我用于此的着色器:
顶点着色器
#version 150
in vec4 in_Position;
in vec3 in_Normal;
in vec2 in_UV;
in vec4 in_Color;
uniform mat4 mvpMatrix;
smooth out vec3 vVaryingNormal;
smooth out vec2 vVaryingTexCoord;
smooth out vec4 vVaryingColor;
void main(void)
{
vVaryingNormal = in_Normal;
vVaryingTexCoord = in_UV;
vVaryingColor = in_Color;
gl_Position = mvpMatrix * in_Position;
}
片段着色器
#version 150
smooth in vec3 vVaryingNormal;
smooth in vec2 vVaryingTexCoord;
smooth in vec4 vVaryingColor;
uniform sampler2DRect pauseMenuTex;
out vec4 out_Color;
void main(void)
{
out_Color.a = vVaryingColor.a;
out_Color += texture(pauseMenuTex, vVaryingTexCoord);
}
我的猜测是我没有在这里某处正确关闭一些纹理状态,但就像我说的,我没有尝试修复这个问题。 如有必要,我可以在程序的其他部分发布代码。
编辑:在这个C ++代码中肯定有一些错误的API使用,以及第一个纹理的代码,因为当我删除第一个纹理的初始化和渲染函数时,第二个显示得很好。 有人可以帮助我查明我错误的OpenGL用法(可能是在构造函数中)。
另一个编辑:经过进一步调查,我发现两个对象的构造函数中的哪一个最先运行的都是在两个显示例程中都显示纹理的那个。
3rd编辑:可能相关的东西:在构造函数中调用glTexImage2D()后,将第一个纹理与glBindTexture(GL_TEXTURE_RECTANGLE,0)解绑,导致它在两个显示例程中的任何一个中都不显示。 对我来说,这似乎是一个问题,它可能与我的其他问题有关。
你的问题就在这里:
glGenTextures(1, &_pm_tex_id[0]);
...
_pm_tex_id[0] = glGetUniformLocation(_shaders.id(), "pauseMenuTex");
第一条语句创建一个纹理对象并将其存储到_pm_tex_id[0]
。 下一个语句用统一的位置覆盖纹理对象。 因此,你失去了纹理对象。 调用new
获取一个指针,然后重写该指针也没什么两样。 你无法取回它。
你的代码在你的修改后的解决方案中“起作用”的原因是你保持它与上下文绑定(在不同的插槽中)。 你绑定它来填充数据,但你永远不会解除绑定它。 因此,上下文仍然包含您遗失的纹理对象。
您需要将纹理名称和采样器统一位置分开存储。 您应该使用比“id”更好的命名约定; 统一的位置不应该具有与OpenGL对象名称相同的命名约定。 这样,你不会混淆他们。 我建议“统一”而不是“身份证”。
其他没有错的东西,只是不一定有用。
你经常打电话给:
glEnableVertexAttribArray(0);
没原因。 与第一次启用属性0相比,不能启用属性0;)
你还分配了很多1个项目的数组。 这真的没有必要。 如果你只想要一个VAO,只需制作一个GLuint
变量。 当你需要生成它时,请把它的地址。
此外,停止分配这么多的记忆期。 如果你需要一个数组,可以使用一个std::vector
(你可以用&vec[0]
你现在一样的方式获得一个指向数组的指针: &vec[0]
)。 这样,您不必记得删除内存; 当对象被销毁时,C ++会为你做。 你已经在使用C ++了,所以你不妨使用这种语言。
我看到一个绑定到GL_TEXTURE_RECTANGLE,并且稍后绑定到GL_TEXTURE_2D。 这些应该是一样的吗?
首先,我没有足够的声望发表评论,如果这不起作用,我不想编辑你的问题,因为我提前表示道歉。
您的解决方案(或解决方法)为每个纹理提供了自己的纹理槽,除非您想将多个纹理传递给相同的着色器,否则不应该这样做,所以肯定会发生冲突。
你可以删除glUniform1i(_pm_tex_id[0], x);
从渲染过程中,并将其放入构造函数中,因为它只需在着色器程序(重新)创建后设置一次。
Tim在发现不同的绑定调用后,是否改变了这一点? 形成OpenGl文档:
一旦创建,命名纹理可以根据需要重新绑定到其相同的原始目标 。
我肯定会改变他们,所以他们都是相同的(我会去GL_TEXTURE_2D)。
你是否正在进行与其他地方纹理相关的任何其他GL_ *调用? 因为在第一个对象被绘制之后,这样的气味仍然像一个陈旧的参数。 希望这有些帮助。
链接地址: http://www.djcxy.com/p/6549.html