【发布时间】:2017-05-12 11:49:23
【问题描述】:
在我使用 opengl 4.5 的 Windows 计算机上,我似乎无法让我的纹理出现在屏幕上。我收到的只是黑屏。对于我的代码,我首先开发了一个小的 Vector 类来容纳所有顶点属性信息:
Vector3D.h
struct Position
{
Position();
Position(float x, float y, float z);
float x;
float y;
float z;
};
Position::Position()
{}
Position::Position(float x, float y, float z) :
x(x), y(y), z(z)
{}
struct Color
{
GLubyte r;
GLubyte g;
GLubyte b;
GLubyte a;
};
struct TextureCoordinate
{
float u;
float v;
};
struct Vector3D
{
Vector3D();
Vector3D(float x, float y, float z);
Position position;
Color color;
TextureCoordinate textCoordinate;
void setUV(float u, float v);
};
Vector3D::Vector3D()
{}
Vector3D::Vector3D(float x, float y, float z) :
position(x, y, z)
{}
void Vector3D::setUV(float u, float v)
{
this->textCoordinate.u = u;
this->textCoordinate.v = v;
}
然后我有一个精灵类,通过它我使用 Init() 函数初始化顶点属性:
Sprite.cpp
void Sprite::Init(float x, float y, float width, float height)
{
this->x = x;
this->y = y;
this->width = width;
this->height = height;
if (vboID == 0)
glGenBuffers(1, &vboID);
Vector3D vertexData[6]{
Vector3D {x + width, y + height, 1.0f},
Vector3D {x, y + height, 1.0f },
Vector3D {x, y, 1.0f},
Vector3D {x, y, 1.0f},
Vector3D {x + width, y, 1.0f},
Vector3D {x + width, y + height, 1.0f},
};
for (int i = 0; i < 6; ++i)
{
vertexData[i].color.r = 0;
vertexData[i].color.g = 155;
vertexData[i].color.b = 200;
};
vertexData[0].setUV(1.0f, 1.0f);
vertexData[1].setUV(0.0f, 1.0f);
vertexData[2].setUV(0.0f, 0.0f);
vertexData[3].setUV(0.0f, 0.0f);
vertexData[4].setUV(1.0f, 0.0f);
vertexData[5].setUV(1.0f, 1.0f);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
然后我在 sprite 类中有绘制函数,它显然会重新绑定以纠正 VBO 并绘制图像:
Sprite.cpp
void Sprite::Draw()
{
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3D), (void*)offsetof(Vector3D, position));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vector3D), (void*)offsetof(Vector3D, textCoordinate));
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
最后,我在这里的 main 函数中调用上面的所有内容(我还使用 SDL 和图像加载库 stb):
main.cpp
int main(int agrc, char** argv)
{
window.Initialize();
playerSprite.Init(-1.0f, -1.0f, 1.0f, 1.0f);
GameState gamestate{ GameState::PLAY };
SDL_Event evnt;
int32 x, y, currentChannels;
int32 forceChannels = 4;
uchar8* imageData = 0;
imageData = stbi_load("CharImage.png", &x, &y, ¤tChannels, forceChannels);
if (imageData == nullptr)
{
LOG("ERROR: Could not load image file!");
};
GLuint texture;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
glTextureParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTextureParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTextureParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTextureParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Blz::OpenGL::ShaderProgram colorShaderProgram;
colorShaderProgram.Compile();
colorShaderProgram.Link();
colorShaderProgram.Bind();
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
while (gamestate != GameState::EXIT)
{
unsigned int startTime = SDL_GetTicks();
//Game Logic Update
while (SDL_PollEvent(&evnt))
{
switch (evnt.type)
{
case SDL_QUIT:
gamestate = GameState::EXIT;
default:
break;
}
}
window.ClearBuffers();
playerSprite.Draw();
window.SwapBuffers();
}
return 0;
}
另外,这是我的着色器:
顶点着色器
#version 430
layout(location=0) in vec3 vertexPosition;
layout(location=1) in vec2 textCoord;
out vec2 TextureCoord;
void main()
{
gl_Position = vec4(vertexPosition, 1.0f);
TextureCoord = textCoord;
};
片段着色器
#version 430
out vec4 daColor;
in vec2 TextureCoord;
uniform sampler2D basicTexture;
void main()
{
vec4 texel = texture(basicTexture, TextureCoord);
daColor = texel;
};
【问题讨论】:
-
查看
sizeof(vertexData)在glBufferData()使用的错误号码。它必须是传递给 glBufferData 的数据大小(以字节为单位)。 -
而 sizeof(vertexData) 返回 144 数组中的字节数是否正确?
-
144 是结构的大小,而不是整个数据数组。 GL 对您的结构一无所知, glBufferData 只获取字节。您可以根据数据布局计算大小。另外,同样,查看如何读取缓冲区 (glVertexAttribPointer)
-
@Ripi2
struct Vector3D有 6 个浮点数,长度为 6*4 = 24 个字节。使用 6 个元素的向量,我们总共有 144 个字节 -
好吧,我会说之前我已经使用上面相同的代码将带有颜色数据的顶点位置发送到 opengl,并得到一个显示正确颜色的正方形。这让我觉得 glbufferdata 和 glvertexattribpointer 设置正确?