Skip to content

Commit

Permalink
UPBGE: Use VBO and VAO for debug drawing.
Browse files Browse the repository at this point in the history
Using VBO and VAO allow to render all the lines in one command
and to render all the AABB and frustum using instancing in one
command too.

The usage of VBO request that all the structs for lines, aabbs,
frustum and boxes use array instead of mathfu types to avoid
SSE padding and alignement.

Four shaders are introduced to help debug drawing using instancing.
The first is just for drawing lines using a flat color, the second
is for wire boxes, the third for solid boxes with in and out color
and the fourth for 2d boxes.
All the these geometry type use geometry instancing.

For each type RAS_OpenGLDebugDraw allocate a VAO and multiples VBOs,
they are stored into m_vbos and m_vaos and accessed thanks to enums.
The VAO are initialized in RAS_OpenGlDebugDraw constructor pointing
to the uninitialized VBOs, some VBOs as unit 3d and 2d box and IBOs
are initialized in the same time.

At each render step the VBO containing data about instancing or
geometry are updated from the data list contained into RAS_DebugDraw.
Then the render is procceed binding the VAO and calling the proper
draw call.

2d boxes receive a special treatment. The boxes are rendered using
a vertically inverted ortho matrix because the Y axis is from the
top of the screen.

All these modification ends in a significant speedup for debug drawing
and makes the code easier to move to blender 2.8.
  • Loading branch information
panzergame committed Dec 31, 2017
1 parent cd9fa2b commit a23e65c
Show file tree
Hide file tree
Showing 18 changed files with 474 additions and 258 deletions.
12 changes: 12 additions & 0 deletions source/blender/gpu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ set(SRC
intern/gpu_shader.c
intern/gpu_texture.c

shaders/gpu_shader_2d_box_vert.glsl
shaders/gpu_shader_flat_color_frag.glsl
shaders/gpu_shader_flat_color_vert.glsl
shaders/gpu_shader_fx_lib.glsl
shaders/gpu_shader_fx_ssao_frag.glsl
shaders/gpu_shader_fx_dof_frag.glsl
Expand All @@ -83,6 +86,9 @@ set(SRC
shaders/gpu_shader_vsm_store_vert.glsl
shaders/gpu_shader_fx_depth_resolve.glsl
shaders/gpu_shader_fire_frag.glsl
shaders/gpu_shader_frustum_line_vert.glsl
shaders/gpu_shader_frustum_solid_frag.glsl
shaders/gpu_shader_frustum_solid_vert.glsl
shaders/gpu_shader_smoke_frag.glsl
shaders/gpu_shader_smoke_vert.glsl

Expand All @@ -104,7 +110,13 @@ set(SRC
intern/gpu_select_private.h
)

data_to_c_simple(shaders/gpu_shader_2d_box_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_geometry.glsl SRC)
data_to_c_simple(shaders/gpu_shader_flat_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_flat_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_frustum_line_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_frustum_solid_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_frustum_solid_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_fire_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_smoke_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_smoke_vert.glsl SRC)
Expand Down
4 changes: 4 additions & 0 deletions source/blender/gpu/GPU_shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_DRAW_FRAME_BUFFER = 8,
GPU_SHADER_STEREO_STIPPLE = 9,
GPU_SHADER_STEREO_ANAGLYPH = 10,
GPU_SHADER_FRUSTUM_LINE = 11,
GPU_SHADER_FRUSTUM_SOLID = 12,
GPU_SHADER_FLAT_COLOR = 13,
GPU_SHADER_2D_BOX = 14,
} GPUBuiltinShader;

GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
Expand Down
60 changes: 59 additions & 1 deletion source/blender/gpu/intern/gpu_shader.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,17 @@
#define MAX_EXT_DEFINE_LENGTH 1024

/* Non-generated shaders */
extern char datatoc_gpu_shader_2d_box_vert_glsl[];
extern char datatoc_gpu_shader_black_frag_glsl[];
extern char datatoc_gpu_shader_black_vert_glsl[];
extern char datatoc_gpu_shader_fire_frag_glsl[];
extern char datatoc_gpu_shader_flat_color_frag_glsl[];
extern char datatoc_gpu_shader_flat_color_vert_glsl[];
extern char datatoc_gpu_shader_frame_buffer_frag_glsl[];
extern char datatoc_gpu_shader_frame_buffer_vert_glsl[];
extern char datatoc_gpu_shader_fire_frag_glsl[];
extern char datatoc_gpu_shader_frustum_line_vert_glsl[];
extern char datatoc_gpu_shader_frustum_solid_vert_glsl[];
extern char datatoc_gpu_shader_frustum_solid_frag_glsl[];
extern char datatoc_gpu_shader_smoke_vert_glsl[];
extern char datatoc_gpu_shader_smoke_frag_glsl[];
extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
Expand Down Expand Up @@ -82,6 +88,10 @@ static struct GPUShadersGlobal {
GPUShader *draw_frame_buffer;
GPUShader *stereo_stipple;
GPUShader *stereo_anaglyph;
GPUShader *frustum_line;
GPUShader *frustum_solid;
GPUShader *flat_color;
GPUShader *box2d;
/* cache for shader fx. Those can exist in combinations so store them here */
GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
} shaders;
Expand Down Expand Up @@ -760,6 +770,34 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
NULL, NULL, "#define ANAGLYPH;\n", 0, 0, 0);
retval = GG.shaders.stereo_anaglyph;
break;
case GPU_SHADER_FRUSTUM_LINE:
if (!GG.shaders.frustum_line)
GG.shaders.frustum_line = GPU_shader_create(
datatoc_gpu_shader_frustum_line_vert_glsl, datatoc_gpu_shader_flat_color_frag_glsl,
NULL, NULL, NULL, 0, 0, 0);
retval = GG.shaders.frustum_line;
break;
case GPU_SHADER_FRUSTUM_SOLID:
if (!GG.shaders.frustum_solid)
GG.shaders.frustum_solid = GPU_shader_create(
datatoc_gpu_shader_frustum_solid_vert_glsl, datatoc_gpu_shader_frustum_solid_frag_glsl,
NULL, NULL, NULL, 0, 0, 0);
retval = GG.shaders.frustum_solid;
break;
case GPU_SHADER_FLAT_COLOR:
if (!GG.shaders.flat_color)
GG.shaders.flat_color = GPU_shader_create(
datatoc_gpu_shader_flat_color_vert_glsl, datatoc_gpu_shader_flat_color_frag_glsl,
NULL, NULL, NULL, 0, 0, 0);
retval = GG.shaders.flat_color;
break;
case GPU_SHADER_2D_BOX:
if (!GG.shaders.box2d)
GG.shaders.box2d = GPU_shader_create(
datatoc_gpu_shader_2d_box_vert_glsl, datatoc_gpu_shader_flat_color_frag_glsl,
NULL, NULL, NULL, 0, 0, 0);
retval = GG.shaders.box2d;
break;
}

