【发布时间】:2025-12-10 08:55:02
【问题描述】:
我正在尝试在我的 2d 游戏引擎中实现实例化,以便它可以支持粒子系统而不会损失任何性能。我的类 ISprite 派生自一个有效的 Sprite 类。我刚刚完成并删除了影响单个精灵的所有功能,并用一个实例计划替换它。不幸的是,屏幕上没有任何东西。
以下是相关信息:
顶点着色器
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoords;
layout (location = 2) in vec4 colorSource;
layout (location = 3) in mat4 transform;
out vec2 TexCoords;
out vec4 Color;
uniform mat4 uniformView;
uniform mat4 uniformProjection;
void main()
{
gl_Position = uniformProjection * uniformView * transform * vec4(position, 1.0f);
TexCoords = texCoords;
Color = colorSource;
}
片段着色器
#version 330 core
in vec2 TexCoords;
in vec4 Color;
out vec4 color;
uniform sampler2D Texture;
uniform vec4 uniformColor;
void main()
{
vec4 texColor = texture(Texture, TexCoords) * Color;
if(texColor.a < 0.1)
discard;
color = texColor;
}
加载 - 为绘制准备所有精灵,调用一次。
void ISprite::Load(Shader spriteShader)
{
spriteShader.Use();
GLfloat vertices[] = {
//X Y Z
0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f
};
glGenVertexArrays(1, &vertexArray);
glGenBuffers(1, &positionBuffer);
glGenBuffers(1, &texCoordsBuffer);
glGenBuffers(1, &colorBuffer);
glGenBuffers(1, &matrixBuffer);
glBindVertexArray(vertexArray);
//The vertex data will never change, so send that data now.
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//For vertex Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (GLvoid*)0);
//For texture coordinates
glBindBuffer(GL_ARRAY_BUFFER, texCoordsBuffer);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GLfloat), (GLvoid*)0);
//For Color
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0);
//For Transformation Matrix
glBindBuffer(GL_ARRAY_BUFFER, matrixBuffer);
for (int i = 0; i < 4; ++i)
{
glEnableVertexAttribArray(3 + i);
glVertexAttribPointer(3 + i, 4, GL_FLOAT, GL_FALSE,
4 * 4 * sizeof(GLfloat), (GLvoid*)(4 * i * sizeof(GLfloat)));
}
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, texCoordsBuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBindBuffer(GL_ARRAY_BUFFER, matrixBuffer);
glBindVertexArray(0);
glVertexAttribDivisor(positionBuffer, 0);
glVertexAttribDivisor(texCoordsBuffer, 1);
glVertexAttribDivisor(colorBuffer, 1);
glVertexAttribDivisor(matrixBuffer, 1);
glVertexAttribDivisor(matrixBuffer + 1, 1);
glVertexAttribDivisor(matrixBuffer + 2, 1);
glVertexAttribDivisor(matrixBuffer + 3, 1);
ISprite::shader = &spriteShader;
}
Prepare Draw - 由每个精灵、每一帧调用。将数据发送到静态向量
void ISprite::prepareDraw(void)
{
//Adds their personal data to vectors shared by class
glm::mat4 transform = calculateTransorm();
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
ISprite::transformMatrices.push_back(transform[i][j]);
}
texture.updateAnimation();
for (int i = 0; i < 12; ++i)
ISprite::textureCoordinatesAll.push_back(texture.textureCoordinates[i]);
ISprite::colorValues.push_back(color.x);
ISprite::colorValues.push_back(color.y);
ISprite::colorValues.push_back(color.z);
ISprite::colorValues.push_back(color.w);
}
绘制精灵 - 每帧调用一次,实际绘制精灵
void ISprite::drawSprites(Texture testTexture)
{
shader->Use();
for (std::vector<ISprite*>::iterator it = Isprites.begin(); it != Isprites.end(); ++it)
(*it)->prepareDraw();
glBindVertexArray(vertexArray);
glBindTexture(GL_TEXTURE_2D, testTexture.ID);
//Bind texture here if you want textures to work. if not, a single texture atlas will be bound
glBindBuffer(GL_ARRAY_BUFFER, texCoordsBuffer);
glBufferData(GL_ARRAY_BUFFER, textureCoordinatesAll.size() * sizeof(GLfloat),
textureCoordinatesAll.data(), GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ARRAY_BUFFER, colorValues.size() * sizeof(GLfloat),
colorValues.data(), GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, matrixBuffer);
glBufferData(GL_ARRAY_BUFFER, transformMatrices.size() * sizeof(GLfloat),
transformMatrices.data(), GL_STREAM_DRAW);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 6, Isprites.size());
textureCoordinatesAll.clear();
colorValues.clear();
transformMatrices.clear();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindVertexArray(0);
}
【问题讨论】:
-
没有直接解决您的代码问题,但是您是否有理由为每个精灵绘制一个四边形,而不是使用点精灵?除非它不能满足您的需求,否则这似乎更容易、更有效。
-
嗯,我想把纹理放在四边形上。我真的没有充分的理由按照我的方式做事。所有这些原因都将是“他们在 learnopenGL.com 上就是这样做的”
-
您可以将纹理应用于点精灵。我在这里的回答概述了如何做到这一点:*.com/questions/27098315/….