From 22e6afffe590fc8b2478f6d23780e16b9495d2b7 Mon Sep 17 00:00:00 2001 From: Kirill Rodriguez Date: Wed, 5 Apr 2017 23:19:46 +0100 Subject: [PATCH] performance boost --- src/frontend/.gitignore | 1 + src/frontend/Quad.cpp | 55 +++++++++----- src/frontend/Quad.hpp | 7 +- src/frontend/Ring.cpp | 140 +++++++++++++++++++++------------- src/frontend/Ring.hpp | 24 +++--- src/frontend/Shape.cpp | 14 +--- src/frontend/Shape.hpp | 15 +--- src/frontend/Space.cpp | 2 +- src/frontend/Sphere.cpp | 162 ++++++++++++++++++++++++++-------------- src/frontend/Sphere.hpp | 26 ++++--- src/frontend/Window.cpp | 4 +- 11 files changed, 271 insertions(+), 179 deletions(-) diff --git a/src/frontend/.gitignore b/src/frontend/.gitignore index 3c63da7..5c1c928 100644 --- a/src/frontend/.gitignore +++ b/src/frontend/.gitignore @@ -4,4 +4,5 @@ planetarium *.jpg *.png *.log +*.trace textures/sam.tga diff --git a/src/frontend/Quad.cpp b/src/frontend/Quad.cpp index b6478e6..45dbb74 100644 --- a/src/frontend/Quad.cpp +++ b/src/frontend/Quad.cpp @@ -21,6 +21,27 @@ void Quad::Init() { AddTriangle(c, d, a, 1, true); } +void Quad::SetTexcoords(size_t index, GLfloat texcoords[6]) { + if(index == 0) { + GLfloat tmp[6] = { + 0, 0, + 0, 1, + 1, 1, + }; + memcpy(texcoords, tmp, 6 * sizeof(GLfloat)); + } else { + GLfloat tmp[6] = { + 1, 1, + 1, 0, + 0, 0, + }; + memcpy(texcoords, tmp, 6 * sizeof(GLfloat)); + } + gl_log("%.2f,%.2f\n", texcoords[0], texcoords[1]); + gl_log("%.2f,%.2f\n", texcoords[2], texcoords[3]); + gl_log("%.2f,%.2f\n", texcoords[4], texcoords[5]); +} + void Quad::AddTriangle( const glm::vec3 &a, const glm::vec3 &b, @@ -38,25 +59,19 @@ void Quad::AddTriangle( size_t color = 0; triangles.back().Init(buffer, color); } else { - GLfloat cpy[6]; - if(index == 0) { - GLfloat texcoords[6] = { - 0, 0, - 0, 1, - 1, 1, - }; - memcpy(cpy, texcoords, 6 * sizeof(GLfloat)); - } else { - GLfloat texcoords[6] = { - 1, 1, - 1, 0, - 0, 0, - }; - memcpy(cpy, texcoords, 6 * sizeof(GLfloat)); - } - gl_log("%.2f,%.2f\n", cpy[0], cpy[1]); - gl_log("%.2f,%.2f\n", cpy[2], cpy[3]); - gl_log("%.2f,%.2f\n", cpy[4], cpy[5]); - triangles.back().Init(buffer, cpy); + gl_log("is textured %d\n", is_textured); + GLfloat texcoords[6]; + SetTexcoords(index, texcoords); + triangles.back().Init(buffer, texcoords); } } + +void Quad::Draw() { + for(auto &t : triangles) + t.Draw(); +} + +void Quad::Clear() { + for(auto &t : triangles) + t.Clear(); +} diff --git a/src/frontend/Quad.hpp b/src/frontend/Quad.hpp index 373a2bb..11054d3 100644 --- a/src/frontend/Quad.hpp +++ b/src/frontend/Quad.hpp @@ -1,7 +1,10 @@ #include "Shape.hpp" +#include "Triangle.hpp" class Quad : public Shape { protected: + std::vector triangles; + void SetTexcoords(size_t index, GLfloat texcoords[6]); void AddTriangle( const glm::vec3 &a, const glm::vec3 &b, @@ -13,6 +16,6 @@ class Quad : public Shape { Quad(); ~Quad(); void Init(); - using Shape::Draw; - using Shape::Clear; + void Draw(); + void Clear(); }; diff --git a/src/frontend/Ring.cpp b/src/frontend/Ring.cpp index d341fa8..2456a0d 100644 --- a/src/frontend/Ring.cpp +++ b/src/frontend/Ring.cpp @@ -4,6 +4,9 @@ #include #include +template const size_t Ring::DIM = 300; +template const size_t Ring::SIZE = DIM * DIM * 2 * 2; + template Ring::Ring(): Shape() @@ -19,72 +22,107 @@ glm::vec3 point_on_circle(float angle) { template void Ring::Init() { - float ir = float(10-N) / 10; - double step = float(M_PI*2) / DIM; + glGenVertexArrays(1, &vao); GLERROR + glBindVertexArray(vao); GLERROR + + txcoords = new GLfloat[SIZE * 6]; + ASSERT(txcoords != NULL); + vertices = new GLfloat[SIZE * 9]; + ASSERT(vertices != NULL); + + InitBuffers(); + + glGenBuffers(1, &vert_vbo); GLERROR + glBindBuffer(GL_ARRAY_BUFFER, vert_vbo); GLERROR + glBufferData(GL_ARRAY_BUFFER, SIZE * sizeof(GLfloat) * 9, vertices, GL_STREAM_DRAW); GLERROR + + glGenBuffers(1, &tex_vbo); GLERROR + glBindBuffer(GL_ARRAY_BUFFER, tex_vbo); GLERROR + glBufferData(GL_ARRAY_BUFFER, SIZE * sizeof(GLfloat) * 6, txcoords, GL_STREAM_DRAW); GLERROR + + ASSERT(vertices != NULL); + delete vertices; + ASSERT(txcoords != NULL); + delete txcoords; + + glEnableVertexAttribArray(0); GLERROR + glBindBuffer(GL_ARRAY_BUFFER, vert_vbo); GLERROR + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); GLERROR + + glEnableVertexAttribArray(1); GLERROR + glBindBuffer(GL_ARRAY_BUFFER, tex_vbo); GLERROR + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL); GLERROR + + glVertexAttribDivisor(0, 0); GLERROR + glVertexAttribDivisor(1, 0); GLERROR +} + +template +void Ring::InitBuffers() { + const static float ir = float(10-N) / 10; + const double step = float(M_PI*2) / DIM; size_t index = 0; double angle = 0.; - for(int i = 0; i < DIM; ++i) { + for(size_t i = 0; i < DIM; ++i) { glm::vec3 &&a = point_on_circle(angle), &&b = point_on_circle(angle + step), &&c = a * ir; - AddTriangle(a, b, c, index, true); - ++index; + SetTexcoords(index); + SetVertices(a, b, c, index), ++index; a = b * ir; - AddTriangle(c, b, a, index, true); - ++index; + SetTexcoords(index); + SetVertices(c, b, a, index), ++index; angle += step; } } template -void Ring::AddTriangle( - const glm::vec3 &a, - const glm::vec3 &b, - const glm::vec3 &c, - size_t index, - bool is_textured) -{ - gl_log("add triangle\n"); - GLfloat buffer[9]; - gl_log("%.2f,%.2f,%.2f\n", a.x,a.y,a.z); - gl_log("%.2f,%.2f,%.2f\n", b.x,b.y,b.z); - gl_log("%.2f,%.2f,%.2f\n", c.x,c.y,c.z); +void Ring::SetTexcoords(int index) { + ASSERT(index < SIZE); + size_t x = index / 2; + ASSERT(x < DIM); + float xstep = 1. / DIM; + float tx0 = float(x) / DIM, tx1 = tx0 + xstep; + GLfloat *buffer = &txcoords[index * 6]; + if(index & 1) { + buffer[0] = tx1, buffer[1] = 1, + buffer[2] = tx0, buffer[3] = 0, + buffer[4] = tx0, buffer[5] = 1; + } else { + buffer[0] = tx1, buffer[1] = 0, + buffer[2] = tx0, buffer[3] = 0, + buffer[4] = tx1, buffer[5] = 1; + } + gl_log("%.2f,%.2f\n", buffer[0], buffer[1]); + gl_log("%.2f,%.2f\n", buffer[2], buffer[3]); + gl_log("%.2f,%.2f\n", buffer[4], buffer[5]); +} + +template +void Ring::SetVertices(const glm::vec3 &a, const glm::vec3 &b, const glm::vec3 &c, size_t index) { + ASSERT(index < SIZE); + GLfloat *buffer = &vertices[index * 9]; memcpy(buffer, glm::value_ptr(a), sizeof(GLfloat) * 3); memcpy(buffer + 3, glm::value_ptr(b), sizeof(GLfloat) * 3); memcpy(buffer + 6, glm::value_ptr(c), sizeof(GLfloat) * 3); - triangles.push_back(Triangle()); - if(!is_textured) { - gl_log("is textured %d\n", is_textured); - size_t color = 0; - triangles.back().Init(buffer, color); - } else { - gl_log("is textured %d\n", is_textured); - size_t x = index / 2; - ASSERT(x < DIM); - float xstep = 1. / DIM; - float tx0 = float(x) / DIM, tx1 = tx0 + xstep; - GLfloat cpy[6]; - if(index & 1) { - GLfloat texcoords[6] = { - tx1, 1, - tx0, 0, - tx0, 1, - }; - memcpy(cpy, texcoords, 6 * sizeof(GLfloat)); - } else { - GLfloat texcoords[6] = { - tx1, 0, - tx0, 0, - tx1, 1, - }; - memcpy(cpy, texcoords, 6 * sizeof(GLfloat)); - } - gl_log("%.2f,%.2f\n", cpy[0], cpy[1]); - gl_log("%.2f,%.2f\n", cpy[2], cpy[3]); - gl_log("%.2f,%.2f\n", cpy[4], cpy[5]); - triangles.back().Init(buffer, cpy); - } + gl_log("adding triangle_strip\n"); + gl_log("%.2f,%.2f,%.2f\n", a.x,a.y,a.z); + gl_log("%.2f,%.2f,%.2f\n", b.x,b.y,b.z); + gl_log("%.2f,%.2f,%.2f\n", c.x,c.y,c.z); +} + +template +void Ring::Draw() { + glBindVertexArray(vao); GLERROR + glDrawArrays(GL_TRIANGLES, 0, SIZE * 3); GLERROR +} + +template +void Ring::Clear() { + glDeleteBuffers(1, &vert_vbo); GLERROR + glDeleteBuffers(1, &tex_vbo); GLERROR + glDeleteVertexArrays(1, &vao); GLERROR } template class Ring<1>; diff --git a/src/frontend/Ring.hpp b/src/frontend/Ring.hpp index 7989ebc..99e2abc 100644 --- a/src/frontend/Ring.hpp +++ b/src/frontend/Ring.hpp @@ -1,22 +1,26 @@ #pragma once #include "Shape.hpp" +#include "Triangle.hpp" template class Ring : public Shape { protected: - const int DIM = 60; - void AddTriangle( - const glm::vec3 &a, - const glm::vec3 &b, - const glm::vec3 &c, - size_t index, - bool is_textured = false - ); + GLuint vao = 0; + GLuint vert_vbo = 0; + GLuint tex_vbo = 0; + GLfloat + *vertices = NULL, + *txcoords = NULL; + static const size_t DIM; + static const size_t SIZE; + void SetTexcoords(int index); + void SetVertices(const glm::vec3 &a, const glm::vec3 &b, const glm::vec3 &c, size_t index); public: Ring(); ~Ring(); void Init(); - using Shape::Draw; - using Shape::Clear; + void InitBuffers(); + void Draw(); + void Clear(); }; diff --git a/src/frontend/Shape.cpp b/src/frontend/Shape.cpp index 6dc3e2f..4fdf411 100644 --- a/src/frontend/Shape.cpp +++ b/src/frontend/Shape.cpp @@ -1,20 +1,8 @@ #include "Shape.hpp" #include "Log.hpp" -Shape::Shape(): - triangles(0) +Shape::Shape() {} Shape::~Shape() {} - -void Shape::Draw() { - for(auto &t : triangles) - t.Draw(); -} - -void Shape::Clear() { - for(auto &t : triangles) - t.Clear(); - triangles.clear(); -} diff --git a/src/frontend/Shape.hpp b/src/frontend/Shape.hpp index 53ea24f..c721695 100644 --- a/src/frontend/Shape.hpp +++ b/src/frontend/Shape.hpp @@ -1,21 +1,10 @@ #pragma once -#include "Triangle.hpp" - class Shape { -protected: - std::vector triangles; - virtual void AddTriangle( - const glm::vec3 &a, - const glm::vec3 &b, - const glm::vec3 &c, - size_t index, - bool is_textured = false - ) = 0; public: Shape(); virtual ~Shape(); virtual void Init() = 0; - virtual void Draw(); - virtual void Clear(); + virtual void Draw() = 0; + virtual void Clear() = 0; }; diff --git a/src/frontend/Space.cpp b/src/frontend/Space.cpp index 9cdd648..497277a 100644 --- a/src/frontend/Space.cpp +++ b/src/frontend/Space.cpp @@ -97,7 +97,7 @@ void Space::Setup(float width, float height) { /* instance->AddObject( */ /* Object( */ /* SPHERE, instance->planet_program, EARTH, */ - /* 0.2f, 0,0,0, */ + /* 1.0f, 0,0,0, */ /* 0.0f */ /* ) */ /* ); */ diff --git a/src/frontend/Sphere.cpp b/src/frontend/Sphere.cpp index 5e8efc8..689efb6 100644 --- a/src/frontend/Sphere.cpp +++ b/src/frontend/Sphere.cpp @@ -6,6 +6,8 @@ #include #include +const size_t Sphere::DIM = 10; +const size_t Sphere::SIZE = DIM*2 * DIM*2; Sphere::Sphere(): Shape() {} @@ -23,78 +25,124 @@ glm::vec3 point_on_sphere(double dyx, double dzx) { } void Sphere::Init() { - const double step = M_PI / double(DIM); + glGenVertexArrays(1, &vao); GLERROR + glBindVertexArray(vao); GLERROR + + txcoords = new GLfloat[SIZE * 6]; + ASSERT(txcoords != NULL); + vertices = new GLfloat[SIZE * 9]; + ASSERT(vertices != NULL); + + InitBuffers(); + + /* for(size_t i = 0; i < SIZE; ++i) { */ + /* GLfloat *v = &vertices[i*9]; */ + /* printf("%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f\n", */ + /* v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); */ + /* } */ + + glGenBuffers(1, &vert_vbo); GLERROR + glBindBuffer(GL_ARRAY_BUFFER, vert_vbo); GLERROR + glBufferData(GL_ARRAY_BUFFER, SIZE * sizeof(GLfloat) * 9, vertices, GL_STREAM_DRAW); GLERROR + + glGenBuffers(1, &tex_vbo); GLERROR + glBindBuffer(GL_ARRAY_BUFFER, tex_vbo); GLERROR + glBufferData(GL_ARRAY_BUFFER, SIZE * sizeof(GLfloat) * 6, txcoords, GL_STREAM_DRAW); GLERROR + + ASSERT(vertices != NULL); + delete vertices; + ASSERT(txcoords != NULL); + delete txcoords; + + glEnableVertexAttribArray(0); GLERROR + glBindBuffer(GL_ARRAY_BUFFER, vert_vbo); GLERROR + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); GLERROR + + glEnableVertexAttribArray(1); GLERROR + glBindBuffer(GL_ARRAY_BUFFER, tex_vbo); GLERROR + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL); GLERROR + + glVertexAttribDivisor(0, 0); GLERROR + glVertexAttribDivisor(1, 0); GLERROR +} + +void Sphere::InitBuffers() { int index = 0; + const double step = M_PI / double(DIM); /* float rx = 1.0 - float(rand() % 10) / 10.; */ /* float ry = 1.0 - float(rand() % 10) / 10.; */ /* float rz = 1.0 - float(rand() % 10) / 10.; */ /* printf("%.2f,%.2f,%.2f\n", rx,ry,rz); */ /* glm::vec3 p(rx, ry, rz); */ #define p - for(double dyx = 0.; dyx < M_PI; dyx += step) { - for(double dzx = 0.; dzx < 2.*M_PI; dzx += step) { - glm::vec3 - &&a = point_on_sphere(dyx, dzx), - &&b = point_on_sphere(dyx + step, dzx + step), - &&c = point_on_sphere(dyx + step, dzx); - AddTriangle(p+a, p+b, p+c, index, true); + for(size_t i = 0; i < DIM; ++i) { + double dyx = double(i) * step; + for(size_t j = 0; j < DIM*2; ++j) { + double dzx = double(j) * step; + SetTexcoords(index); + SetVertices( + point_on_sphere(dyx, dzx), + point_on_sphere(dyx + step, dzx + step), + point_on_sphere(dyx + step, dzx), + index); ++index; - a = point_on_sphere(dyx, dzx); - b = point_on_sphere(dyx, dzx + step); - c = point_on_sphere(dyx + step, dzx + step); - AddTriangle(p+a, p+b, p+c, index, true); + SetTexcoords(index); + SetVertices( + point_on_sphere(dyx, dzx), + point_on_sphere(dyx, dzx + step), + point_on_sphere(dyx + step, dzx + step), + index); ++index; } } #undef p } -void Sphere::AddTriangle( - const glm::vec3 &a, - const glm::vec3 &b, - const glm::vec3 &c, - size_t index, - bool is_textured) -{ - GLfloat buffer[9]; +void Sphere::SetTexcoords(size_t index) { + ASSERT(index < SIZE); + GLfloat *buffer = &txcoords[index * 6]; + size_t + y = DIM - 1 - (index/2) / (2 * DIM), + x = (index/2) % (2 * DIM); + float xstep = 0.5f / float(DIM); + float tx0 = float(x) / float(2 * DIM); + float tx1 = tx0 + xstep; + float ystep = 1.0f / float(DIM); + float ty0 = float(y) / float(DIM); + float ty1 = ty0 + ystep; + if(index & 1) { + buffer[0] = tx0, buffer[1] = ty1, + buffer[2] = tx1, buffer[3] = ty1, + buffer[4] = tx1, buffer[5] = ty0; + } else { + buffer[0] = tx0, buffer[1] = ty1, + buffer[2] = tx1, buffer[3] = ty0, + buffer[4] = tx0, buffer[5] = ty0; + } + gl_log("%.2f,%.2f\n", buffer[0], buffer[1]); + gl_log("%.2f,%.2f\n", buffer[2], buffer[3]); + gl_log("%.2f,%.2f\n", buffer[4], buffer[5]); +} + +void Sphere::SetVertices(const glm::vec3 &&a, const glm::vec3 &&b, const glm::vec3 &&c, size_t index) { + ASSERT(index < SIZE); + GLfloat *buffer = &vertices[index * 9]; memcpy(buffer, glm::value_ptr(a), sizeof(GLfloat) * 3); memcpy(buffer + 3, glm::value_ptr(b), sizeof(GLfloat) * 3); memcpy(buffer + 6, glm::value_ptr(c), sizeof(GLfloat) * 3); - triangles.push_back(Triangle()); - if(!is_textured) { - gl_log("is textured %d\n", is_textured); - size_t color = 0; - triangles.back().Init(buffer, color); - } else { - size_t - y = DIM - 1 - (index/2) / (2 * DIM), - x = (index/2) % (2 * DIM); - float xstep = 0.5f / float(DIM); - float tx0 = float(x) / float(2 * DIM); - float tx1 = tx0 + xstep; - float ystep = 1.0f / float(DIM); - float ty0 = float(y) / float(DIM); - float ty1 = ty0 + ystep; - gl_log("is textured %d\n", is_textured); - GLfloat cpy[6]; - if(index & 1) { - GLfloat texcoords[6] = { - tx0, ty1, - tx1, ty1, - tx1, ty0, - }; - memcpy(cpy, texcoords, 6 * sizeof(GLfloat)); - } else { - GLfloat texcoords[6] = { - tx0, ty1, - tx1, ty0, - tx0, ty0, - }; - memcpy(cpy, texcoords, 6 * sizeof(GLfloat)); - } - gl_log("%.2f,%.2f\n", cpy[0], cpy[1]); - gl_log("%.2f,%.2f\n", cpy[2], cpy[3]); - gl_log("%.2f,%.2f\n", cpy[4], cpy[5]); - triangles.back().Init(buffer, cpy); - } + gl_log("adding triangle_strip\n"); + gl_log("%.2f,%.2f,%.2f\n", buffer[0], buffer[1], buffer[2]); + gl_log("%.2f,%.2f,%.2f\n", buffer[3], buffer[4], buffer[5]); + gl_log("%.2f,%.2f,%.2f\n", buffer[6], buffer[7], buffer[8]); +} + +void Sphere::Draw() { + glBindVertexArray(vao); GLERROR + glDrawArrays(GL_TRIANGLES, 0, SIZE * 3); GLERROR +} + +void Sphere::Clear() { + glDeleteBuffers(1, &vert_vbo); GLERROR + glDeleteBuffers(1, &tex_vbo); GLERROR + glDeleteVertexArrays(1, &vao); GLERROR } diff --git a/src/frontend/Sphere.hpp b/src/frontend/Sphere.hpp index c305df2..b4c22a5 100644 --- a/src/frontend/Sphere.hpp +++ b/src/frontend/Sphere.hpp @@ -1,21 +1,27 @@ #pragma once +#include +#include "incgraphics.h" + #include "Shape.hpp" class Sphere : public Shape { + GLuint vao = 0; + GLuint vert_vbo = 0; + GLuint tex_vbo = 0; + GLfloat + *vertices = NULL, + *txcoords = NULL; protected: - const int DIM = 15; - void AddTriangle( - const glm::vec3 &a, - const glm::vec3 &b, - const glm::vec3 &c, - size_t index, - bool is_textured = false - ); + static const size_t DIM; + static const size_t SIZE; + void SetTexcoords(size_t index); + void SetVertices(const glm::vec3 &&a, const glm::vec3 &&b, const glm::vec3 &&c, size_t index); public: Sphere(); ~Sphere(); void Init(); - using Shape::Draw; - using Shape::Clear; + void InitBuffers(); + void Draw(); + void Clear(); }; diff --git a/src/frontend/Window.cpp b/src/frontend/Window.cpp index 22b6064..d2a7a6b 100644 --- a/src/frontend/Window.cpp +++ b/src/frontend/Window.cpp @@ -57,8 +57,8 @@ Window::Window(size_t width, size_t height): current_screen(NULL) { /* current_screen = &trianglescreen; */ - /* current_screen = &spacescreen; */ - current_screen = &menuscreen; + current_screen = &spacescreen; + /* current_screen = &menuscreen; */ start(); }