[英]Textured triangles with OpenGL using VBO/IBO
我正在尝试使用一个VBO绘制两个带纹理的三角形,以形成一个正方形,该VBO包含屏幕上的坐标和纹理的坐标以及带有索引的IBO。 但是我遇到了一个问题。 在不使用着色器的情况下,无论如何尝试,我都能获得两个三角形的正确大小和位置,但没有纹理。 使用着色器时,我得到了纹理,但是三角形的尺寸错误,位置错误并且没有以任何方式使用纹理坐标。
创建纹理
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0,
texture_format, GL_UNSIGNED_BYTE, surface->pixels);
glBindTexture(GL_TEXTURE_2D, NULL);
填充VBO和IBO (TileData是具有两个大小为2的数组的结构)
indices.push_back(0);
indices.push_back(1);
indices.push_back(2);
indices.push_back(0);
indices.push_back(2);
indices.push_back(3);
TileData tile;
tile.texCoord[0] = 0 / imageSizeX;
tile.texCoord[1] = 0 / imageSizeY;
tile.worldCoord[0] = 0;
tile.worldCoord[1] = 0;
tiles.push_back(tile);
tile.texCoord[0] = (0 + texWidth) / imageSizeX;
tile.texCoord[1] = 0 / imageSizeY;
tile.worldCoord[0] = 0 + texWidth;
tile.worldCoord[1] = 0;
tiles.push_back(tile);
tile.texCoord[0] = (0 + texWidth) / imageSizeX;
tile.texCoord[1] = (0 + texHeight) / imageSizeY;
tile.worldCoord[0] = 0 + texWidth;
tile.worldCoord[1] = 0 + texHeight;
tiles.push_back(tile);
tile.texCoord[0] = 0 / imageSizeX;
tile.texCoord[1] = (0 + texHeight) / imageSizeY;
tile.worldCoord[0] = 0;
tile.worldCoord[1] = 0 + texHeight;
tiles.push_back(tile);
这给出的代码给了我世界坐标和纹理坐标:
0, 0 0, 0
16, 0 0.25, 0
16, 16 0.25, 1
0, 16 0, 1
生成我的缓冲区
glGenBuffers(1, &vboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, tiles.size() * sizeof(TileData), &tiles[0], GL_STATIC_DRAW);
glGenBuffers(1, &iboID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
带着色器的绘图功能
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(camera.x, camera.x + 320, camera.y + 240, camera.y, -1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderHandler.programID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
GLint texLocation = glGetUniformLocation(shaderHandler.programID, "tex");
glUniform1i(texLocation, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(CGame::TileData), (GLvoid *)0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(CGame::TileData), (GLvoid*)offsetof(CGame::TileData, CGame::TileData::worldCoord));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
glDrawElements(GL_TRIANGLES, indices->size(), GL_UNSIGNED_INT, (GLvoid*)0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindTexture(GL_TEXTURE_2D, 0);
SDL_GL_SwapWindow(window);
结果 与着色器
没有着色器的绘图功能 (如果我取消链接着色器程序 ,上面的代码也可以获得与这一结果相同的结果)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexPointer(2, GL_FLOAT, sizeof(CGame::TileData), (GLvoid*)0);
glTexCoordPointer(2, GL_FLOAT, sizeof(CGame::TileData), (GLvoid*)offsetof(CGame::TileData, CGame::TileData::worldCoord));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
glDrawElements(GL_TRIANGLES, indices->size(), GL_UNSIGNED_INT, (GLvoid*)0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
SDL_GL_SwapWindow(window);
Resulst 没有着色器
顶点着色器
#version 330
layout(location = 0) in vec2 vert;
layout(location = 1) in vec2 vertTexCoord;
out vec2 fragTexCoord;
void main()
{
fragTexCoord = vertTexCoord;
gl_Position = vec4(vert, 0, 1);
}
片段着色器
#version 330
uniform sampler2D tex;
in vec2 fragTexCoord;
out vec4 finalColor;
void main()
{
finalColor = texture2D(tex, fragTexCoord);
}
在这一点上,我不知道如何继续。 在这里或任何地方,找不到任何对我有帮助的东西。 我已经做了很多尝试,以至于我可能使用了不赞成使用的功能或执行了不受支持的操作,但我不知道该怎么做。
我可以看到几个问题:
在固定函数中,必须显式调用glEnable(GL_TEXTURE_2D)
告诉GL应应用当前绑定的2D纹理(每个纹理单元分别使用)。
顶点着色器永远不会根据变换状态来变换顶点。 不推荐使用所有与矩阵相关的GL函数,例如glOrtho
, glTranslate
, glMatrixMode
。 您必须使用自己的矩阵函数(或类似glm的库),并通过统一方式(或其他方式)将矩阵提供给着色器。 在兼容性配置文件中,您还可以使用GLSL内置制服,该制服允许您访问使用那些不推荐使用的功能设置的旧内置矩阵,但是我强烈建议不要依赖不推荐使用的功能。 无论哪种情况,着色器都必须实际应用顶点和modelview转换,通常可以归结为矩阵向量乘积,例如projection * modelView * vec4(pos,1)
。
至少可以说,您的属性指针很奇怪。 顶点位置使用偏移量0, 纹理坐标使用offsetof(...::worldCoord)
偏移量。 现在,根据定义成员的顺序,这两个成员都可能指向内存中完全相同的值,这将解释您提到的“并且不以任何方式使用纹理坐标”部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.