直接模式,渲染器不可知论,轻巧的调试图形API,用于C ++。
该软件在公共领域。如果未确认该奉献精神,您将获得永久的,不可撤销的许可,以复制,分发和修改源代码,如您所见。
提供源代码“原样”,而无需任何明示或暗示的保证。不需要归因,但是对作者的提及表示赞赏。
调试绘制是一个单一源文件库,因此“标题”正向声明和实现包含在同一文件中( debug_draw.hpp )。这应该有助于与您自己的项目进行部署和集成。您所要做的就是#include库中的库文件之一,并在该文件中定义DEBUG_DRAW_IMPLEMENTATION以生成实现。您还可以在其他地方包含图书馆。当未定义DEBUG_DRAW_IMPLEMENTATION时,它充当普通的C ++标头文件。例子:
在my_program.cpp中:
# define DEBUG_DRAW_IMPLEMENTATION
# include " debug_draw.hpp "现在,在my_program.hpp或任何其他标头或源文件中,您可以将其包含在普通的C ++标头:
# include " debug_draw.hpp "就是这样,您现在应该能够在自己的应用程序中构建调试。
Debug Draw并不是关于覆盖渲染器API的假设,因此它可以很容易地与Direct3D或OpenGL或您选择的任何其他渲染引擎集成在一起。所需的只是您为dd::RenderInterface Abstrack类提供实现,该类别为绘制点,线条和角色字形的基本方法提供了调试绘制。以下是dd::RenderInterface的样子:
class RenderInterface
{
public:
virtual void beginDraw ();
virtual void endDraw ();
virtual GlyphTextureHandle createGlyphTexture ( int width, int height, const void * pixels);
virtual void destroyGlyphTexture (GlyphTextureHandle glyphTex);
virtual void drawPointList ( const DrawVertex * points, int count, bool depthEnabled);
virtual void drawLineList ( const DrawVertex * lines, int count, bool depthEnabled);
virtual void drawGlyphList ( const DrawVertex * glyphs, int count, GlyphTextureHandle glyphTex);
virtual ~RenderInterface () = 0 ;
};并非所有方法都必须实现,而是决定支持哪些功能!查看RenderInterface声明的源代码。对每种方法都进行了很好的评论,并描述了您应该实施的预期行为。要使用诸如OpenGL之类的标准API的RenderInterface的参考实现,请参阅此项目中的samples/目录。
一旦您为渲染器实现了RenderInterface ,开始使用调试绘制之前,您需要做的就是调用dd::initialize()将其传递给您的自定义RenderInterface :
MyRenderInterface renderIface;
dd::initialize (&renderIface);但是请注意,调试绘制批次会减少RenderInterface的调用数量,因此绘图只会在您调用dd::flush()时实际上进行,通常在帧的末端完成,然后再翻转屏幕缓冲区:
// You only have to pass the current time if you have timed debug
// draws in the queues. Otherwise just omit the argument or pass 0.
dd::flush (getTimeMilliseconds());因此,整体设置应该看起来如下:
class MyRenderInterface : public dd ::RenderInterface
{
// Cherrypick the methods you want to implement or implement them all
...
};
int main ()
{
MyRenderInterface renderIface;
dd::initialize (&renderIface);
while (!quitting)
{
// Any other drawing that you already do
...
// Call any dd:: functions to add debug primitives to the draw queues
...
dd::flush ( getTimeMilliseconds ());
// Swap buffers to present the scene
...
}
dd::shutdown ();
}Debug Draw提供了多个用于库配置和自定义的编译器开关。在debug_draw.hpp中查看文档以获取所有开关列表以及每个开关的详细说明。
图书馆的语言要求很少。它的主要目标之一是无痛地整合和便携。唯一的要求是最新的C ++编译器,并具有最小的标准库支持。假定一些C ++ 11功能,例如nullptr和<cstdint> 。样本包括更重用C ++标准库,以演示使用线程的调试绘制使用情况。
不使用RTTI和C ++异常,因此您在将库与禁用这些功能的项目集成在一起时应该没有问题。
内存足迹也很小,您可以通过预处理器指令管理将内部队列承诺的内存量。目前,我们仅在库启动时分配少量的动态内存,以解压缩字体字形以用于调试文本绘图功能以及绘制队列和库上下文数据。
默认情况下,Debug Draw将在内部使用静态全局上下文,从而提供一个不是线程安全的程序风格的API。这是最容易使用和设置的“经典”调试模式,但是该库还支持其他两个在编译时间安全且可配置的模式:
DEBUG_DRAW_PER_THREAD_CONTEXT :如果在实现之前定义了这一点,则库将使用线程 - 本地上下文而不是全局共享默认值。这允许从不同线程调用库,因为每个线程都会保留其私人上下文并绘制队列。此模式提供了相同的公共库接口,但需要编译器的TLS(线程本地存储)支持。
DEBUG_DRAW_EXPLICIT_CONTEXT :如果在实现之前定义了这一点,则库希望用户为上下文提供句柄。此模式揭示了dd::ContextHandle类型,并更改库中的每个功能以将此句柄作为第一个参数。此模式使库完全无状态,因此每个调用库中的渲染线程都可以创建并维护其自己的调试绘制实例。
显式上下文模式是一种更清洁,更具功能风格的API,应该是新用户的首选。过程模式仍然保留为与较旧的库版本兼容的默认模式,但是建议您通过将#define DEBUG_DRAW_EXPLICIT_CONTEXT与DEBUG_DRAW_IMPLEMENTATION一起添加#Debug_draw_draw_explitic_context来使用显式上下文模式。将来,程序性的状态API将被贬低,以明确的弃用。
在其中心绘制一个带有一组坐标轴的盒子:
const ddVec3 boxColor = { 0 . 0f , 0 . 8f , 0 . 8f };
const ddVec3 boxCenter = { 0 . 0f , 0 . 0f , 3 . 0f };
dd::box (boxCenter, boxColor, 1 . 5f , 1 . 5f , 1 . 5f );
dd::cross (boxCenter, 1 . 0f );要可视化矩阵变换,您可以使用dd::axisTriad()将转换绘制为三个箭头:
const ddMat4x4 transform = { // The identity matrix
1 . 0f , 0 . 0f , 0 . 0f , 0 . 0f ,
0 . 0f , 1 . 0f , 0 . 0f , 0 . 0f ,
0 . 0f , 0 . 0f , 1 . 0f , 0 . 0f ,
0 . 0f , 0 . 0f , 0 . 0f , 1 . 0f
};
dd::axisTriad (transform, 0 . 3f , 2 . 0f );可以在samples/目录中找到有关如何与您自己的渲染器集成调试的更复杂的样本和示例。公共API中提供的每个功能在标题文件中也有很好的记录。在图书馆导出的每个公共功能的原型之前,您会发现描述性标头评论。