我正在使用SDL2和OpenGL(glew)制作游戏,并使用SOIL加载图像,同时使用现代OpenGL技术,包括顶点数组对象和着色器等。我尝试将纹理渲染到窗口中,但好像无法成功。我查看了很多教程和解决方案,但似乎无法正确理解应该如何做。我不确定是着色器有问题还是代码本身有问题。以下是所有必要的代码,如果需要更多代码,我会很乐意提供。欢迎任何答案和解决方案。为了以后的上下文,我有一个用于存储VAO数据的类,以便于使用。以下是加载纹理的代码:
这是我的顶点着色器代码:
这是我的片段着色器:
最后,这里是一段代码,用于在加载着色器时正确引用我使用的VAO属性指针:
void PXSprite::loadSprite() {
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
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);
glGenerateMipmap(GL_TEXTURE_2D);
int imagew, imageh;
//The path is a class variable, and I haven't received any errors from this function, so I can only assume it's getting the texture file correctly.
unsigned char* image = SOIL_load_image(path.c_str(), &imagew, &imageh, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imagew, imageh, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
//Don't worry about this code. It's just to keep the buffer object data.
//It works properly when rendering polygons.
spriteVAO.clear();
spriteVAO.addColor(PXColor::WHITE());
spriteVAO.addColor(PXColor::WHITE());
spriteVAO.addColor(PXColor::WHITE());
spriteVAO.addColor(PXColor::WHITE());
spriteVAO.addTextureCoordinate(0, 0);
spriteVAO.addTextureCoordinate(1, 0);
spriteVAO.addTextureCoordinate(1, 1);
spriteVAO.addTextureCoordinate(0, 1);
glGenVertexArrays(1, &spriteVAO.vaoID);
glGenBuffers(1, &spriteVAO.posVBOid);
glBindBuffer(GL_ARRAY_BUFFER, spriteVAO.posVBOid);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*12, nullptr, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, &spriteVAO.colVBOid);
glBindBuffer(GL_ARRAY_BUFFER, spriteVAO.colVBOid);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, &spriteVAO.colors[0], GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, &spriteVAO.texVBOid);
glBindBuffer(GL_ARRAY_BUFFER, spriteVAO.texVBOid);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, &spriteVAO.texCoords[0], GL_STATIC_DRAW);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
这是我用于渲染纹理的代码:
void PXSprite::render(int x, int y) {
spriteVAO.clear(PXVertexArrayObject::positionAttributeIndex);
spriteVAO.addPosition(x, y);
spriteVAO.addPosition(x+width, y);
spriteVAO.addPosition(x, y+height);
spriteVAO.addPosition(x+width, y+height);
glBindTexture(GL_TEXTURE_2D, textureID);
glBindVertexArray(spriteVAO.vaoID);
glBindBuffer(GL_ARRAY_BUFFER, spriteVAO.posVBOid);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat)*12, &spriteVAO.positions[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindTexture(GL_TEXTURE_2D, 0);
}
这是我的顶点着色器代码:
#version 330 core
in vec3 in_Position;
in vec4 in_Color;
in vec2 in_TexCoord;
out vec4 outPosition;
out vec4 outColor;
out vec2 outTexCoord;
void main() {
gl_Position = vec4(in_Position.x, in_Position.y*-1.0, in_Position.z, 1.0);
outTexCoord = in_TexCoord;
outColor = in_Color;
}
这是我的片段着色器:
#version 330 core
in vec2 outTexCoord;
in vec4 outColor;
out vec4 glFragColor;
out vec4 glTexColor;
uniform sampler2D pxsampler;
void main() {
vec4 texColor = texture(pxsampler, outTexCoord);
//This outputs the color of polygons if I don't multiply outColor by texColor, but once I add texColor, no colors show up at all.
glFragColor = texColor*outColor;
}
最后,这里是一段代码,用于在加载着色器时正确引用我使用的VAO属性指针:
glBindAttribLocation(ProgramID, 0, "in_Position");
glBindAttribLocation(ProgramID, 1, "in_Color");
glBindAttribLocation(ProgramID, 2, "in_TexCoord");
欢迎提供任何帮助或建议。如果需要任何额外的代码,我会添加它。如果这个问题看起来有些冗余,我很抱歉,但我找不到任何可以帮助我的东西。如果有人能够向我解释渲染纹理的代码如何工作,那就太好了,因为从我读过的教程中,他们通常不解释每个部分的功能,以便我知道如何再次完成它,所以我不太清楚我正在做什么。再次感谢任何帮助。谢谢!
gl_ProjectionMatrix
在核心配置文件中不可用。 - Reto KoradiglGenerateMipmap
有点奇怪,但这应该不是问题,因为你实际上并没有使用mipmaps。你检查过SOIL_load_image
返回的非空指针以及imagew
和imagew
的值是否正确吗? - PeterTSOIL_load_image
后图像文件的正确值,所以我可以肯定它至少加载了图像,至少我认为是这样。 - GyoPXSprite::render
中的x
、y
、width
和height
的值范围是多少?我怀疑你可能在使用像素坐标,而你的顶点着色器只会传递(除了y之外),这意味着你的精灵位置必须是剪辑空间坐标(并且y可能有一些奇怪的情况)。 - datenwolf