Unity3Dダイレクトレンダリングコード
は通常、ビジュアルプログラミングを使用するUnity3Dなどの開発エンジンです。ツリー構造を通じて3次元世界のノードを管理し、エンティティモデルをノードにバインドし、3次元モデルの空間関係を整理します。ノード座標を介して、カメラノードを介して透視投影計算を実行します。ビジュアルコンテンツを2D画面空間にレンダリングします。同時に、カメラはRenderToTextureメソッドを提供して、3次元世界の一部をテクスチャにレンダリングし、この中間テクスチャを使用して、車のバックミラーを実装するなど、ターゲット空間にレンダリングします。
作業上のニーズにより、以前のVC6プロジェクトを新しいバージョンに移行する必要があります*(VC6は64ビットプログラミングをサポートしていないため、プログラムメモリが不足します。現在の緊急の解決策は、editbin / LARGEADDRESSAWARExxxを使用してpeファイルを編集することです。 .exe、win32プログラムの2Gメモリを突破する制限、このメソッドは最大で3Gマルチメモリを使用します)*、およびVC6をVS移植の試行の任意のバージョンに使用するには、多くのコンパイルエラーと構文の非互換性に対処する必要があります問題は、Unity3Dに直接移植するほど良くはなく、ビジュアルプログラミングの扱いを楽しむこともできます。
Unity3Dを使用してC ++ DirectXレンダリングパイプラインコード関数を実装する場合、エンジンによって提供されるノードモードとカメラモードは煩雑であり、より低レベルのレンダリング方法が必要です。
C ++によって実装されるコアレンダリングコード:
Void CRenderToTextureWindow::OnUpdateSurface()
{
OnUpdateSurfaceBegin();
OnUpdateSurfaceDrawing();
OnUpdateSurfaceEnd(m_bDownloadToVideoTexture ? m_pDataTexture : Null);
CWindow::OnUpdateSurface();
}
OnUpdateSurfaceBeginは、レンダリングパイプラインの準備を実現します
Void CRenderToTextureWindow::OnUpdateSurfaceBegin(CTexture *pRenderTarget/* = Null*/, COLORREF color/* = 0x00*/, IDirect3DSurface9 *pD3DDepthStencilSurface/* =Null*/)
{
HRESULT hr = S_OK;
// Render video to texture
if (Null == pRenderTarget) {
pRenderTarget = m_pRenderTarget;
}
if (Null == pD3DDepthStencilSurface) {
pD3DDepthStencilSurface = m_pD3DDepthStencilSurface;
}
ASSERT(Null != pRenderTarget->GetSafeTexture());
m_pD3DTexture = pRenderTarget->GetSafeTexture();
m_pD3DTarget = Null;
m_pD3DBackSurface = Null;
m_pD3DBackDepthStencilSurface = Null;
D3D::GetD3DDevice()->GetRenderTarget(0, &m_pD3DBackSurface);
D3D::GetD3DDevice()->GetDepthStencilSurface(&m_pD3DBackDepthStencilSurface);
m_pD3DTexture->GetSurfaceLevel(0, &m_pD3DTarget);
D3D::GetD3DDevice()->SetRenderTarget(0, m_pD3DTarget);
D3D::GetD3DDevice()->SetDepthStencilSurface(pD3DDepthStencilSurface);
D3D::GetD3DDevice()->Clear(0, NULL, D3DCLEAR_TARGET/*|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL*/, color, 1.0f, 0);
D3D::GetD3DDevice()->BeginScene();
}
OnUpdateSurfaceEndは、レンダリングパイプラインの終了後に仕上げ作業を実現します
Void CRenderToTextureWindow::OnUpdateSurfaceEnd(CTexture *pDataTexture/* = Null*/)
{
HRESULT hr = S_OK;
D3D::GetD3DDevice()->EndScene();
D3D::GetD3DDevice()->SetDepthStencilSurface(m_pD3DBackDepthStencilSurface);
D3D::GetD3DDevice()->SetRenderTarget(0, m_pD3DBackSurface);
// download data target's data
if (Null != pDataTexture) {
LPDIRECT3DSURFACE pD3DDataSurface = Null;
pDataTexture->GetSafeTexture()->GetSurfaceLevel(0, &pD3DDataSurface);
if (FAILED(hr = D3D::GetD3DDevice()->GetRenderTargetData(m_pD3DTarget, pD3DDataSurface))) {
TRACE(DXGetErrorString(hr));
}
SAFE_RELEASE(pD3DDataSurface);
}
SAFE_RELEASE(m_pD3DTarget);
SAFE_RELEASE(m_pD3DBackSurface);
SAFE_RELEASE(m_pD3DBackDepthStencilSurface);
}
OnUpdateSurfaceDrawingは、サブウィンドウの走査とレンダリングを実装します
Void CRenderToTextureWindow::OnUpdateSurfaceDrawing()
{
// RENDER CODE
this->SetRoot(True);
CWindow *pChild = FirstChild();
while (Null != pChild) {
if (pChild->IsVisibled() && pChild->GetRenderLevel() == GetRenderLevel()+1) {
GetApplication()->GetWindowsManager()->UpdateWindow(pChild);
}
pChild = NextChild(pChild);
}
this->SetRoot(False);
}
ウィンドウトラバーサルとレンダリングのためのUpdateWindow関数
Void CWindowsManager::UpdateWindow( CWindow *pWindow )
{
...
pWindow->OnEraseBkgnd() ;
pWindow->OnUpdate() ;
// update child
CWindow * pChild = pWindow->FirstChild() ;
while ( Null != pChild ) {
CWindow *pNext = pWindow->NextChild( pChild ) ;
if ( pChild->IsVisibled()) {
UpdateWindow( pChild ) ;
}
pChild = pNext ;
}
pWindow->OnUpdateFrgnd() ;
pWindow->OnUpdateNcFrgnd() ;
}
CWindow :: OnUpdateウィンドウレンダリングコード
Void CWindow::OnUpdate()
{
CRender *pRender = GetBkgndRender() ;
if ( Null != pRender ) {
pRender->SetAlpha( GetEnvironmentAlpha() ) ;
pRender->SetRenderOrigin( C2D(CPoint(0,0)) ) ;
pRender->Render() ;
}
}
C2DGridRender :: Renderはメッシュエンティティをレンダリングします
Void C2DGridRender::Render()
{
if ( !IsVisibled() ) return; // donnot render if unvisibled
if (Null == m_pD3DVertexBuffer) {
return;
}
if (Null == m_pD3DIndexBuffer) {
return;
}
LPCUSTOMVERTEX pVertices;
if (SUCCEEDED(m_pD3DVertexBuffer->Lock(0, sizeof(CUSTOMVERTEX)*GetNumVertices(), (void **)&pVertices, 0))) {
memcpy(pVertices, &m_Vertices[0], sizeof(CUSTOMVERTEX)*GetNumVertices());
CMatrix4 mat = m_matRenderRect * m_matTransform;
// transform each vertices
for ( int i = 0 ; i < GetNumVertices() ; ++ i ) {
D3DXVec4Transform((LPD3DXVECTOR4)&pVertices[i].vector,
(LPD3DXVECTOR4)&pVertices[i].vector, mat);
pVertices[i].x += (float)m_ptOrigin.x;
pVertices[i].y += (float)m_ptOrigin.y;
}
m_pD3DVertexBuffer->Unlock() ;
}
CClipper *pClipper = GetApplication()->GetWindowsManager()->GetClipper();
OnBeginRender();
LPDIRECT3DDEVICE pD3DDevice = GetD3DDevice();
pD3DDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
pD3DDevice->SetTexture(0, m_pTexture1->GetSafeTexture());
pD3DDevice->SetStreamSource(0, m_pD3DVertexBuffer, 0, sizeof(CUSTOMVERTEX));
if (Null != m_pTexture2) {
pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE) ;
pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT) ;
pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE) ;
pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT) ;
pD3DDevice->SetTexture(1, m_pTexture2->GetSafeTexture());
}
// draw
pD3DDevice->SetIndices(m_pD3DIndexBuffer);
pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
0,
0,
GetNumVertices(),
0,
GetNumFaces());
if (Null != m_pTexture2) {
pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
}
OnEndRender() ;
}
Unity3Dエンジンは、比較的低レベルのレンダリングパイプラインも提供します。これにより、レンダリングパイプライン命令を介して直接メッシュレンダリングが可能になります。
移植後のメインレンダリングロジック
protected override void OnUpdateSurface()
{
base.OnUpdateSurface();
RenderTexture save = OnUpdateSurfaceBegin(targetTexture, Color.black);
OnUpdateSurfaceDrawing();
OnUpdateSurfaceEnd(save, null);
}
OnUpdateSurfaceBeginは、レンダリングパイプラインの準備を実現します
protected virtual RenderTexture OnUpdateSurfaceBegin(RenderTexture target, Color color)
{
GL.PushMatrix();
RenderTexture save = RenderTexture.active;
Graphics.SetRenderTarget(target);
GL.LoadPixelMatrix(0, target.width, 0, target.height);
CApplicationSetting.Instance.drawBuffer.Clear();
CApplicationSetting.Instance.drawBuffer.ClearRenderTarget(true, true, color);
Graphics.ExecuteCommandBuffer(CApplicationSetting.Instance.drawBuffer);
return save;
}
OnUpdateSurfaceEndは、レンダリングパイプラインの終了後に仕上げ作業を実現します
protected virtual void OnUpdateSurfaceEnd(RenderTexture save, Texture dataTexture)
{
GL.PopMatrix();
Graphics.SetRenderTarget(save);
// download data target's data
if (null != dataTexture)
{
}
}
OnUpdateSurfaceDrawingは、サブウィンドウの走査とレンダリングを実装します
protected virtual void OnUpdateSurfaceDrawing()
{
// RENDER CODE
SetRoot(true);
for (int i = 0; i < transform.childCount; ++i)
{
CWindow child = transform.GetChild(i).GetComponent<CWindow>();
if (null != child && child.isActiveAndEnabled)
{
CApplicationSetting.Instance.UpdateWindow(child);
}
}
SetRoot(false);
}
ウィンドウトラバーサルとレンダリングのためのUpdateWindow関数
public void UpdateWindow(CWindow window)
{
window.OnEraseBkgnd();
window.OnUpdate();
for (int i = 0; i < window.transform.childCount; ++i)
{
CWindow child = window.transform.GetChild(i).GetComponent<CWindow>();
if (null != child)
{
UpdateWindow(child);
}
}
window.OnUpdateFrgnd();
window.OnUpdateNcFrgnd();
}
OnUpdateウィンドウレンダリングコード
protected virtual void OnUpdate()
{
if (null != Backgnd)
{
Backgnd.Render();
}
}
レンダリングメッシュエンティティをレンダリングする
public override void Render()
{
base.Render();
material.mainTexture = Texture;
material.SetPass(0);
if(Vector3.zero != m_Origin)
{
CApplicationSetting.Instance.drawBuffer.DrawMesh(mesh, Matrix4x4.Translate(m_Origin), material);
}
else
{
CApplicationSetting.Instance.drawBuffer.DrawMesh(mesh, Matrix4x4.identity, material);
}
Graphics.ExecuteCommandBuffer(CApplicationSetting.Instance.drawBuffer);
}
Unity3Dエンジンのビジュアルプログラミングはないようですが、実際にはありません。ディレクトリツリーとパネルを介して操作プロセスを理解するのに役立ちます。
![実行中の値を表示できます。レンダリングマップをクリックしてレンダリング結果を表示します](https://img-blog.csdnimg.cn/20210113224608321.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10 、text_aHR0cHM6Ly9ibG9FxXQMZMD4LmN0Zsize color_FFFFFF、t_70
postscript:このプログラムの機能の大部分は、ウィンドウを介したレイヤーブレンディング操作、つまりテクスチャへの多数のレンダリングを実行することです。Unity3Dエンジンを介してノードの表示範囲を管理することは困難です。カメラとテクスチャへのレンダリング、および多数の中間状態の視覚化エンティティは3次元の世界に積み重ねられており、効率は高くありません。