Witam! Obejrzałem i postanowiłem zastosować ten system w mojej aplikacji. Niestety zamiast 300 fpsów przy 60 tysiącach spritów, ja mam 20.
enum
{
RENDERER_MAX_SPRITES = 60000,
RENDERER_SPRITE_SIZE = sizeof(Vertex) * 4,
RENDERER_BUFFER_SIZE= RENDERER_SPRITE_SIZE * RENDERER_ MAX_SPRITES,
RENDERER_INDICES_SIZE = RENDERER_MAX_SPRITES * 6,
};
class Sprite
{
public:
Sprite(const Rectangle& rectangle, const ColorRGBA& color);
~Sprite() = default;
private:
friend class Renderer2D;
Vec2 position;
Vec2 dimension;
ColorRGBA color;
};
class SpriteBatch
{
public:
SpriteBatch();
~SpriteBatch();
void Create();
void Begin();
void Draw(const Sprite* sprite);
void End();
void Flush();
private:
GLuint vao;
GLuint vbo;
GLuint ibo;
int indexCount;
Vertex* vertex;
void SetupIndices(GLuint* indices);
};
Sprite::Sprite(const Rectangle& rectangle, const ColorRGBA& color) :
{
position = {rectangle.x, rectangle.y};
dimension = {rectangle.w, rectangle.h};
this->color = color;
}
SpriteBatch::SpriteBatch()
{
Create();
}
SpriteBatch::~SpriteBatch()
{
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ibo);
glDeleteVertexArrays(1, &vao);
}
void SpriteBatch::Create()
{
glCreateVertexArrays(1, &vao);
glBindVertexArray(vao);
glCreateBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glNamedBufferData(vbo, RENDERER_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
glVertexArrayAttribBinding(vao, 0, 0);
glVertexArrayAttribFormat(vao, 0, 2, GL_FLOAT, GL_FALSE, 0);
glEnableVertexArrayAttrib(vao, 0);
glVertexArrayAttribBinding(vao, 1, 0);
glVertexArrayAttribFormat(vao, 1, 4, GL_FLOAT, GL_TRUE, 4 * sizeof(GLfloat)));
glEnableVertexArrayAttrib(vao, 1);
glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(Vertex));
glBindBuffer(GL_ARRAY_BUFFER, 0);
GLuint* indices = new GLuint[RENDERER_INDICES_SIZE];
SetupIndices(indices);
glCreateBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glNamedBufferData(ibo, RENDERER_INDICES_SIZE * sizeof(GLuint), indices, GL_STATIC_DRAW);
glBindVertexArray(0);
}
void SpriteBatch::Begin()
{
vertex = (Vertex*)glMapNamedBuffer(vbo, GL_WRITE_ONLY);
}
void SpriteBatch::Draw(const Sprite* sprite)
{
vertex ->position = Vec2(sprite->position.x, sprite->position.y);
vertex ->color = sprite->color;
vertex ++;
vertex ->position = Vec2(sprite->position.x, sprite->position.y + sprite->dimension.y);
vertex ->color = sprite->color;
vertex ++;
vertex ->position = Vec2(sprite->position.x + sprite->dimension.x, sprite->position.y + sprite->dimension.y);
vertex ->color = sprite->color;
vertex ++;
vertex ->position = Vec2(sprite->position.x + sprite->dimension.x, sprite->position.y);
vertex ->color = sprite->color;
vertex ++;
indexCount += 6;
spriteSize += 1;
}
void SpriteBatch::Flush()
{
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, NULL);
glBindVertexArray(0);
indexCount = 0;
}
void SpriteBatch::End()
{
glUnmapNamedBuffer(vbo);
}
void SpriteBatch::SetupIndices(GLuint* indices)
{
unsigned short offset = 0;
for (GLuinti = 0; i < RENDERER_INDICES_SIZE; i += 6)
{
indices[i] = offset + 0;
indices[i + 1] = offset + 1;
indices[i + 2] = offset + 2;
indices[i + 3] = offset + 2;
indices[i + 4] = offset + 3;
indices[i + 5] = offset + 0;
offset += 4;
}
}
int main(int argc, char* argv[])
{
Window window;
//Tworzy okno o nazwie OpenGLWindow z wymiarami 800x600 i opengl w wersji 4.6
window.CreateWindow("OpenGLWindow", 800, 600, 4, 6);
SpriteBatch spriteBatch;
Camera camera;
camera.Ortho(800.0f, 600.0f);
Shader shader("Shader.vs.glsl", "Shader.fs.glsl");
shader.UseProgram();
glClearColor(1.0, 0.0, 0.0, 1.0);
glViewport(0, 0, 800, 600);
bool quit = false;
srand(time(NULL);
std::vector<Sprite*> sprites;
for (float y = 0.0f; y < 9.0f; y += 0.05f) {
for (float x = 0.0f; x < 16.0f; x += 0.05f) {
sprites.push_back(new Sprite(Rectangle(x, y, 0.08f, 0.08f), Rectangle(0.0f, 0.0f, 1.0f, 1.0f), ColorRGBA((rand() % 1000 / 1000.0f) * 255, 0, 255, 255)));
}
}
while(!quit)
{
while(window.PollEvent())
{
if(window.Quit())
{
quit = true;
}
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.Uniform4fv(shader.getLocation("camera", camera.Matrix());
camera.Process();
spriteBatch.Begin();
for(const auto& sprite:sprites)
spriteBatch.renderer(sprite);
spriteBatch.End();
spriteBatch.Flush();
window.Update();
}
return 0;
}
w jaki sposób zyskać tak duży przyrost fpsów? Użycie starszy odpowiedników typu glMapBuffer zamist glMapNamedBuffer niczego nie zmienia. FPSy się zgadzają w momencie gdy sprites.push_back()
dam w komentarz. Czasami nawet komputer się ścina i robi "wrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr" i po chwili się odcina.
Specyfikacja:
i5 7600k
gtx 1080 armor oc
16 GB 3000MHz CL15
tomahawk z270
ssd adata nazwy nie pamiętam 240GB