首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多个渲染系统

多个渲染系统
EN

Stack Overflow用户
提问于 2012-01-16 16:46:43
回答 4查看 4.3K关注 0票数 3

在不久的将来,我将开始开发一个游戏引擎。我想要包含的一个特性是拥有多个渲染系统,比如DirectX9/10/11和OpenGL。这样,使用这个引擎的游戏将能够支持更多的玩家,因为如果一个渲染系统不工作,它将恢复到不同的渲染系统。

所以我的问题是,我该怎么做呢?我研究了一下,发现Ogre3D使用了类似的东西,但我不知道他们是如何做到的。我基本上希望能够插入不同的渲染系统,并使用相同的代码来运行它。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-01-19 05:57:34

您可以创建一个接口类,使您可以进一步扩展您希望扩展到的API。

我已经在过去创建了一个DirectX911渲染器,我希望很快将其扩展到OpenGL。这项任务有很多确定性,但很容易解释它的基本工作原理。不幸的是,我的项目是闭源的,所以如果你对此有任何问题,请不要犹豫询问。

首先,您需要创建一个单独的项目作为.lib/.dll,我将其称为"RenderInterface“。这将包含用于顶点缓冲区、索引缓冲区、着色器以及最重要的IRenderInterface和IRenderUtility的基本接口,这些接口在后面的实现中可能包含诸如ID3D11DeviceContext和ID3D11Device之类的项。

我在"RenderInterface“项目中最重要的两个项目是IRenderInterface和IRenderUtility。这里的想法是让IRenderInterface来做繁重的工作,比如创建呈现目标、呈现和初始化应用程序接口。as IRenderUtility将执行更常见的操作,例如创建顶点/索引缓冲区、创建着色器和渲染。我在初始化和渲染时更频繁地传递IRenderUtility,而IRenderInterface很少传递。这是为了防止用户在不需要的时候进行意外操作。这个项目还将包括一些通用的structs\enum,它们将在整个代码库中使用。

然后,我创建了另一个项目,比如D3D11RenderInterface。此D3D11RenderInterface将包含IRenderInterface、IRenderUtlity、IVertexShader、IVertexBuffer等的实现。

一个非常简单的例子是

代码语言:javascript
复制
class IRenderUtility
{
public:
    virtual void Draw(unsigned int vertexCount, unsigned int vertexStartOffset) = 0;
};

class D3D11RenderUtility : public IRenderUtility
{
protected:
    ID3D11DeviceContext *mD3D11DeviceContext;
public:
    void Draw(unsigned int vertexCount, unsigned int vertexStartOffset)
    {
        mD3D11DeviceContext->Draw(vertexCount, vertexStartOffset);
    };
};

这是通过在调用IRenderUtility::Draw之前调用IRenderUtility来设置VertexBuffer和IVertexBuffer的。

然后,在您的应用程序中将只需要加载RenderInterface项目和应用程序接口实现。还有其他方法可以做到这一点,比如在你的代码库中使用#定义代码,但是imo,这太混乱了。

票数 5
EN

Stack Overflow用户

发布于 2012-01-16 18:59:47

使用C++接口的强大功能!

创建定义呈现系统接口的抽象

代码语言:javascript
复制
class Renderer
{
 //...
    virtual void DrawRect(Color c, Vector2 Pos) = 0;
 //...
}

然后在每个渲染系统中实现它:

代码语言:javascript
复制
class D3DRenderer : Renderer
{
    void DrawRect(Color c, Vector2 Pos);
}

这种方法快速、简单、高效,这就是为什么它在许多游戏引擎中使用的原因。应该注意是,在构建这样的东西(甚至像行较大矩阵与列较大矩阵这样的小事情)时,确实需要了解某些API限制。

票数 5
EN

Stack Overflow用户

发布于 2012-01-16 16:55:35

使用预处理器

一种解决方案是使用预处理器。

代码语言:javascript
复制
#ifdef DIRECT_X
// something for DX
#else
// something for OpenGL etc.
#endif

像SDL这样的库也使用这种方法。如果你想使用渲染系统,只需简单地#define它。此外,从跨平台兼容性来看,您可能需要使用特定于平台的宏。参见this

使用单独的翻译单元

一种更好的方法是将特定于平台的方法放在单独的翻译单元中。这将使代码更整洁、更具可读性,更易于开发和维护。

例如:

代码语言:javascript
复制
class Rectangle
{
     public:
         void draw(int,int,int,int);
};

rectangle_dx_9.cpp

代码语言:javascript
复制
#include "rectangle.hpp"
void
Rectangle ::
draw(int upper_left_corner_x, int upper_left_corner_y,
            unsigned int length, unsigned int width)
{
// Direct X 9 specific code here.
}

rectangle_open_gl.cpp

代码语言:javascript
复制
#include "rectangle.hpp"
void
Rectangle ::
draw(int upper_left_corner_x, int upper_left_corner_y,
            unsigned int length, unsigned int width)
{
// OpenGL specific code here.
}

等。

现在,对于DirectX9,您需要做的就是将构建过程配置为使用rectangle_dx_9.cpp,,而对于OpenGL,则使用rectangle_open_gl.cpp.

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8877471

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档