I'm trying to implement instancing into my 2d Game Engine so that it can support particle systems without losing any performance. My class, ISprite, is derived from a working Sprite class. I just went through and removed all the functionality affecting single sprites and replaced it with an instancing plan in mind. Unfortunately, nothing is drawing on the screen.
Here is the relevant information:
Vertex Shader
#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;
}
Fragment Shader
#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 - Prepares all sprites for drawing, called once.
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 - called by each sprite, each frame. Sends data to static vectors
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);
}
Draw Sprites - called once each frame, actually draws the sprites
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);
}