opengl 2d 游戏只绘制第二个精灵纹理而不是第一个
opengl 2d game only drawing second sprite texture and not first
我目前正在使用 OpenGL 创建一个 2d 格斗游戏,我遇到了一个问题 运行 OpenGL 只在我最后一次初始化的精灵位置上绘制,不管我初始化并尝试绘制了多少精灵.即使我初始化 sprite1
和 sprite2
但只绘制 sprite1
,sprite
仍然会被绘制。它从我的 sprite class 开始,我在屏幕上初始化我想要我的图像的位置以及要使用的图像:
Sprite.cpp
Init(int screenCoordinateX, int screenCoordinateY, uint imageWidth, unsigned int imageHeight, std::string imageFilePath)
{
//casting to float since GLSL shader variables vec2,3,4 require vertex data to be in floats
this->x = static_cast<float>(x);
this->y = static_cast<float>(y);
this->width = static_cast<float>(width);
this->height = static_cast<float>(height);
glGenBuffers(1, &vboID);
Blz::Graphics::GLTexture texture(imageFilePath);
this->texture = texture;
float halfWidth = this->width / 2;
//Setting sprite origin at bottom middle of image by subtracting half width
this->vertexData.at(0).SetPosition(glm::vec3{ this->x + (this->width - halfWidth), this->y + this->height, 0.0f });//Top right corner
this->vertexData.at(1).SetPosition(glm::vec3{ this->x - halfWidth, this->y + height, 0.0f });//Top left corner
this->vertexData.at(2).SetPosition(glm::vec3{ this->x - halfWidth, this->y, 0.0f });//Bottom left corner
this->vertexData.at(3).SetPosition(glm::vec3{ this->x - halfWidth, this->y, 0.0f });//Bottom left corner
this->vertexData.at(4).SetPosition(glm::vec3{ this->x + (this->width - halfWidth), this->y, 0.0f });//Bottom right corner
this->vertexData.at(5).SetPosition(glm::vec3{ this->x + (this->width - halfWidth), this->y + this->height, 0.0f });//Top right corner
this->vertexData.at(0).SetUV(glm::vec2{ 1.0f, 1.0f });
this->vertexData.at(1).SetUV(glm::vec2{ 0.0f, 1.0f });
this->vertexData.at(2).SetUV(glm::vec2{ 0.0f, 0.0f });
this->vertexData.at(3).SetUV(glm::vec2{ 0.0f, 0.0f });
this->vertexData.at(4).SetUV(glm::vec2{ 1.0f, 0.0f });
this->vertexData.at(5).SetUV(glm::vec2{ 1.0f, 1.0f });
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, (sizeof(Vector3D) * this->vertexData.size()), &this->vertexData.front(), GL_STATIC_DRAW);
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, textureCoordinates));
//Unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
然后我尝试像这样渲染传递给渲染器的精灵:
Renderer.cpp
void Renderer::Draw(Sprite& sprite)
{
glm::mat4 orthoProjection = glm::ortho(0.0f, static_cast<sfloat>(1024), 0.0f, static_cast<sfloat>(768));
GLuint transformationMatrixUniformLocation = this->shaderProgram.GetUniformLocation("transformationMatrix");
glUniformMatrix4fv(transformationMatrixUniformLocation, 1, GL_FALSE, &(orthoProjection[0][0]));
glBindTexture(GL_TEXTURE_2D, sprite.texture.id);
glBindBuffer(GL_ARRAY_BUFFER, sprite.vboID);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
这是我的 main.cpp 我开始调用所有内容的地方:
int main()
{
Blz::Graphics::Renderer renderer;
Blz::Window window;
Blz::Input input;
Scene scene;
window.Initialize();
renderer.Init();
Sprite sprite1;
sprite.Init(900, 300, 200, 200, "CharImage.png");
Sprite sprite2;
sprite2.Init(100, 100, 200, 200, "CharImage.png");
while (!input.IsKeyPressed(SDLK_ESCAPE))
{
window.ClearBuffers();
renderer.Draw(sprite1);
window.SwapBuffers();
}
return 0;
}
因此,即使我要求绘制 sprite1
,屏幕上也只会绘制 100x 100y 的 sprite2
位置。即使我手动尝试在 renderer.cpp 中输入 1 的 vboID
(即 sprite1
的 vboID
),它仍然绘制 sprite2
的位置。我做错了什么?
如有必要,这是我的着色器:
VertexShader.glsl
#version 430
in vec3 vertexPosition;
in vec2 textCoord;
out vec2 TextureCoord;
uniform mat4 transformationMatrix;
void main()
{
vec4 position = vec4(vertexPosition, 1.0f);
gl_Position = transformationMatrix * position;
TextureCoord = textCoord;
};
FragmentShader.glsl
#version 430
out vec4 daColor;
in vec2 TextureCoord;
uniform sampler2D basicTexture;
void main()
{
vec4 texel = texture(basicTexture, TextureCoord);
daColor = texel;
};
所以我想这对任何有志于学习和使用 OpenGL 的人来说都是一堂课。任何时候您使用 VBO 和 vbo id 绑定 OpenGL 缓冲区,您还需要在绘制之前再次指定您的顶点属性指针。所以我的新 renderer.cpp 文件如下所示:
void Renderer::Draw(Sprite& sprite)
{
glm::mat4 orthoProjection = glm::ortho(0.0f, static_cast<sfloat>(1024), 0.0f, static_cast<sfloat>(768));
GLuint transformationMatrixUniformLocation = this->shaderProgram.GetUniformLocation("transformationMatrix");
glUniformMatrix4fv(transformationMatrixUniformLocation, 1, GL_FALSE, &(orthoProjection[0][0]));
glBindTexture(GL_TEXTURE_2D, sprite.texture.id);
glBindBuffer(GL_ARRAY_BUFFER, sprite.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, textureCoordinates));
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
另一个 SO 答案给出了原因:is VertexAttribPointer needed after each BindBuffer?。为避免这种情况,您可以使用较新的 VAO,它存储顶点属性信息,这样您就不必每次都指定 vertexattribpointer 函数。
我目前正在使用 OpenGL 创建一个 2d 格斗游戏,我遇到了一个问题 运行 OpenGL 只在我最后一次初始化的精灵位置上绘制,不管我初始化并尝试绘制了多少精灵.即使我初始化 sprite1
和 sprite2
但只绘制 sprite1
,sprite
仍然会被绘制。它从我的 sprite class 开始,我在屏幕上初始化我想要我的图像的位置以及要使用的图像:
Sprite.cpp
Init(int screenCoordinateX, int screenCoordinateY, uint imageWidth, unsigned int imageHeight, std::string imageFilePath)
{
//casting to float since GLSL shader variables vec2,3,4 require vertex data to be in floats
this->x = static_cast<float>(x);
this->y = static_cast<float>(y);
this->width = static_cast<float>(width);
this->height = static_cast<float>(height);
glGenBuffers(1, &vboID);
Blz::Graphics::GLTexture texture(imageFilePath);
this->texture = texture;
float halfWidth = this->width / 2;
//Setting sprite origin at bottom middle of image by subtracting half width
this->vertexData.at(0).SetPosition(glm::vec3{ this->x + (this->width - halfWidth), this->y + this->height, 0.0f });//Top right corner
this->vertexData.at(1).SetPosition(glm::vec3{ this->x - halfWidth, this->y + height, 0.0f });//Top left corner
this->vertexData.at(2).SetPosition(glm::vec3{ this->x - halfWidth, this->y, 0.0f });//Bottom left corner
this->vertexData.at(3).SetPosition(glm::vec3{ this->x - halfWidth, this->y, 0.0f });//Bottom left corner
this->vertexData.at(4).SetPosition(glm::vec3{ this->x + (this->width - halfWidth), this->y, 0.0f });//Bottom right corner
this->vertexData.at(5).SetPosition(glm::vec3{ this->x + (this->width - halfWidth), this->y + this->height, 0.0f });//Top right corner
this->vertexData.at(0).SetUV(glm::vec2{ 1.0f, 1.0f });
this->vertexData.at(1).SetUV(glm::vec2{ 0.0f, 1.0f });
this->vertexData.at(2).SetUV(glm::vec2{ 0.0f, 0.0f });
this->vertexData.at(3).SetUV(glm::vec2{ 0.0f, 0.0f });
this->vertexData.at(4).SetUV(glm::vec2{ 1.0f, 0.0f });
this->vertexData.at(5).SetUV(glm::vec2{ 1.0f, 1.0f });
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, (sizeof(Vector3D) * this->vertexData.size()), &this->vertexData.front(), GL_STATIC_DRAW);
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, textureCoordinates));
//Unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
然后我尝试像这样渲染传递给渲染器的精灵:
Renderer.cpp
void Renderer::Draw(Sprite& sprite)
{
glm::mat4 orthoProjection = glm::ortho(0.0f, static_cast<sfloat>(1024), 0.0f, static_cast<sfloat>(768));
GLuint transformationMatrixUniformLocation = this->shaderProgram.GetUniformLocation("transformationMatrix");
glUniformMatrix4fv(transformationMatrixUniformLocation, 1, GL_FALSE, &(orthoProjection[0][0]));
glBindTexture(GL_TEXTURE_2D, sprite.texture.id);
glBindBuffer(GL_ARRAY_BUFFER, sprite.vboID);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
这是我的 main.cpp 我开始调用所有内容的地方:
int main()
{
Blz::Graphics::Renderer renderer;
Blz::Window window;
Blz::Input input;
Scene scene;
window.Initialize();
renderer.Init();
Sprite sprite1;
sprite.Init(900, 300, 200, 200, "CharImage.png");
Sprite sprite2;
sprite2.Init(100, 100, 200, 200, "CharImage.png");
while (!input.IsKeyPressed(SDLK_ESCAPE))
{
window.ClearBuffers();
renderer.Draw(sprite1);
window.SwapBuffers();
}
return 0;
}
因此,即使我要求绘制 sprite1
,屏幕上也只会绘制 100x 100y 的 sprite2
位置。即使我手动尝试在 renderer.cpp 中输入 1 的 vboID
(即 sprite1
的 vboID
),它仍然绘制 sprite2
的位置。我做错了什么?
如有必要,这是我的着色器:
VertexShader.glsl
#version 430
in vec3 vertexPosition;
in vec2 textCoord;
out vec2 TextureCoord;
uniform mat4 transformationMatrix;
void main()
{
vec4 position = vec4(vertexPosition, 1.0f);
gl_Position = transformationMatrix * position;
TextureCoord = textCoord;
};
FragmentShader.glsl
#version 430
out vec4 daColor;
in vec2 TextureCoord;
uniform sampler2D basicTexture;
void main()
{
vec4 texel = texture(basicTexture, TextureCoord);
daColor = texel;
};
所以我想这对任何有志于学习和使用 OpenGL 的人来说都是一堂课。任何时候您使用 VBO 和 vbo id 绑定 OpenGL 缓冲区,您还需要在绘制之前再次指定您的顶点属性指针。所以我的新 renderer.cpp 文件如下所示:
void Renderer::Draw(Sprite& sprite)
{
glm::mat4 orthoProjection = glm::ortho(0.0f, static_cast<sfloat>(1024), 0.0f, static_cast<sfloat>(768));
GLuint transformationMatrixUniformLocation = this->shaderProgram.GetUniformLocation("transformationMatrix");
glUniformMatrix4fv(transformationMatrixUniformLocation, 1, GL_FALSE, &(orthoProjection[0][0]));
glBindTexture(GL_TEXTURE_2D, sprite.texture.id);
glBindBuffer(GL_ARRAY_BUFFER, sprite.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, textureCoordinates));
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
另一个 SO 答案给出了原因:is VertexAttribPointer needed after each BindBuffer?。为避免这种情况,您可以使用较新的 VAO,它存储顶点属性信息,这样您就不必每次都指定 vertexattribpointer 函数。