//DebugShape class class DebugShape { public: DebugShape(uint num_vertices, float* vertices, uint num_indices, uint* indices); void CleanUp(); void SetTransform(float4x4 transform); void SetColour(float4 colour); void SetMode(int mode); void SetStroke(uint stroke); uint GetNumVertices(); float* GetVertices(); uint GetNumIndices(); uint* GetIndices(); float4 GetColour(); float4x4 GetTransform(); int GetMode(); uint GetStroke(); private: uint num_vertices = 0; float* vertices = nullptr; uint num_indices = 0; uint* indices = nullptr; float4 colour = float4::zero; float4x4 transform = float4x4::identity; int mode = 0x0004; uint stroke = 1; }; DebugShape::DebugShape(uint _num_vertices, float * _vertices, uint _num_indices, uint * _indices) { if (_num_vertices > 0) { // Vertices vertices = new float[_num_vertices * 3]; memcpy(vertices, _vertices, sizeof(float) * _num_vertices * 3); num_vertices = _num_vertices; if (_num_indices > 0) { // Indices indices = new uint[_num_indices]; memcpy(indices, _indices, sizeof(uint) * _num_indices); num_indices = _num_indices; } } mode = GL_TRIANGLES; transform = float4x4::identity; colour = float4(1.0f, 1.0f, 1.0f, 1.0f); } void DebugDraw::Line(float3 start, float3 end, float4 colour) { uint num_vertices = 2; uint num_indices = 2; float* vertices = new float[num_vertices * 3]; uint* indices = new uint[num_indices]; vertices[0] = start.x; vertices[1] = start.y; vertices[2] = start.z; vertices[3] = end.x; vertices[4] = end.y; vertices[5] = end.z; indices[0] = 0; indices[1] = 1; DebugShape shape(num_vertices, vertices, num_indices, indices); shape.SetMode(GL_LINES); shape.SetColour(colour); shape.SetStroke(line_stroke); AddShape(shape); delete[] vertices; delete[] indices; } void DebugDraw::Quad(float3 center, float2 size, float4 colour) { uint num_vertices = 4; uint num_indices = 8; float* vertices = new float[num_vertices * 3]; uint* indices = new uint[num_indices]; float3 up_left = float3(center.x - (size.x/2), center.y + (size.y/2), center.z); float3 down_left = float3(center.x - (size.x/2), center.y - (size.y/2), center.z); float3 down_right = float3(center.x + (size.x / 2), center.y - (size.y / 2), center.z); float3 up_right = float3(center.x + (size.x / 2), center.y + (size.y / 2), center.z); vertices[0] = up_left.x; vertices[1] = up_left.y; vertices[2] = up_left.z; vertices[3] = down_left.x; vertices[4] = down_left.y; vertices[5] = down_left.z; vertices[6] = down_right.x; vertices[7] = down_right.y; vertices[8] = down_right.z; vertices[9] = up_right.x; vertices[10] = up_right.y; vertices[11] = up_right.z; indices[0] = 0; indices[1] = 1; indices[2] = 1; indices[3] = 2; indices[4] = 2; indices[5] = 3; indices[6] = 3; indices[7] = 0; DebugShape shape(num_vertices, vertices, num_indices, indices); shape.SetMode(GL_LINES); shape.SetColour(colour); shape.SetStroke(line_stroke); AddShape(shape); delete[] vertices; delete[] indices; } void DebugDraw::Quad(float4x4 transform, float2 size, float4 colour) { uint num_vertices = 4; uint num_indices = 8; float* vertices = new float[num_vertices * 3]; uint* indices = new uint[num_indices]; float3 up_left = float3(-(size.x / 2), (size.y / 2), 0); float3 down_left = float3(-(size.x / 2), -(size.y / 2), 0); float3 down_right = float3((size.x / 2), -(size.y / 2), 0); float3 up_right = float3((size.x / 2), (size.y / 2), 0); vertices[0] = up_left.x; vertices[1] = up_left.y; vertices[2] = up_left.z; vertices[3] = down_left.x; vertices[4] = down_left.y; vertices[5] = down_left.z; vertices[6] = down_right.x; vertices[7] = down_right.y; vertices[8] = down_right.z; vertices[9] = up_right.x; vertices[10] = up_right.y; vertices[11] = up_right.z; indices[0] = 0; indices[1] = 1; indices[2] = 1; indices[3] = 2; indices[4] = 2; indices[5] = 3; indices[6] = 3; indices[7] = 0; DebugShape shape(num_vertices, vertices, num_indices, indices); shape.SetMode(GL_LINES); shape.SetTransform(transform); shape.SetColour(colour); shape.SetStroke(line_stroke); AddShape(shape); delete[] vertices; delete[] indices; } void DebugDraw::Circle(float4x4 transform, float rad, float4 colour, uint resolution) { int slices = resolution; float angle_slice = 360 / slices; uint num_vertices = slices; uint num_indices = slices*2; float* vertices = new float[num_vertices * 3]; uint* indices = new uint[num_indices]; float curr_angle = 0; for(int i = 0; i < slices; i++) { vertices[(i * 3)] = cos(curr_angle * DEGTORAD) * rad; vertices[(i * 3) + 1] = sin(curr_angle * DEGTORAD) * rad; vertices[(i * 3) + 2] = 0; curr_angle += angle_slice; indices[i*2] = i; if (i+1 < slices) indices[(i * 2) + 1] = i + 1; else indices[(i * 2) + 1] = 0; } DebugShape shape(num_vertices, vertices, num_indices, indices); shape.SetMode(GL_LINES); shape.SetTransform(transform); shape.SetColour(colour); shape.SetStroke(line_stroke); AddShape(shape); delete[] vertices; delete[] indices; } void DebugDraw::AddShape(DebugShape shape) { shapes.push_back(shape); } void DebugDraw::Render(ComponentCamera* camera) { if (shapes.empty()) return; // Activate GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture); glActiveTexture(GL_TEXTURE0); GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler); GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb); GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb); GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha); GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha); GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb); GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha); GLboolean last_enable_blend = glIsEnabled(GL_BLEND); GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Render ---- uint program = App->resources->GetShaderProgram("default_debug_program")->GetProgramID(); App->renderer3D->UseShaderProgram(program); App->renderer3D->SetUniformMatrix(program, "view", camera->GetViewMatrix()); App->renderer3D->SetUniformMatrix(program, "projection", camera->GetProjectionMatrix()); uint vao; glGenVertexArrays(1, (GLuint*)&vao); float4 color = float4::zero; for (std::vector::iterator it = shapes.begin(); it != shapes.end(); ++it) { glLineWidth((*it).GetStroke()); uint id_vertices_data = 0; uint id_indices = 0; float4x4 trans = (*it).GetTransform(); float4 current_colour = (*it).GetColour(); int mode = (*it).GetMode(); App->renderer3D->SetUniformMatrix(program, "Model", trans.Transposed().ptr()); if (!current_colour.Equals(color)) { App->renderer3D->SetUniformVector4(program, "debug_color", current_colour); } glGenBuffers(1, &id_vertices_data); glBindBuffer(GL_ARRAY_BUFFER, id_vertices_data); glBufferData(GL_ARRAY_BUFFER, sizeof(float) * (*it).GetNumVertices() * 3, (*it).GetVertices(), GL_DYNAMIC_DRAW); glBindVertexArray(vao); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0 * sizeof(GLfloat), (void*)(0 * sizeof(GLfloat))); glEnableVertexAttribArray(0); glGenBuffers(1, &id_indices); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id_indices); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint) * (*it).GetNumIndices(), (*it).GetIndices(), GL_DYNAMIC_DRAW); glDrawElements(GL_TRIANGLES, (*it).GetNumIndices(), GL_UNSIGNED_INT, nullptr); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDeleteBuffers(1, &id_vertices_data); glDeleteBuffers(1, &id_indices); glBindVertexArray(0); } glDeleteVertexArrays(1, &vao); // ----------- // DeActivate glLineWidth(1); App->renderer3D->UseShaderProgram(last_program); glBindTexture(GL_TEXTURE_2D, last_texture); glBindSampler(0, last_sampler); glActiveTexture(last_active_texture); glBindVertexArray(last_vertex_array); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer); glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha); glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha); if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); glPolygonMode(GL_FRONT_AND_BACK, last_polygon_mode[0]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); } ////////////////////////////////// //Vertex Shader #version 330 core layout(location = 0) in vec3 position; uniform mat4 Model; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view * Model * vec4(position, 1.0f); } //Fragment Shader #version 330 core out vec4 color; uniform vec4 debug_color; void main() { color = debug_color; }