Radium Engine  1.5.0
DebugRender.cpp
1 #include <Engine/Rendering/DebugRender.hpp>
2 
3 #include <Engine/Data/DrawPrimitives.hpp>
4 #include <Engine/Data/Mesh.hpp>
5 #include <Engine/Data/ShaderProgram.hpp>
6 #include <Engine/Data/ShaderProgramManager.hpp>
7 #include <Engine/OpenGL.hpp>
8 #include <Engine/RadiumEngine.hpp>
9 
10 #include <Core/Containers/MakeShared.hpp>
11 #include <Core/Geometry/MeshPrimitives.hpp>
12 #include <Core/Utils/Log.hpp>
13 
14 #include <globjects/Program.h>
15 #include <globjects/Shader.h>
16 #include <globjects/base/StaticStringSource.h>
17 
18 #include <fstream>
19 
20 namespace Ra {
21 namespace Engine {
22 namespace Rendering {
23 
24 using namespace Core::Utils; // log
25 
26 DebugRender::DebugRender() = default;
27 
28 DebugRender::~DebugRender() = default;
29 
33  auto setShader = []( Data::ShaderProgramManager* manager,
34  const std::string& configName,
35  const char* vertexShader,
36  const char* fragmentShader ) -> const Data::ShaderProgram* {
37  Data::ShaderConfiguration config { configName };
38  config.addShaderSource( Data::ShaderType::ShaderType_VERTEX, vertexShader );
39  config.addShaderSource( Data::ShaderType::ShaderType_FRAGMENT, fragmentShader );
40  auto added = manager->addShaderProgram( config );
41  if ( added ) { return *added; }
42  else { return nullptr; }
43  };
44 
45  auto shaderProgramManager = RadiumEngine::getInstance()->getShaderProgramManager();
46 
47  const char* lineVertStr = R"(
48  layout (location = 0) in vec3 in_pos;
49  layout (location = 5) in vec3 in_col;
50 
51  uniform mat4 model;
52  uniform mat4 view;
53  uniform mat4 proj;
54 
55  out vec3 v_color;
56  void main()
57  {
58  gl_Position = proj * view * model * vec4(in_pos, 1.0);
59  v_color = in_col;
60  }
61  )";
62 
63  const char* lineFragStr = R"(
64  in vec3 v_color;
65  out vec4 f_color;
66 
67  void main()
68  {
69  f_color = vec4(v_color, 1.0);
70  }
71  )";
72 
73  static const char* pointVertStr = R"(
74  layout (location = 0) in vec3 in_pos;
75  layout (location = 1) in vec3 in_col;
76 
77  uniform mat4 view;
78  uniform mat4 proj;
79 
80  out vec3 v_color;
81 
82  void main()
83  {
84  gl_Position = proj * view * vec4(in_pos, 1.0);
85  v_color = in_col;
86  gl_PointSize = 40 / gl_Position.w;
87  }
88  )";
89 
90  static const char* pointFragStr = R"(
91  in vec3 v_color;
92  out vec4 f_color;
93 
94  void main()
95  {
96  f_color = vec4(v_color, 1.0);
97  }
98  )";
99  static const char* meshVertStr = R"(
100  layout (location = 0) in vec3 in_pos;
101  layout (location = 5) in vec3 in_col;
102 
103  uniform mat4 model;
104  uniform mat4 view;
105  uniform mat4 proj;
106 
107  out vec3 v_color;
108 
109  void main()
110  {
111  gl_Position = proj * view * model * vec4(in_pos, 1.0);
112  v_color = in_col;
113  }
114  )";
115 
116  static const char* meshFragStr = R"(
117  in vec3 v_color;
118  out vec4 f_color;
119 
120  void main()
121  {
122  f_color = vec4(v_color, 1.0);
123  }
124  )";
125 
126  m_lineProg = setShader( shaderProgramManager, "dbgLineShader", lineVertStr, lineFragStr );
127  m_pointProg = setShader( shaderProgramManager, "dbgPointShader", pointVertStr, pointFragStr );
128  m_meshProg = setShader( shaderProgramManager, "dbgMeshShader", meshVertStr, meshFragStr );
129 
130  GL_CHECK_ERROR;
131 }
132 
133 void DebugRender::render( const Core::Matrix4& viewMatrix, const Core::Matrix4& projMatrix ) {
134  renderLines( viewMatrix.cast<float>(), projMatrix.cast<float>() );
135  renderPoints( viewMatrix.cast<float>(), projMatrix.cast<float>() );
136  renderMeshes( viewMatrix.cast<float>(), projMatrix.cast<float>() );
137 }
138 
139 void DebugRender::renderLines( const Core::Matrix4f& viewMatrix,
140  const Core::Matrix4f& projMatrix ) {
141  Core::Vector3Array vertices;
142  Core::Vector4Array colors;
144  unsigned int indexI = 0;
145  for ( const auto& l : m_lines ) {
146  vertices.push_back( l.a );
147  vertices.push_back( l.b );
148 
149  colors.push_back( l.col );
150  colors.push_back( l.col );
151 
152  indices.push_back( { indexI, indexI + 1 } );
153  indexI += 2;
154  }
155 
156  if ( !vertices.empty() ) {
157  const Core::Matrix4f id = Core::Matrix4f::Identity();
158 
159  m_lineProg->bind();
160  m_lineProg->setUniform( "model", id );
161  m_lineProg->setUniform( "view", viewMatrix );
162  m_lineProg->setUniform( "proj", projMatrix );
163 
164  Core::Geometry::LineMesh geom;
165  geom.setVertices( vertices );
166  geom.setIndices( std::move( indices ) );
167  geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_COLOR ),
168  colors );
169 
170  Data::LineMesh mesh( "temp", std::move( geom ) );
171 
172  mesh.updateGL();
174  mesh.render( m_lineProg );
175  }
176 
177  m_lines.clear();
178 }
179 
180 void DebugRender::renderPoints( const Core::Matrix4f& viewMatrix,
181  const Core::Matrix4f& projMatrix ) {
182  uint size = m_points.size();
183  if ( 0 == size ) { return; }
184 
186  GLuint vao, vbo;
187  glGenVertexArrays( 1, &vao );
188 
189  glBindVertexArray( vao );
190  glGenBuffers( 1, &vbo );
191  glBindBuffer( GL_ARRAY_BUFFER, vbo );
192  glBufferData(
193  GL_ARRAY_BUFFER, size * 2 * sizeof( Core::Vector3 ), m_points.data(), GL_DYNAMIC_DRAW );
194  GLint64 ptr = 0;
195  glVertexAttribPointer( 0, 3, GL_SCALAR, GL_FALSE, 6 * sizeof( Scalar ), (GLvoid*)ptr );
196  glEnableVertexAttribArray( 0 );
197  ptr += 3 * sizeof( Scalar );
198  glVertexAttribPointer( 1, 3, GL_SCALAR, GL_FALSE, 6 * sizeof( Scalar ), (GLvoid*)ptr );
199  glEnableVertexAttribArray( 1 );
200 
201  glEnable( GL_PROGRAM_POINT_SIZE );
202  m_pointProg->bind();
203 
204  m_pointProg->setUniform( "view", viewMatrix );
205  m_pointProg->setUniform( "proj", projMatrix );
206 
207  glDrawArrays( GL_POINTS, 0, size );
208  glDisable( GL_PROGRAM_POINT_SIZE );
209 
210  glBindVertexArray( 0 );
211  glDeleteVertexArrays( 1, &vao );
212  glDeleteBuffers( 1, &vbo );
213 
214  m_points.clear();
215 }
216 
217 void DebugRender::renderMeshes( const Core::Matrix4f& view, const Core::Matrix4f& proj ) {
218  if ( m_meshes.empty() ) { return; }
219 
220  // Avoid too much states change
221  uint idx = 0;
222  std::sort( m_meshes.begin(), m_meshes.end(), []( const DbgMesh& a, const DbgMesh& b ) -> bool {
223  return a.mesh->getRenderMode() < b.mesh->getRenderMode();
224  } );
225 
226  for ( ; idx < m_meshes.size() && m_meshes[idx].mesh->getRenderMode() != GL_TRIANGLES; ++idx )
227  ;
228 
229  m_lineProg->bind();
230  m_lineProg->setUniform( "view", view );
231  m_lineProg->setUniform( "proj", proj );
232 
233  for ( uint i = 0; i < idx; ++i ) {
234  m_lineProg->setUniform( "model", m_meshes[i].transform.matrix() );
235  m_meshes[i].mesh->updateGL();
236  m_meshes[i].mesh->render( m_lineProg );
237  }
238 
239  m_meshProg->bind();
240  m_meshProg->setUniform( "view", view );
241  m_meshProg->setUniform( "proj", proj );
242 
243  for ( uint i = idx; i < m_meshes.size(); ++i ) {
244  m_meshProg->setUniform( "model", m_meshes[i].transform.matrix() );
245  m_meshes[i].mesh->updateGL();
246  m_meshes[i].mesh->render( m_meshProg );
247  }
248 
249  m_meshes.clear();
250 }
251 
252 void DebugRender::addLine( const Core::Vector3& from,
253  const Core::Vector3& to,
254  const Core::Utils::Color& color ) {
255  Line l( from, to, color );
256  m_lines.push_back( l );
257 }
258 
259 void DebugRender::addPoint( const Core::Vector3& p, const Core::Utils::Color& c ) {
260  m_points.push_back( { p, c.head<3>() } );
261 }
262 
263 void DebugRender::addPoints( const Core::Vector3Array& p, const Core::Utils::Color& c ) {
264  for ( uint i = 0; i < p.size(); ++i ) {
265  m_points.push_back( { p[i], c.head<3>() } );
266  }
267 }
268 
269 void DebugRender::addPoints( const Core::Vector3Array& p, const Core::Vector4Array& c ) {
270  CORE_ASSERT( p.size() == c.size(), "Data sizes mismatch." );
271  for ( uint i = 0; i < p.size(); ++i ) {
272  m_points.push_back( { p[i], c[i].head<3>() } );
273  }
274 }
275 
276 void DebugRender::addMesh( const std::shared_ptr<Data::AttribArrayDisplayable>& mesh,
277  const Core::Transform& transform ) {
278  m_meshes.push_back( { mesh, transform } );
279 }
280 
281 void DebugRender::addCross( const Core::Vector3& position,
282  Scalar size,
283  const Core::Utils::Color& color ) {
284  const Scalar hz = size / 2.0;
285  for ( int i = 0; i < 3; ++i ) {
286  Core::Vector3 offset = Core::Vector3::Zero();
287  offset[i] = hz;
288 
289  const Core::Vector3 from = position - offset;
290  const Core::Vector3 to = position + offset;
291 
292  addLine( from, to, color );
293  }
294 }
295 
296 void DebugRender::addSphere( const Core::Vector3& center,
297  Scalar radius,
298  const Core::Utils::Color& color ) {
299  addMesh( Data::DrawPrimitives::Sphere( center, radius, color ) );
300 }
301 
302 void DebugRender::addCircle( const Core::Vector3& center,
303  const Core::Vector3& normal,
304  Scalar radius,
305  const Core::Utils::Color& color ) {
306  addMesh( Data::DrawPrimitives::Circle( center, normal, radius, 64, color ) );
307 }
308 
309 void DebugRender::addFrame( const Core::Transform& transform, Scalar size ) {
310  addMesh( Data::DrawPrimitives::Frame( transform, size ) );
311 }
312 
313 void DebugRender::addTriangle( const Core::Vector3& p0,
314  const Core::Vector3& p1,
315  const Core::Vector3& p2,
316  const Core::Utils::Color& color ) {
317  addMesh( Data::DrawPrimitives::Triangle( p0, p1, p2, color ) );
318 }
319 
320 void DebugRender::addAABB( const Core::Aabb& box, const Core::Utils::Color& color ) {
321  addMesh( Data::DrawPrimitives::AABB( box, color ) );
322 }
323 
324 void DebugRender::addOBB( const Core::Aabb& box,
325  const Core::Transform& transform,
326  const Core::Utils::Color& color ) {
327  addMesh( Data::DrawPrimitives::AABB( box, color ), transform );
328 }
329 
330 RA_SINGLETON_IMPLEMENTATION( DebugRender );
331 
332 } // namespace Rendering
333 } // namespace Engine
334 } // namespace Ra
void addShaderSource(ShaderType type, const std::string &source)
Core::Utils::optional< const Data::ShaderProgram * > addShaderProgram(const Data::ShaderConfiguration &config)
LineMeshPtr Line(const Core::Vector3 &a, const Core::Vector3 &b, const Core::Utils::Color &color)
Displays given line.
AttribArrayDisplayablePtr Triangle(const Core::Vector3 &a, const Core::Vector3 &b, const Core::Vector3 &c, const Core::Utils::Color &color, bool fill)
MeshPtr AABB(const Core::Aabb &aabb, const Core::Utils::Color &color)
Display a wireframe AABB.
MeshPtr Frame(const Core::Transform &frameFromEntity, Scalar scale)
MeshPtr Sphere(const Core::Vector3 &center, Scalar radius, const Core::Utils::Color &color)
Displays geodesic sphere computed with given center and radius.
LineMeshPtr Circle(const Core::Vector3 &center, const Core::Vector3 &normal, Scalar radius, uint segments, const Core::Utils::Color &color)
Definition: Cage.cpp:3