草庐IT

c++ - 图形 API 的包装器

coder 2024-02-02 原文

我非常喜欢拥有一个具有适应能力的游戏引擎,不仅在它能做什么,而且在它如何处理新代码方面。最近,对于我的 graphics 子系统,我编写了一个 class 来重写,它的工作方式如下:

class LowLevelGraphicsInterface {
    virtual bool setRenderTarget(const RenderTarget* renderTarget) = 0;
    virtual bool setStreamSource(const VertexBuffer* vertexBuffer) = 0;
    virtual bool setShader(const Shader* shader) = 0;
    virtual bool draw(void) = 0;

    //etc. 
};

我的想法是创建一个在大多数图形 API 中通用的函数列表。然后,对于 DirectX11,我将创建一个新的子 class:

class LGI_DX11 : public LowLevelGraphicsInterface {
    virtual bool setRenderTarget(const RenderTarget* renderTarget);
    virtual bool setStreamSource(const VertexBuffer* vertexBuffer);
    virtual bool setShader(const Shader* shader);
    virtual bool draw(void);

    //etc. 
};

这些功能中的每一个都将直接与 DX11 交互。我确实意识到这里有一个间接层。人们是否被这个事实拒之门外?

这是一种广泛使用的方法吗?还有什么我可以/应该做的吗?可以选择使用 preprocessor 但这对我来说似乎很困惑。有人还向我提到了模板。大家怎么看?

最佳答案

如果虚拟函数调用成为问题,有一种编译时方法可以使用少量预处理器和编译器优化来删除虚拟调用。一种可能的实现是这样的:

用纯虚函数声明你的基础渲染器:

class RendererBase {
public:
    virtual bool Draw() = 0;
};

声明具体实现:

#include <d3d11.h>
class RendererDX11 : public RendererBase {
public:
    bool Draw();
private:
    // D3D11 specific data
};

创建一个 header RendererTypes.h 以根据您要与某些预处理器一起使用的类型转发声明您的渲染器:

#ifdef DX11_RENDERER
    class RendererDX11;
    typedef RendererDX11 Renderer;
#else
    class RendererOGL;
    typedef RendererOGL Renderer;
#endif

同时创建一个 header Renderer.h 以包含适合您的渲染器的 header :

#ifdef DX11_RENDERER
    #include "RendererDX11.h"
#else
    #include "RendererOGL.h"
#endif

现在,无论你在哪里使用渲染器,都将其称为 Renderer 类型,在头文件中包含 RendererTypes.hRenderer.h在你的 cpp 文件中。

您的每个渲染器实现都应该在不同的项目中。然后创建不同的构建配置以使用您要使用的任何渲染器实现进行编译。例如,您不想为 Linux 配置包含 DirectX 代码。

在调试版本中,可能仍会进行虚函数调用,但在发布版本中,它们会被优化掉,因为您永远不会通过基类接口(interface)进行调用。它仅用于在编译时为您的渲染器类强制执行通用签名。

虽然此方法确实需要一些预处理器,但它是最小的并且不会影响代码的可读性,因为它是孤立的并且仅限于某些 typedef 和包含。一个缺点是您不能使用此方法在运行时切换渲染器实现,因为每个实现都将构建为单独的可执行文件。但是,实际上并没有太多需要在运行时切换配置。

关于c++ - 图形 API 的包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26089090/

有关c++ - 图形 API 的包装器的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby-on-rails - ActionController::RoutingError: 未初始化常量 Api::V1::ApiController - 2

    我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc

  3. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  4. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  5. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  6. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  7. ruby-on-rails - Mandrill API 模板 - 2

    我正在使用Mandrill的RubyAPIGem并使用以下简单的测试模板:testastic按照Heroku指南中的示例,我有以下Ruby代码:require'mandrill'm=Mandrill::API.newrendered=m.templates.render'test-template',[{:header=>'someheadertext',:main_section=>'Themaincontentblock',:footer=>'asdf'}]mail(:to=>"JaysonLane",:subject=>"TestEmail")do|format|format.h

  8. ruby-on-rails - 在 Ruby (on Rails) 中使用 imgur API 获取图像 - 2

    我正在尝试使用Ruby2.0.0和Rails4.0.0提供的API从imgur中提取图像。我已尝试按照Ruby2.0.0文档中列出的各种方式构建http请求,但均无济于事。代码如下:require'net/http'require'net/https'defimgurheaders={"Authorization"=>"Client-ID"+my_client_id}path="/3/gallery/image/#{img_id}.json"uri=URI("https://api.imgur.com"+path)request,data=Net::HTTP::Get.new(path

  9. ruby-on-rails - 使用 HTTParty 的非常基本的 Rails 4.1 API 调用 - 2

    Rails相对较新。我正在尝试调用一个API,它应该向我返回一个唯一的URL。我的应用程序中捆绑了HTTParty。我已经创建了一个UniqueNumberController,并且我已经阅读了几个HTTParty指南,直到我想要什么,但也许我只是有点迷路,真的不知道该怎么做。基本上,我需要做的就是调用API,获取它返回的URL,然后将该URL插入到用户的数据库中。谁能给我指出正确的方向或与我分享一些代码? 最佳答案 假设API为JSON格式并返回如下数据:{"url":"http://example.com/unique-url"

  10. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

随机推荐