#ifndef _H_DEBUGDRAW_H #define _H_DEBUGDRAW_H #include #include #include #include #include #include struct ShaderSource { const char* vertexShader; const char* fragShader; }; struct ShaderProgram { unsigned programID; //uniform locations unsigned u_MVP, u_Color; void setup(const ShaderSource& source) { unsigned vertexID, fragID; // compile vertex shader vertexID = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexID, 1, &source.vertexShader, NULL); glCompileShader(vertexID); // compile fragment shader fragID = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragID, 1, &source.fragShader, NULL); glCompileShader(fragID); // link shaders to program programID = glCreateProgram(); glAttachShader(programID, vertexID); glAttachShader(programID, fragID); glLinkProgram(programID); // delete shaders glDeleteShader(vertexID); glDeleteShader(fragID); // get uniform locations u_MVP = glGetUniformLocation(programID, "u_MVP"); u_Color = glGetUniformLocation(programID, "u_Color"); } void use () { if (programID) glUseProgram(programID); } void setMVP (const float* mvpPointer) { use(); glUniformMatrix4fv(u_MVP, 1, GL_FALSE, mvpPointer); } void setColor (const float* colorPointer) { use(); glUniform4fv(u_Color, 1, colorPointer); } void delShader () { glDeleteProgram(programID); } }; class Circle { private: unsigned VAO, VBO; glm::mat4 MVP; glm::vec4 Color; float radius; public: Circle(const glm::vec3& position, float radius); void setMVP (const glm::mat4& mvp) { MVP = mvp; } void setColor(const glm::vec4& color) { Color = color; } const glm::mat4& getMVP () const { return MVP; } const glm::vec4& getColor() const { return Color; } void draw(); void updatePosition(const glm::vec3& position); ~Circle(); }; class Line { private: unsigned VAO, VBO; glm::vec4 color; public: Line(glm::vec3 start, glm::vec3 end); void setColor(glm::vec4 color) { this->color = color; } const glm::vec4& getColor() const { return color; } void draw(); void updateVertices(const glm::vec3& origin, const glm::vec3& target); ~Line(); }; class DebugDrawer { public: static DebugDrawer& getInstance() { static DebugDrawer instance; return instance; } DebugDrawer(DebugDrawer const&) = delete; void operator=(DebugDrawer const&) = delete; void addLine(const glm::vec3& start, const glm::vec3& end, const glm::vec4& color) { auto line = std::make_shared(start, end); line->setColor(color); lines.push_back(line); } void addCircle(const glm::vec3& position, float radius, const glm::vec4& color) { auto circle = std::make_shared(position, radius); circle->setColor(color); circles.push_back(circle); } void draw(const glm::mat4& mvp) { lineProgram.use(); for (auto& line : lines) { lineProgram.setMVP(glm::value_ptr(mvp)); lineProgram.setColor(glm::value_ptr(line->getColor())); line->draw(); } lines.clear(); circleProgram.use(); for (auto& circle : circles) { circleProgram.setMVP(glm::value_ptr(mvp)); circleProgram.setColor(glm::value_ptr(circle->getColor())); circle->draw(); } circles.clear(); } ~DebugDrawer() { lineProgram.delShader(); circleProgram.delShader(); } private: std::vector> lines; std::vector> circles; DebugDrawer() { circleProgram.setup(circleSource); lineProgram.setup(lineSource); } ShaderSource circleSource { // vertex shader program "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "layout (location = 1) in float aRadius;\n" "uniform mat4 u_MVP;\n" "void main()\n" "{\n" "float angle = 2.0 * 3.14159 * float(gl_InstanceID) / 360.0;\n" "float x = aPos.x + cos(angle) * aRadius;\n" "float y = aPos.y + sin(angle) * aRadius;\n" "gl_Position = u_MVP * vec4(x, y, aPos.z, 1.0);\n" "}\0" , // fragment shader program "#version 330 core\n" "out vec4 FragColor;\n" "uniform vec4 u_Color;\n" "void main()\n" "{\n" "FragColor = u_Color;\n" "}\0" }; ShaderSource lineSource { // vertex shader "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "uniform mat4 mvp;\n" "void main()\n" "{\n" "gl_Position = mvp * vec4(aPos, 1.0);\n" "}\0" , // fragment shader "#version 330 core\n" "out vec4 FragColor;\n" "uniform vec4 Color;\n" "void main()\n" "{\n" "FragColor = Color;\n" "}\0" }; ShaderProgram circleProgram; ShaderProgram lineProgram; }; #endif