【发布时间】:2016-07-28 05:54:38
【问题描述】:
所以我目前正在使用带有 OpenGL (glew) 的 SDL2 制作游戏,并使用 SOIL 加载图像,并且我正在使用带有顶点数组对象和着色器等的现代 opengl 技术。我目前正在尝试仅向窗口渲染纹理,但我似乎无法做到。我查看了许多教程和解决方案,但我似乎无法理解我应该如何正确地做到这一点。我不确定是着色器问题还是我的代码本身。我将在下面发布所有必要的代码,如果需要更多代码,我很乐意提供。欢迎任何答案和解决方案。对于未来的上下文,为了方便起见,我有一个类用于存储 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这样的内置插件在核心配置文件中不可用。 -
@RetoKoradi 好吧,如果我从 glFragColor 中删除 texColor 变量,(未纹理化的)多边形会呈现为我设置的颜色,但是一旦我添加了 texColor 变量,就什么也不会呈现。关于着色器,它们不会编译失败,它仍然可以工作,我认为内置插件根本没有做任何事情。我删除了内置插件(以及一秒钟的 texColor 变量以使多边形渲染)并且一切正常,所以我将删除它们,因为它们什么都不做。
-
在插入任何数据之前调用
glGenerateMipmap很奇怪,但这应该不是问题,因为您实际上并没有使用mipmap。检查SOIL_load_image是否返回非空指针,imagew和imagew的值是否正确? -
@PeterT 奇怪吗?就像我说的那样,我不完全确定自己在做什么,因为我通常发现教程没有解释什么时候调用事物以及为什么我当时调用它们。好吧,我不完全确定如何检查它是否返回 nullptr,我想我确定我可以弄清楚,但我检查了 imagew 和 imageh,它们是调用 @ 后图像文件的正确值987654331@,所以我可以肯定地假设它正在正确加载图像,至少我认为。