if (retval == NULL)
Expand Down Expand Up @@ -901,6 +939,26 @@ void GPU_shader_free_builtin_shaders(void)
GG.shaders.stereo_anaglyph = NULL;
}

if (GG.shaders.frustum_line) {
GPU_shader_free(GG.shaders.frustum_line);
GG.shaders.frustum_line = NULL;
}

if (GG.shaders.frustum_solid) {
GPU_shader_free(GG.shaders.frustum_solid);
GG.shaders.frustum_solid = NULL;
}

if (GG.shaders.flat_color) {
GPU_shader_free(GG.shaders.flat_color);
GG.shaders.flat_color = NULL;
}

if (GG.shaders.box2d) {
GPU_shader_free(GG.shaders.box2d);
GG.shaders.box2d = NULL;
}

for (i = 0; i < 2 * MAX_FX_SHADERS; ++i) {
if (GG.shaders.fx_shaders[i]) {
GPU_shader_free(GG.shaders.fx_shaders[i]);
Expand Down
11 changes: 11 additions & 0 deletions source/blender/gpu/shaders/gpu_shader_2d_box_vert.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
in vec2 pos;
in vec4 trans;
in vec4 color;

flat out vec4 finalColor;

void main()
{
gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(pos * trans.zw + trans.xy, 0.0, 1.0);
finalColor = color;
}
6 changes: 6 additions & 0 deletions source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
flat in vec4 finalColor;

void main()
{
gl_FragColor = finalColor;
}
10 changes: 10 additions & 0 deletions source/blender/gpu/shaders/gpu_shader_flat_color_vert.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
in vec3 pos;
in vec4 color;

flat out vec4 finalColor;

void main()
{
gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(pos, 1.0);
finalColor = color;
}
11 changes: 11 additions & 0 deletions source/blender/gpu/shaders/gpu_shader_frustum_line_vert.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
in vec3 pos;
in mat4 mat;
in vec4 color;

flat out vec4 finalColor;

void main()
{
gl_Position = gl_ModelViewProjectionMatrix * mat * vec4(pos, 1.0);
finalColor = color;
}
8 changes: 8 additions & 0 deletions source/blender/gpu/shaders/gpu_shader_frustum_solid_frag.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
flat in vec4 insideFinalColor;
flat in vec4 outsideFinalColor;
out vec4 fragColor;

void main()
{
gl_FragColor = gl_FrontFacing ? insideFinalColor : outsideFinalColor;
}
14 changes: 14 additions & 0 deletions source/blender/gpu/shaders/gpu_shader_frustum_solid_vert.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
in vec3 pos;
in mat4 mat;
in vec4 insideColor;
in vec4 outsideColor;

flat out vec4 insideFinalColor;
flat out vec4 outsideFinalColor;

void main()
{
gl_Position = gl_ModelViewProjectionMatrix * mat * vec4(pos, 1.0);
insideFinalColor = insideColor;
outsideFinalColor = outsideColor;
}
6 changes: 0 additions & 6 deletions source/gameengine/Ketsji/KX_Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,3 @@ void KX_RasterizerDrawDebugLine(const mt::vec3& from,const mt::vec3& to,const mt
{
g_engine->GetRasterizer()->GetDebugDraw(g_scene).DrawLine(from, to, color);
}

void KX_RasterizerDrawDebugCircle(const mt::vec3& center, const float radius, const mt::vec4& color,
const mt::vec3& normal, int nsector)
{
g_engine->GetRasterizer()->GetDebugDraw(g_scene).DrawCircle(center, radius, color, normal, nsector);
}
2 changes: 0 additions & 2 deletions source/gameengine/Ketsji/KX_Globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,5 @@ const std::string& KX_GetMainPath();
const std::string& KX_GetOrigPath();

void KX_RasterizerDrawDebugLine(const mt::vec3 &from,const mt::vec3 &to,const mt::vec4 &color);
void KX_RasterizerDrawDebugCircle(const mt::vec3 &center, const float radius, const mt::vec4 &color,
const mt::vec3 &normal, int nsector);

#endif // __KX_GLOBALS_H__
26 changes: 13 additions & 13 deletions source/gameengine/Ketsji/KX_KetsjiEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1160,7 +1160,7 @@ void KX_KetsjiEngine::RenderDebugProperties()
if (m_flags & (SHOW_FRAMERATE | SHOW_PROFILE)) {
// Title for profiling("Profile")
// Adds the constant x indent (0 for now) to the title x margin
debugDraw.RenderText2D("Profile", mt::vec2(xcoord + const_xindent + title_xmargin, ycoord), white);
debugDraw.RenderText2d("Profile", mt::vec2(xcoord + const_xindent + title_xmargin, ycoord), white);

// Increase the indent by default increase
ycoord += const_ysize;
Expand All @@ -1170,38 +1170,38 @@ void KX_KetsjiEngine::RenderDebugProperties()

// Framerate display
if (m_flags & SHOW_FRAMERATE) {
debugDraw.RenderText2D("Frametime :",
debugDraw.RenderText2d("Frametime :",
mt::vec2(xcoord + const_xindent,
ycoord), white);

debugtxt = (boost::format("%5.2fms (%.1ffps)") % (tottime * 1000.0f) % (1.0f / tottime)).str();
debugDraw.RenderText2D(debugtxt, mt::vec2(xcoord + const_xindent + profile_indent, ycoord), white);
debugDraw.RenderText2d(debugtxt, mt::vec2(xcoord + const_xindent + profile_indent, ycoord), white);
// Increase the indent by default increase
ycoord += const_ysize;
}

// Profile display
if (m_flags & SHOW_PROFILE) {
for (int j = tc_first; j < tc_numCategories; j++) {
debugDraw.RenderText2D(m_profileLabels[j], mt::vec2(xcoord + const_xindent, ycoord), white);
debugDraw.RenderText2d(m_profileLabels[j], mt::vec2(xcoord + const_xindent, ycoord), white);

double time = m_logger.GetAverage((KX_TimeCategory)j);

debugtxt = (boost::format("%5.2fms | %d%%") % (time*1000.f) % (int)(time/tottime * 100.f)).str();
debugDraw.RenderText2D(debugtxt, mt::vec2(xcoord + const_xindent + profile_indent, ycoord), white);
debugDraw.RenderText2d(debugtxt, mt::vec2(xcoord + const_xindent + profile_indent, ycoord), white);

const mt::vec2 boxSize(50 * (time / tottime), 10);
debugDraw.RenderBox2D(mt::vec2(xcoord + (int)(2.2 * profile_indent), ycoord), boxSize, white);
const mt::vec2 boxSize(50 * (time / tottime), 9);
debugDraw.RenderBox2d(mt::vec2(xcoord + (int)(2.2 * profile_indent), ycoord), boxSize, white);
ycoord += const_ysize;
}
}

if (m_flags & SHOW_RENDER_QUERIES) {
debugDraw.RenderText2D("Render Queries :", mt::vec2(xcoord + const_xindent + title_xmargin, ycoord), white);
debugDraw.RenderText2d("Render Queries :", mt::vec2(xcoord + const_xindent + title_xmargin, ycoord), white);
ycoord += const_ysize;

for (unsigned short i = 0; i < QUERY_MAX; ++i) {
debugDraw.RenderText2D(m_renderQueriesLabels[i], mt::vec2(xcoord + const_xindent, ycoord), white);
debugDraw.RenderText2d(m_renderQueriesLabels[i], mt::vec2(xcoord + const_xindent, ycoord), white);

if (i == QUERY_TIME) {
debugtxt = (boost::format("%.2fms") % (((float)m_renderQueries[i].Result()) / 1e6)).str();
Expand All @@ -1210,7 +1210,7 @@ void KX_KetsjiEngine::RenderDebugProperties()
debugtxt = (boost::format("%i") % m_renderQueries[i].Result()).str();
}

debugDraw.RenderText2D(debugtxt, mt::vec2(xcoord + const_xindent + profile_indent, ycoord), white);
debugDraw.RenderText2d(debugtxt, mt::vec2(xcoord + const_xindent + profile_indent, ycoord), white);
ycoord += const_ysize;
}
}
Expand All @@ -1222,7 +1222,7 @@ void KX_KetsjiEngine::RenderDebugProperties()
if (m_flags & SHOW_DEBUG_PROPERTIES) {
// Title for debugging("Debug properties")
// Adds the constant x indent (0 for now) to the title x margin
debugDraw.RenderText2D("Debug Properties", mt::vec2(xcoord + const_xindent + title_xmargin, ycoord), white);
debugDraw.RenderText2d("Debug Properties", mt::vec2(xcoord + const_xindent + title_xmargin, ycoord), white);

// Increase the indent by default increase
ycoord += const_ysize;
Expand Down Expand Up @@ -1252,7 +1252,7 @@ void KX_KetsjiEngine::DrawDebugCameraFrustum(KX_Scene *scene, RAS_DebugDraw& deb
cam->GetWorldToCamera(), cam->GetCameraData()->m_perspective);
const mt::mat4 projmat = GetCameraProjectionMatrix(scene, cam, cameraFrameData.m_stereoMode, cameraFrameData.m_eye,
cameraFrameData.m_viewport, cameraFrameData.m_area);
debugDraw.DrawCameraFrustum(projmat, viewmat);
debugDraw.DrawCameraFrustum(projmat * viewmat);
}
}
}
Expand All @@ -1269,7 +1269,7 @@ void KX_KetsjiEngine::DrawDebugShadowFrustum(KX_Scene *scene, RAS_DebugDraw& deb
const mt::mat4 projmat(raslight->GetWinMat());
const mt::mat4 viewmat(raslight->GetViewMat());

debugDraw.DrawCameraFrustum(projmat, viewmat);
debugDraw.DrawCameraFrustum(projmat * viewmat);
}
}
}
Expand Down
13 changes: 10 additions & 3 deletions source/gameengine/Ketsji/KX_ObstacleSimulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,6 @@ void KX_ObstacleSimulation::DrawObstacles()
if (!m_enableVisualization)
return;
static const mt::vec4 bluecolor(0.0f, 0.0f, 1.0f, 1.0f);
static const mt::vec3 normal = mt::axisZ3;
static const int SECTORS_NUM = 32;
for (size_t i=0; i<m_obstacles.size(); i++)
{
Expand All @@ -317,8 +316,16 @@ void KX_ObstacleSimulation::DrawObstacles()
}
else if (m_obstacles[i]->m_shape==KX_OBSTACLE_CIRCLE)
{
KX_RasterizerDrawDebugCircle(m_obstacles[i]->m_pos, m_obstacles[i]->m_rad, bluecolor,
normal, SECTORS_NUM);
const float radius = m_obstacles[i]->m_rad;
const mt::vec3& pos = m_obstacles[i]->m_pos;
const float delta = M_PI * 2.0f / SECTORS_NUM;
for (unsigned short i = 0; i < SECTORS_NUM; ++i) {
const float t1 = delta * i;
const float t2 = delta * (i + 1);
const mt::vec3 p1 = mt::vec3(cosf(t1), sinf(t1), 0.0f) * radius + pos;
const mt::vec3 p2 = mt::vec3(cosf(t2), sinf(t2), 0.0f) * radius + pos;
KX_RasterizerDrawDebugLine(p1, p2, bluecolor);
}
}
}
}
Expand Down
24 changes: 12 additions & 12 deletions source/gameengine/Ketsji/KX_Scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,7 @@ void KX_Scene::DrawDebug(RAS_DebugDraw& debugDraw, const std::vector<KX_GameObje
{
const KX_DebugOption showBoundingBox = KX_GetActiveEngine()->GetShowBoundingBox();
if (showBoundingBox != KX_DebugOption::DISABLE) {
for (KX_GameObject *gameobj : m_objectlist) {
for (KX_GameObject *gameobj : objects) {
const mt::vec3& scale = gameobj->NodeGetWorldScaling();
const mt::vec3& position = gameobj->NodeGetWorldPosition();
const mt::mat3& orientation = gameobj->NodeGetWorldOrientation();
Expand All @@ -1181,15 +1181,15 @@ void KX_Scene::DrawDebug(RAS_DebugDraw& debugDraw, const std::vector<KX_GameObje
mt::vec4(1.0f, 0.0f, 1.0f, 1.0f));

// Render center in red, green and blue.
debugDraw.DrawLine(orientation * center * scale + position,
orientation * (center + mt::axisX3) * scale + position,
mt::vec4(1.0f, 0.0f, 0.0f, 1.0f));
debugDraw.DrawLine(orientation * center * scale + position,
orientation * (center + mt::axisY3) * scale + position,
mt::vec4(0.0f, 1.0f, 0.0f, 1.0f));
debugDraw.DrawLine(orientation * center * scale + position,
orientation * (center + mt::axisZ3) * scale + position,
mt::vec4(0.0f, 0.0f, 1.0f, 1.0f));
debugDraw.DrawLine(orientation * (center * scale) + position,
orientation * ((center + mt::axisX3) * scale) + position,
mt::vec4(1.0f, 0.0f, 0.0f, 1.0f));
debugDraw.DrawLine(orientation * (center * scale) + position,
orientation * ((center + mt::axisY3) * scale) + position,
mt::vec4(0.0f, 1.0f, 0.0f, 1.0f));
debugDraw.DrawLine(orientation * (center * scale) + position,
orientation * ((center + mt::axisZ3) * scale) + position,
mt::vec4(0.0f, 0.0f, 1.0f, 1.0f));
}
}

Expand Down Expand Up @@ -1238,15 +1238,15 @@ void KX_Scene::RenderDebugProperties(RAS_DebugDraw& debugDraw, int xindent, int
first = false;
}
}
debugDraw.RenderText2D(debugtxt, mt::vec2(xcoord + xindent, ycoord), white);
debugDraw.RenderText2d(debugtxt, mt::vec2(xcoord + xindent, ycoord), white);
ycoord += ysize;
}
else {
EXP_Value *propval = gameobj->GetProperty(propname);
if (propval) {
const std::string text = propval->GetText();
const std::string debugtxt = objname + ": '" + propname + "' = " + text;
debugDraw.RenderText2D(debugtxt, mt::vec2(xcoord + xindent, ycoord), white);
debugDraw.RenderText2d(debugtxt, mt::vec2(xcoord + xindent, ycoord), white);
ycoord += ysize;
}
}
Expand Down
Loading

2 comments on commit a23e65c

@joelgomes1994
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, @panzergame !
From this commit onwards I can't start the game engine. Blender simply closes, printing:
image
And standalone player stops responding. Windows 7 64 bit, MSVSC 2015 32 bit.
Any advice? Thanks.
And happy new year. ;)

@panzergame
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello,

I got issues too but only with intel GPUs, I'm investigating on.

Please sign in to comment.