在工作精灵系统中添加实例的问题
Issues adding instancing to a working sprite system
我试图在我的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;
}
Load -准备绘制的所有精灵,调用一次。
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);
}
不呈现任何内容的原因可能有很多。变换的问题,坐标超出范围等。但是与实例化相关的一件事在发布的代码中肯定看起来是错误的:
glBindVertexArray(0);
glVertexAttribDivisor(positionBuffer, 0);
glVertexAttribDivisor(texCoordsBuffer, 1);
glVertexAttribDivisor(colorBuffer, 1);
...
glVertexAttribDivisor()
的第一个参数是顶点属性的位置,而不是缓冲区的名称。此外,这个调用设置的状态是VAO状态的一部分,因此您应该在VAO仍然绑定时进行这些调用。
所以调用应该是这样的:
glVertexAttribDivisor(0, 0);
glVertexAttribDivisor(1, 0);
glVertexAttribDivisor(2, 1);
...
glBindVertexArray(0);
,其中glVertexAttribDivisor()
的第一个参数与您也用作glVertexAttribPointer()
和glEnableVertexAttribArray()
的第一个参数的位置值相匹配。
纹理坐标的除数值(属性1)应该最有可能是0,因为你希望纹理坐标被设置为每个顶点,就像位置一样。对于颜色和其他其他属性,1是正确的值,以便它们在每个实例中应用。
另外,正如我在评论中提到的,你可能还想使用点精灵。虽然它们不能提供与绘制单个四边形相同的灵活性,但它们通常可以用于精灵。对于点精灵,每个精灵只需要一个顶点,并且纹理坐标会自动生成。我在这里给出了一个关于如何使用点精灵的大纲,包括如何应用纹理:在现代OpenGL中渲染大的圆形点。
- C++ std::function 对于类 exept 的所有实例都是空的(只有 Visual2019 编译器问题)
- 在另一个类中创建类实例时出现问题
- 为什么我的类电影在创建电影实例时遇到问题?
- 在C++中将类实例添加到对象层次结构中的问题
- 在抛出 'std::invalid_argument' 的实例后终止调用 what(): stoi (找不到问题所在)
- 错误 C2280 / 在 std::vector 中实例化对象时复制构造函数出现问题?
- C++程序问题:抛出'std::invalid_argument'实例后终止调用
- 显式模板实例化问题
- 在 x86 32 位上的静态类实例中解决此问题
- 分割故障 - 遇到问题,创建新的数组实例
- 关于QLIST类型实例复制构造函数的一个奇怪问题
- 如何理解C++并发操作中同类实例导致死锁的问题
- 创建 QQuickItem 子类的实例是否有问题,我不打算渲染或添加到 QML 树中的实例?
- 创建'new'实例可以解决析构函数崩溃问题?
- 实例化函数模板的编译问题
- 从结构实例调用变量语法问题C++
- CPP-Netlib 问题,在抛出 'boost::exception_detail::clone_impl 的实例后调用终止
- 模板函数实例化的可移植性问题
- 实例变量列表中的对象未被保留?指针问题
- 由于静态库导致的单例多实例问题