引擎技术研究之渲染到目标

渲染到目标,通俗地说就是把特定场景的物体放在目标上显示。这个目标可以是纹理,窗口等。本文介绍的是把场景渲染到纹理,并以图片的形式保存起来。

其原理如下:

在初始化时创建一纹理Texture,获取指向该纹理的指针,接着创建深度表面,并获取指向其的指针DepthSurface。在渲染时先获取系统的默认的渲染目标和深度模板表面,再设置Texture的表面为渲染目标,并通过DepthSurface设置深度模板表面,接着渲染场景中的物体,并保存该纹理到制定路径,最后恢复系统的默认的渲染目标和深度模板表面。

二 具体步骤:

设计一渲染目标类RenderTarget,负责纹理,深度表面的创建,以及设置渲染目标,深度表面等。现介绍其实现:

初始化函数:该函数接收外界传入的widthheight作为纹理的宽和高,

其功能有:1 是根据widthheight创建纹理,调用IDirect3DDevice9接口的

CreateTexture(width,height,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,

D3DPOOL_DEFAULT,&mpRTT,NULL);

mpRTT为指向该纹理的指针。

2 根据widthheigh创建深度表面,调用IDirect3DDevice9接口的

CreateDepthStencilSurface(width,height,D3DFMT_D24S8,

D3DMULTISAMPLE_NONE,0,TRUE,&mpDepthSurface,NULL);

mpDepthSurface为指向该深度表面的指针

渲染函数:首先要获取一个系统设备指针device,定义并初始化IDirect3DSurface9类型指针 pOldZBufferpRenderSurface pBackBuffer

接着获取系统默认的渲染目标device->GetRenderTarget(0,&pBackBuffer);

获取系统d3d默认深度表面device->GetDepthStencilSurface(&pOldZBuffer);

设置mpRTT纹理的表面作为渲染目标

mpRTT->GetSurfaceLevel(0,&pRenderSurface);

device->SetRenderTarget(0,pRenderSurface);

再设置深度表面 device->SetDepthStencilSurface(mpDepthSurface);

执行场景物体的渲染操作后,再恢复系统默认设置

device->SetRenderTarget(0,pBackBuffer);

device->SetDepthStencilSurface(pOldZBuffer);

最后释放引用 SAFE_RELEASE(pBackBuffer);SAFE_RELEASE(pRenderSurface);

三 监听器模式实现:

现讨论一下场景物体的渲染部分:

因某些场景的不同而需要进行特殊的渲染操作,这样就要求根据不同场景调用不同的渲染流程。这样需用到一设计模式:监听器模式。

其原理如下:先设置调用哪一种监听器,再根据不同的监听器执行其相应的渲染操作。

实现如下:

1 先定义一虚基类:Listener,定义两个纯虚函数:

virtual void Execute()=0; virtual void AfterExecute()=0;

再定义两个Listener的子类:ReflectListenerCurrentSceneListener 并改写其纯虚函数,可在Execute()里进行场景物体模型的渲染操作,AfterExecute()执行相关的重置操作。

2 在场景类Scene的私有成员列表中定义:

RenderTarget *mpReflectTarget;

ReflectListener *mpSceneRenderer;

RenderTarget *m_pCurrentSceneTarget;

CurrentSceneListener *m_pCurrentListener;

即一个监听器对应一个渲染目标。

3 RenderTarget私有成员列表中定义:Listener *mpRenderListener;

并添加对应的设置监听器的接口函数 SetRenderEvent(Listener *pListener)

再添加一成员函数__Rend(),其在RenderTarget类的Rend()中调用,__Rend()首先要进行清理操作:执行IDirect3DDevice9接口的

Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(255,255,255),1.0f, 0);

再执行:mpRenderListener->Execute();mpRenderListener->AfterExecute();

这样可根据不同的监听器执行不同的渲染流程。

4 在场景类的初始化函数执行:

m_pCurrentListener=new CurrentSceneListener();

m_pCurrentSceneTarget=new RenderTarget();

m_pCurrentSceneTarget->Initial("currentsceneTarget",1024,1024);

m_pCurrentSceneTarget->SetRenderEvent(m_pCurrentListener);

同理可使用ReflectListener监听器。

5 因本文描述的是渲染目标到纹理,并以图片的格式保存,那可在Scene的析构函数里执行场景物体的渲染操作: m_pCurrentSceneTarget->Render();

这样保存的是运行界面关闭时的那个场景画面。

四 概括一下流程:

Scene的初始化函数执行RenderTargetInitial(),接着设置监听器SetRenderEvent(),再在Scene的析构函数里执行RenderTargetRender()Render()调用RenderTarget__Render(), __Render()调用相应监听器的 Execute() AfterExecute(),在Execute()进行场景物体的渲染操作。

你可能感兴趣的:(技术)