// // Use stencil buffer as a mask. draw shadows to the scene // HRESULT DrawShadow(IDirect3DDevice9* pd3dDevice) { IDirect3DStateBlock9* pStateBlock = NULL; pd3dDevice->CreateStateBlock(D3DSBT_ALL, &pStateBlock); // Set renderstates (disable z-buffering, enable stencil, disable fog, and // turn on alphablending) SetRenderStateSafe(pd3dDevice, D3DRS_ZENABLE, FALSE); SetRenderStateSafe(pd3dDevice, D3DRS_STENCILENABLE, TRUE); SetRenderStateSafe(pd3dDevice, D3DRS_FOGENABLE, FALSE); SetRenderStateSafe(pd3dDevice, D3DRS_ALPHABLENDENABLE, TRUE); SetRenderStateSafe(pd3dDevice, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); SetRenderStateSafe(pd3dDevice, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); SetRenderStateSafe(pd3dDevice, D3DRS_ALPHATESTENABLE, FALSE); // Only write where stencil val >= 1 (count indicates # of shadows that // overlap that pixel) SetRenderStateSafe(pd3dDevice, D3DRS_STENCILREF, 0x1); SetRenderStateSafe(pd3dDevice, D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL); SetRenderStateSafe(pd3dDevice, D3DRS_CULLMODE, D3DCULL_CCW); // counter clock-wise render triangles pd3dDevice->EndStateBlock(&pStateBlock); // Draw a big, gray square pd3dDevice->SetFVF( SHADOWVERTEX::FVF ); pd3dDevice->SetStreamSource( 0, g_pBigSquareVB, 0, sizeof(SHADOWVERTEX) ); pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 ); pStateBlock->Apply(); SAFE_RELEASE(pStateBlock); return S_OK; }
// renderStage1 - Render grass and shadows over near features, and write depth texture for scene 0 void DistantLand::renderStage1() { DECLARE_MWBRIDGE IDirect3DStateBlock9 *stateSaved; UINT passes; ///LOG::logline("Stage 1 prims: %d", recordMW.size()); if(!isRenderCached) { // Save state block manually since we can change FVF/decl device->CreateStateBlock(D3DSBT_ALL, &stateSaved); // TODO: Locate this properly if(isDistantCell()) cullGrass(&mwView, &mwProj); if(isDistantCell()) { // Render over Morrowind domain effect->Begin(&passes, D3DXFX_DONOTSAVESTATE); // Draw grass with shadows if(Configuration.MGEFlags & USE_GRASS) { effect->BeginPass(PASS_RENDERGRASSINST); renderGrassInst(); effect->EndPass(); } // Overlay shadow onto Morrowind objects if((Configuration.MGEFlags & USE_SHADOWS) && mwBridge->CellHasWeather()) { effect->BeginPass(PASS_RENDERSHADOW); renderShadow(); effect->EndPass(); } effect->End(); } // Depth texture from recorded renders and distant land effectDepth->Begin(&passes, D3DXFX_DONOTSAVESTATE); renderDepth(); effectDepth->End(); // Restore render state stateSaved->Apply(); stateSaved->Release(); } recordMW.clear(); }
// // Render shadow information to stencil buffer // HRESULT RenderShadow(IDirect3DDevice9* pd3dDevice) { IDirect3DStateBlock9* pStateBlock = NULL; pd3dDevice->CreateStateBlock(D3DSBT_ALL, &pStateBlock); // Disable z-buffer writes (note: z-testing still occurs), and enable the // stencil-buffer SetRenderStateSafe(pd3dDevice, D3DRS_ZWRITEENABLE, FALSE); SetRenderStateSafe(pd3dDevice, D3DRS_STENCILENABLE, TRUE); // If ztest passes, inc/decrement stencil buffer value SetRenderStateSafe(pd3dDevice, D3DRS_STENCILREF, 0x1); SetRenderStateSafe(pd3dDevice, D3DRS_STENCILPASS, D3DSTENCILOP_INCR); // Make sure that no pixels get drawn to the frame buffer SetRenderStateSafe(pd3dDevice, D3DRS_ALPHABLENDENABLE, TRUE); SetRenderStateSafe(pd3dDevice, D3DRS_SRCBLEND, D3DBLEND_ZERO); SetRenderStateSafe(pd3dDevice, D3DRS_DESTBLEND, D3DBLEND_ONE); // TODO: Check device caps if(true) { // With 2-sided stencil, we can avoid rendering twice: SetRenderStateSafe(pd3dDevice, D3DRS_TWOSIDEDSTENCILMODE, TRUE); SetRenderStateSafe(pd3dDevice, D3DRS_CCW_STENCILPASS, D3DSTENCILOP_DECR); SetRenderStateSafe(pd3dDevice, D3DRS_CULLMODE, D3DCULL_NONE); // Draw both sides of shadow volume in stencil/z only g_baseShadow.Render( pd3dDevice ); SetRenderStateSafe(pd3dDevice, D3DRS_TWOSIDEDSTENCILMODE, FALSE); } else { // Draw front-side of shadow volume in stencil/z only SetRenderStateSafe(pd3dDevice, D3DRS_CULLMODE, D3DCULL_CCW); g_baseShadow.Render( pd3dDevice ); // Now reverse cull order so back sides of shadow volume are written. SetRenderStateSafe(pd3dDevice, D3DRS_CULLMODE, D3DCULL_CW); // Decrement stencil buffer value SetRenderStateSafe(pd3dDevice, D3DRS_STENCILPASS, D3DSTENCILOP_DECR); // Draw back-side of shadow volume in stencil/z only g_baseShadow.Render( pd3dDevice ); } pd3dDevice->EndStateBlock(&pStateBlock); pStateBlock->Apply(); SAFE_RELEASE(pStateBlock); return S_OK; }
// renderStageBlend - Blend between MGE distant land and Morrowind, rendering caustics first so it blends out void DistantLand::renderStageBlend() { DECLARE_MWBRIDGE IDirect3DStateBlock9 *stateSaved; UINT passes; if(isRenderCached) return; // Save state block manually since we can change FVF/decl device->CreateStateBlock(D3DSBT_ALL, &stateSaved); effect->Begin(&passes, D3DXFX_DONOTSAVESTATE); // Render caustics if(mwBridge->IsExterior() && Configuration.DL.WaterCaustics > 0) { D3DXMATRIX m; IDirect3DTexture9 *tex = PostShaders::borrowBuffer(0); D3DXMatrixTranslation(&m, eyePos.x, eyePos.y, mwBridge->WaterLevel()); effect->SetTexture(ehTex0, tex); effect->SetTexture(ehTex1, texWater); effect->SetTexture(ehTex3, texDepthFrame); effect->SetMatrix(ehWorld, &m); effect->SetFloat(ehAlphaRef, Configuration.DL.WaterCaustics); effect->CommitChanges(); effect->BeginPass(PASS_RENDERCAUSTICS); PostShaders::applyBlend(); effect->EndPass(); } // Blend MW/MGE if(isDistantCell() && (~Configuration.MGEFlags & NO_MW_MGE_BLEND)) { effect->SetTexture(ehTex0, texDistantBlend); effect->SetTexture(ehTex3, texDepthFrame); effect->CommitChanges(); effect->BeginPass(PASS_BLENDMGE); PostShaders::applyBlend(); effect->EndPass(); } effect->End(); stateSaved->Apply(); stateSaved->Release(); }
void DevState::releaseAll() { ods("D3D9: Release All"); releaseData(); if (pSB) pSB->Release(); pSB = NULL; }
void CState::Save() { if( !m_StateBlock && m_D3DDev ) m_D3DDev->CreateStateBlock(D3DSBT_ALL, &m_StateBlock); if( m_StateBlock ) m_StateBlock->Capture(); }
void Overlay::RenderMeshes() { if(g_Globals.UsingOverlay && _Meshes.Length() > 0) { IDirect3DStateBlock9* pStateBlock = NULL; _Device->CreateStateBlock( D3D9Base::D3DSBT_ALL, &pStateBlock ); const UINT MaxTextureSlots = 8; for(UINT TextureIndex = 0; TextureIndex < MaxTextureSlots; TextureIndex++) { _Device->SetTexture(TextureIndex, NULL); } D3D9Base::D3DXMATRIXA16 NewTransformWorld, NewTransformView, NewTransformProjection; NewTransformWorld = Matrix4ToD3DXMATRIX(Matrix4::Identity()); NewTransformView = Matrix4ToD3DXMATRIX(Matrix4::Identity()); NewTransformProjection = Matrix4ToD3DXMATRIX(_MeshTransform); _Device->SetTransform(D3DTS_WORLD, &NewTransformWorld); _Device->SetTransform(D3D9Base::D3DTS_VIEW, &NewTransformView); _Device->SetTransform(D3D9Base::D3DTS_PROJECTION, &NewTransformProjection); _Device->SetRenderState(D3D9Base::D3DRS_ALPHABLENDENABLE, FALSE); //_Device->SetRenderState(D3D9Base::D3DRS_ZENABLE, D3D9Base::D3DZB_TRUE); _Device->SetRenderState(D3D9Base::D3DRS_ZENABLE, D3D9Base::D3DZB_FALSE); _Device->SetRenderState(D3D9Base::D3DRS_LIGHTING, FALSE); _Device->SetRenderState(D3D9Base::D3DRS_ZFUNC, D3D9Base::D3DCMP_ALWAYS); _Device->SetRenderState(D3D9Base::D3DRS_ALPHATESTENABLE, FALSE); _Device->SetRenderState(D3D9Base::D3DRS_CULLMODE, D3D9Base::D3DCULL_NONE); const DWORD D3DMeshFlags = D3DFVF_DIFFUSE | D3DFVF_NORMAL | D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1; _Device->SetFVF(D3DMeshFlags); _Device->SetVertexShader(NULL); _Device->SetPixelShader(NULL); for(UINT MeshIndex = 0; MeshIndex < _Meshes.Length(); MeshIndex++) { Mesh &CurMesh = *(_Meshes[MeshIndex]); _Device->DrawIndexedPrimitiveUP(D3D9Base::D3DPT_TRIANGLELIST, 0, CurMesh.VertexCount(), CurMesh.FaceCount(), CurMesh.Indices(), D3D9Base::D3DFMT_INDEX32, CurMesh.Vertices(), sizeof(MeshVertex)); } pStateBlock->Apply(); pStateBlock->Release(); } }
// renderStage2 - Render shadows and depth texture for scenes 1+ (post-stencil redraw/alpha/1st person) void DistantLand::renderStage2() { DECLARE_MWBRIDGE IDirect3DStateBlock9 *stateSaved; UINT passes; ///LOG::logline("Stage 2 prims: %d", recordMW.size()); // Early out if nothing is happening if(recordMW.empty()) return; if(!isRenderCached) { // Save state block manually since we can change FVF/decl device->CreateStateBlock(D3DSBT_ALL, &stateSaved); if(isDistantCell()) { // Shadowing onto recorded renders if((Configuration.MGEFlags & USE_SHADOWS) && mwBridge->CellHasWeather()) { effect->Begin(&passes, D3DXFX_DONOTSAVESTATE); effect->BeginPass(PASS_RENDERSHADOW); renderShadow(); effect->EndPass(); effect->End(); } } // Depth texture from recorded renders effectDepth->Begin(&passes, D3DXFX_DONOTSAVESTATE); renderDepthAdditional(); effectDepth->End(); // Restore state stateSaved->Apply(); stateSaved->Release(); } recordMW.clear(); }
void DevState::createCleanState() { if (dwMyThread != 0) { ods("D3D9: CreateCleanState from other thread."); } Stash<DWORD> stashThread(&dwMyThread, GetCurrentThreadId()); if (pSB) pSB->Release(); pSB = NULL; IDirect3DStateBlock9* pStateBlock = NULL; dev->CreateStateBlock(D3DSBT_ALL, &pStateBlock); if (! pStateBlock) return; pStateBlock->Capture(); dev->CreateStateBlock(D3DSBT_ALL, &pSB); if (! pSB) { pStateBlock->Release(); return; } D3DVIEWPORT9 vp; dev->GetViewport(&vp); dev->SetVertexShader(NULL); dev->SetPixelShader(NULL); dev->SetFVF(D3DFVF_TLVERTEX); dev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); dev->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); // 0x16 dev->SetRenderState(D3DRS_WRAP0, FALSE); // 0x80 dev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); dev->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER); dev->SetRenderState(D3DRS_ZENABLE, FALSE); dev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); dev->SetRenderState(D3DRS_COLORVERTEX, FALSE); dev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); dev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); dev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); dev->SetRenderState(D3DRS_LIGHTING, FALSE); pSB->Capture(); pStateBlock->Apply(); pStateBlock->Release(); }
static void doPresent(IDirect3DDevice9 *idd) { DevMapType::iterator it = devMap.find(idd); DevState *ds = it != devMap.end() ? it->second : NULL; if (ds && ds->pSB) { if (ds->dwMyThread != 0) { ods("D3D9: doPresent from other thread"); } Stash<DWORD> stashThread(&(ds->dwMyThread), GetCurrentThreadId()); IDirect3DSurface9 *pTarget = NULL; IDirect3DSurface9 *pRenderTarget = NULL; idd->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pTarget); idd->GetRenderTarget(0, &pRenderTarget); // Present is called for each frame. Thus, we do not want to always log here. #ifdef EXTENDED_OVERLAY_DEBUGOUTPUT ods("D3D9: doPresent BackB %p RenderT %p", pTarget, pRenderTarget); #endif IDirect3DStateBlock9* pStateBlock = NULL; idd->CreateStateBlock(D3DSBT_ALL, &pStateBlock); pStateBlock->Capture(); ds->pSB->Apply(); if (pTarget != pRenderTarget) idd->SetRenderTarget(0, pTarget); idd->BeginScene(); ds->draw(); idd->EndScene(); pStateBlock->Apply(); pStateBlock->Release(); pRenderTarget->Release(); pTarget->Release(); // ods("D3D9: Finished ref is %d %d", ds->myRefCount, ds->refCount); } }
static void doPresent(IDirect3DDevice9 *idd) { DevState *ds = devMap[idd]; if (ds && ds->pSB) { DWORD dwOldThread = ds->dwMyThread; if (dwOldThread) ods("doPresent from other thread"); ds->dwMyThread = GetCurrentThreadId(); IDirect3DSurface9 *pTarget = NULL; IDirect3DSurface9 *pRenderTarget = NULL; idd->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pTarget); idd->GetRenderTarget(0, &pRenderTarget); ods("D3D9: doPresent Back %p RenderT %p",pTarget,pRenderTarget); IDirect3DStateBlock9* pStateBlock = NULL; idd->CreateStateBlock(D3DSBT_ALL, &pStateBlock); pStateBlock->Capture(); ds->pSB->Apply(); if (pTarget != pRenderTarget) idd->SetRenderTarget(0, pTarget); idd->BeginScene(); ds->draw(); idd->EndScene(); pStateBlock->Apply(); pStateBlock->Release(); pRenderTarget->Release(); pTarget->Release(); // ods("Finished ref is %d %d", ds->myRefCount, ds->refCount); ds->dwMyThread = dwOldThread; } }
//-------------------------------------------------------------------------------- void System::OnRender(IDirect3DDevice9* pDevice) { //if(clock() - TheGameWorld->GetRendering() < 400) { IDirect3DStateBlock9* pStateBlock = NULL; pDevice->CreateStateBlock(D3DSBT_ALL, &pStateBlock); pStateBlock->Capture(); try { if(mUI && mPlatform) { Update(); mPlatform->getRenderManagerPtr()->drawOneFrame(); } } catch(...) { } pStateBlock->Apply(); pStateBlock->Release(); } }
// renderStageWater - Render distant water without blend, for exceptional cases void DistantLand::renderStageWater() { DECLARE_MWBRIDGE IDirect3DStateBlock9 *stateSaved; UINT passes; if(isRenderCached) return; if(mwBridge->CellHasWater()) { // Save state block manually since we can change FVF/decl device->CreateStateBlock(D3DSBT_ALL, &stateSaved); effect->Begin(&passes, D3DXFX_DONOTSAVESTATE); // Draw water plane bool u = mwBridge->IsUnderwater(eyePos.z); bool i = !mwBridge->IsExterior(); if(u || i) { // Set up clip plane at fog end for certain environments to save fillrate float clipAt = Configuration.DL.InteriorFogEnd * 8192.0; D3DXPLANE clipPlane(0, 0, -clipAt, mwProj._33 * clipAt + mwProj._43); device->SetClipPlane(0, clipPlane); device->SetRenderState(D3DRS_CLIPPLANEENABLE, 1); } // Switch to appropriate shader and render effect->BeginPass(u ? PASS_RENDERUNDERWATER : PASS_RENDERWATER); renderWaterPlane(); effect->EndPass(); effect->End(); stateSaved->Apply(); stateSaved->Release(); } }
HRESULT WINAPI sample_EndScene(IDirect3DDevice9* device){ Vert v[] = { {100.0f,100.0f,0.0f,0.0f,0xFF00FF00}, {200.0f,100.0f,0.0f,0.0f,0xFF00FF00}, {200.0f,200.0f,0.0f,0.0f,0xFF00FF00}, {100.0f,200.0f,0.0f,0.0f,0xFF00FF00}, }; IDirect3DStateBlock9* stateBlock = NULL; device->CreateStateBlock(D3DSBT_ALL, &stateBlock); // Stateblock saves all the rendersettings, as we are going to modify them in order to draw our stuff device->SetRenderState(D3DRS_ALPHABLENDENABLE,1); device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v,sizeof(Vert)); stateBlock->Apply(); stateBlock->Release(); return endscene_og(device); }
STDMETHODIMP CDirect3DDevice8::DeleteStateBlock(THIS_ DWORD Token) { IDirect3DStateBlock9* pBlock = (IDirect3DStateBlock9*)Token; pBlock->Release(); return D3D_OK; }
STDMETHODIMP CDirect3DDevice8::CaptureStateBlock(THIS_ DWORD Token) { IDirect3DStateBlock9* pBlock = (IDirect3DStateBlock9*)Token; return pBlock->Capture(); }
STDMETHODIMP CDirect3DDevice8::ApplyStateBlock(THIS_ DWORD Token) { IDirect3DStateBlock9* pBlock = (IDirect3DStateBlock9*)Token; return pBlock->Apply(); }
/******************************Public*Routine*****************************\ * Render \**************************************************************************/ STDMETHODIMP CGameUILayer::Render( IDirect3DDevice9 *pDevice) { HRESULT hr = S_OK; IDirect3DStateBlock9 *pState = NULL; D3DMATRIX matW; D3DXMATRIX matW1; if( !pDevice ) { return E_POINTER; } try { CHECK_HR( hr = pDevice->BeginStateBlock(), DbgMsg("")); CHECK_HR( hr = pDevice->EndStateBlock(&pState), DbgMsg("")); pDevice->GetTransform( D3DTS_WORLD, &matW); D3DXMatrixIdentity( &matW1); pDevice->SetTransform( D3DTS_WORLD, &matW1); pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE ); pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); pDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE ); pDevice->SetRenderState( D3DRS_ALPHAREF, 0x06 ); pDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL ); CHECK_HR( hr = pDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ), DbgMsg("")); CHECK_HR( hr = pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ), DbgMsg("")); CHECK_HR( hr = pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ), DbgMsg("")); CHECK_HR( hr = pDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 ), DbgMsg("")); CHECK_HR( hr = pDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ), DbgMsg("")); if( m_bViewing ) { if( m_pTextureButtonResume ) { CHECK_HR( hr = pDevice->SetTexture(0, m_pTextureButtonResume), DbgMsg("")); } } else { if( m_pTextureButtonView ) { CHECK_HR( hr = pDevice->SetTexture(0, m_pTextureButtonView), DbgMsg("")); } } CHECK_HR( hr = pDevice->SetFVF( m_FVFUILayer ), DbgMsg("")); CHECK_HR( hr = pDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, (LPVOID)(m_V), sizeof(m_V[0])), DbgMsg("")); pDevice->SetTransform( D3DTS_WORLD, &matW); CHECK_HR( hr = pDevice->SetTexture(0, NULL), DbgMsg("")); CHECK_HR( hr = pState->Apply(), DbgMsg("")); } catch( HRESULT hr1 ) { if( D3DERR_DEVICELOST == hr1 && m_pOwner ) { hr = m_pOwner->ProcessLostDevice(); } else { hr = hr1; } } RELEASE( pState ); return hr; }
/** * Render the Oculus Rift View. ***/ void* OculusRenderer::Provoke(void* pThis, int eD3D, int eD3DInterface, int eD3DMethod, DWORD dwNumberConnected, int& nProvokerIndex) { // return if wrong call if ((eD3D >= (int)AQU_DirectXVersion::DirectX_9_0) && (eD3D <= (int)AQU_DirectXVersion::DirectX_9_29)) { if (((eD3DInterface == INTERFACE_IDIRECT3DDEVICE9) && (eD3DMethod == METHOD_IDIRECT3DDEVICE9_PRESENT)) || ((eD3DInterface == INTERFACE_IDIRECT3DDEVICE9) && (eD3DMethod == METHOD_IDIRECT3DDEVICE9_ENDSCENE)) || ((eD3DInterface == INTERFACE_IDIRECT3DSWAPCHAIN9) && (eD3DMethod == METHOD_IDIRECT3DSWAPCHAIN9_PRESENT))) { (pThis); } else return nullptr; } else return nullptr; // get input data if (m_paInput[(int)ORN_Decommanders::LeftTexture]) m_pcTextureLeft = *(LPDIRECT3DTEXTURE9*)m_paInput[(int)ORN_Decommanders::LeftTexture]; else m_pcTextureLeft = nullptr; if (m_paInput[(int)ORN_Decommanders::RightTexture]) m_pcTextureRight = *(LPDIRECT3DTEXTURE9*)m_paInput[(int)ORN_Decommanders::RightTexture]; else m_pcTextureRight = nullptr; if (m_paInput[(int)ORN_Decommanders::DistortionVertexBufferLeft]) if (*(LPDIRECT3DVERTEXBUFFER9**)m_paInput[(int)ORN_Decommanders::DistortionVertexBufferLeft]) m_pcDistortionVertexBufferLeft = **(LPDIRECT3DVERTEXBUFFER9**)m_paInput[(int)ORN_Decommanders::DistortionVertexBufferLeft]; else m_pcDistortionVertexBufferLeft = nullptr; else m_pcDistortionVertexBufferLeft = nullptr; if (m_paInput[(int)ORN_Decommanders::DistortionVertexBufferRight]) if (*(LPDIRECT3DVERTEXBUFFER9**)m_paInput[(int)ORN_Decommanders::DistortionVertexBufferRight]) m_pcDistortionVertexBufferRight = **(LPDIRECT3DVERTEXBUFFER9**)m_paInput[(int)ORN_Decommanders::DistortionVertexBufferRight]; else m_pcDistortionVertexBufferRight = nullptr; else m_pcDistortionVertexBufferRight = nullptr; if (m_paInput[(int)ORN_Decommanders::DistortionIndexBufferLeft]) if (*(LPDIRECT3DINDEXBUFFER9**)m_paInput[(int)ORN_Decommanders::DistortionIndexBufferLeft]) m_pcDistortionIndexBufferLeft = **(LPDIRECT3DINDEXBUFFER9**)m_paInput[(int)ORN_Decommanders::DistortionIndexBufferLeft]; else m_pcDistortionIndexBufferLeft = nullptr; else m_pcDistortionIndexBufferLeft = nullptr; if (m_paInput[(int)ORN_Decommanders::DistortionIndexBufferRight]) if (*(LPDIRECT3DINDEXBUFFER9**)m_paInput[(int)ORN_Decommanders::DistortionIndexBufferRight]) m_pcDistortionIndexBufferRight = **(LPDIRECT3DINDEXBUFFER9**)m_paInput[(int)ORN_Decommanders::DistortionIndexBufferRight]; else m_pcDistortionIndexBufferRight = nullptr; else m_pcDistortionIndexBufferRight = nullptr; if (m_paInput[(int)ORN_Decommanders::OculusVertexDeclaration]) if (*(LPDIRECT3DVERTEXDECLARATION9**)m_paInput[(int)ORN_Decommanders::OculusVertexDeclaration]) m_pcVertexDecl = **(LPDIRECT3DVERTEXDECLARATION9**)m_paInput[(int)ORN_Decommanders::OculusVertexDeclaration]; else m_pcVertexDecl = nullptr; else m_pcVertexDecl = nullptr; if (m_paInput[(int)ORN_Decommanders::DefaultEyeFovLeft]) if (*(ovrFovPort**)m_paInput[(int)ORN_Decommanders::DefaultEyeFovLeft]) m_psFOVPortLeft = *(ovrFovPort**)m_paInput[(int)ORN_Decommanders::DefaultEyeFovLeft]; else m_psFOVPortLeft = nullptr; else m_psFOVPortLeft = nullptr; if (m_paInput[(int)ORN_Decommanders::DefaultEyeFovRight]) if (*(ovrFovPort**)m_paInput[(int)ORN_Decommanders::DefaultEyeFovRight]) m_psFOVPortRight = *(ovrFovPort**)m_paInput[(int)ORN_Decommanders::DefaultEyeFovRight]; else m_psFOVPortRight = nullptr; else m_psFOVPortRight = nullptr; // get device LPDIRECT3DDEVICE9 pcDevice = nullptr; bool bReleaseDevice = false; if (eD3DInterface == INTERFACE_IDIRECT3DDEVICE9) { pcDevice = (LPDIRECT3DDEVICE9)pThis; } else if (eD3DInterface == INTERFACE_IDIRECT3DSWAPCHAIN9) { LPDIRECT3DSWAPCHAIN9 pSwapChain = (LPDIRECT3DSWAPCHAIN9)pThis; if (!pSwapChain) { OutputDebugString(L"Oculus Renderer Node : No swapchain !"); return nullptr; } pSwapChain->GetDevice(&pcDevice); bReleaseDevice = true; } if (!pcDevice) { OutputDebugString(L"Oculus Renderer Node : No device !"); return nullptr; } // Original code (LibOVR) : // pShaderCode = ShaderCompile("precompiledVertexShaderSrc",VertexShaderSrc,"vs_2_0"); // pShaderCode = ShaderCompile("precompiledVertexShaderTimewarpSrc",VertexShaderTimewarpSrc,"vs_3_0"); // pShaderCode = ShaderCompile("precompiledPixelShaderSrc",PixelShaderSrc,"ps_3_0"); // pixel shader created ? if (!m_pcOculusPixelShader) { LPD3DXBUFFER pShader; // compile and create shader if (SUCCEEDED(D3DXCompileShader(PixelShaderSrc,strlen(PixelShaderSrc),NULL,NULL,"main","ps_3_0",NULL,&pShader,NULL,&m_pcOculusPixelShaderCT))) { OutputDebugString(L"Pixel shader compiled!"); pcDevice->CreatePixelShader((DWORD*)pShader->GetBufferPointer(), &m_pcOculusPixelShader); } } // vertex shader created ? if (!m_pcOculusVertexShader) { LPD3DXBUFFER pShader; // compile and create shader if (SUCCEEDED(D3DXCompileShader(VertexShaderSrc,strlen(VertexShaderSrc),NULL,NULL,"main","vs_2_0",NULL,&pShader,NULL,&m_pcOculusVertexShaderCT))) { OutputDebugString(L"Vertex shader compiled!"); pcDevice->CreateVertexShader((DWORD*)pShader->GetBufferPointer(), &m_pcOculusVertexShader); } } // side by side pixel shader ? if (!m_pcSideBySidePixelShader) { LPD3DXBUFFER pShader; // compile and create shader if (SUCCEEDED(D3DXCompileShader(PixelShaderSrcSideBySide,strlen(PixelShaderSrcSideBySide),NULL,NULL,"SBS","ps_2_0",NULL,&pShader,NULL,&m_pcSideBySidePixelShaderCT))) { OutputDebugString(L"Pixel shader compiled!"); pcDevice->CreatePixelShader((DWORD*)pShader->GetBufferPointer(), &m_pcSideBySidePixelShader); } } // test textures created ? if ((!m_pcTextureRightTest) || (!m_pcTextureLeftTest)) { HMODULE hModule = GetModuleHandle(L"OculusRenderer.dll"); if (!m_pcTextureLeftTest) { // create a test texture if (SUCCEEDED(D3DXCreateTextureFromResource(pcDevice, hModule, MAKEINTRESOURCE(IMG_BACKGROUND01), &m_pcTextureLeftTest))) OutputDebugString(L"Texture created !"); else m_pcTextureLeftTest = nullptr; } if (!m_pcTextureRightTest) { // create a test texture if (SUCCEEDED(D3DXCreateTextureFromResource(pcDevice, hModule, MAKEINTRESOURCE(IMG_BACKGROUND02), &m_pcTextureRightTest))) OutputDebugString(L"Texture created !"); else m_pcTextureRightTest = nullptr; } } // default vertex buffer ? if (!m_pcVertexBufferDefault) { InitDefaultVertexBuffer(pcDevice); if (!m_pcVertexBufferDefault) return nullptr; } // vertex buffers ? index buffers ? not all present ? if ((!m_pcDistortionVertexBufferLeft) || (!m_pcDistortionVertexBufferRight) || (!m_pcDistortionIndexBufferLeft) || (!m_pcDistortionIndexBufferRight) || (!m_pcVertexDecl)) { if (m_bBuffersConnected) { // clear all descriptions for safety ZeroMemory(&m_sVertexBufferDescLeft, sizeof(D3DVERTEXBUFFER_DESC)); ZeroMemory(&m_sVertexBufferDescRight, sizeof(D3DVERTEXBUFFER_DESC)); ZeroMemory(&m_sIndexBufferDescLeft, sizeof(D3DINDEXBUFFER_DESC)); ZeroMemory(&m_sIndexBufferDescRight, sizeof(D3DINDEXBUFFER_DESC)); m_bBuffersConnected = false; } } else { m_bBuffersConnected = true; // vertex buffer description ? left if (!m_sVertexBufferDescLeft.Size) m_pcDistortionVertexBufferLeft->GetDesc(&m_sVertexBufferDescLeft); // vertex buffer length matches oculus vertex type ? if ((m_sVertexBufferDescLeft.Size % sizeof(ovrDistortionVertex)) != 0) { OutputDebugString(L"OculusRenderer Node : Connected vertex buffer size mismatch !"); return nullptr; } // and right if (!m_sVertexBufferDescRight.Size) m_pcDistortionVertexBufferRight->GetDesc(&m_sVertexBufferDescRight); // vertex buffer length matches oculus vertex type ? if ((m_sVertexBufferDescRight.Size % sizeof(ovrDistortionVertex)) != 0) { OutputDebugString(L"OculusRenderer Node : Connected vertex buffer size mismatch !"); return nullptr; } // index buffer ? if ((!m_pcDistortionIndexBufferLeft) || (!m_pcDistortionIndexBufferRight)) return nullptr; // index buffer description ? if (!m_sIndexBufferDescLeft.Size) { m_pcDistortionIndexBufferLeft->GetDesc(&m_sIndexBufferDescLeft); // index buffer length matches vertex buffer size ? TODO !! /*if () { OutputDebugString(L"OculusRenderer Node : Connected index buffer size mismatch !"); return nullptr; }*/ } if (!m_sIndexBufferDescRight.Size) { m_pcDistortionIndexBufferRight->GetDesc(&m_sIndexBufferDescRight); // index buffer length matches vertex buffer size ? TODO !! /*if () { OutputDebugString(L"OculusRenderer Node : Connected index buffer size mismatch !"); return nullptr; }*/ } } // start to render pcDevice->BeginScene(); // save states IDirect3DStateBlock9* pStateBlock = nullptr; pcDevice->CreateStateBlock(D3DSBT_ALL, &pStateBlock); // set ALL render states to default SetAllRenderStatesDefault(pcDevice); // set states pcDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); pcDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); pcDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); pcDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CONSTANT); pcDevice->SetTextureStageState(0, D3DTSS_CONSTANT, 0xffffffff); pcDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pcDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); pcDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); pcDevice->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, 0); pcDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); pcDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); pcDevice->SetSamplerState(0, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP); pcDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC); pcDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC); pcDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); D3DCOLOR clearColor = D3DCOLOR_RGBA(0, 0, 0, 0); pcDevice->Clear(0, NULL, D3DCLEAR_TARGET, clearColor, 0, 0); // required fields D3DSURFACE_DESC sSurfaceDesc; ovrSizei sTextureSize; ovrRecti sRenderViewport; ovrVector2f UVScaleOffset[2]; // LEFT EYE : // left eye, first set stream source, indices if (m_bBuffersConnected) { // no timewarp here, use standard vertex shader, set pixel shader, set vertex declaration pcDevice->SetVertexShader( m_pcOculusVertexShader); pcDevice->SetPixelShader( m_pcOculusPixelShader ); pcDevice->SetVertexDeclaration( m_pcVertexDecl ); // set texture if (m_pcTextureLeft) pcDevice->SetTexture( 0, m_pcTextureLeft ); else if (m_pcTextureLeftTest) pcDevice->SetTexture( 0, m_pcTextureLeftTest ); else pcDevice->SetTexture( 0, 0); // get texture size if (m_pcTextureLeft) m_pcTextureLeft->GetLevelDesc(0, &sSurfaceDesc); else if (m_pcTextureLeftTest) m_pcTextureLeftTest->GetLevelDesc(0, &sSurfaceDesc); else ZeroMemory(&sSurfaceDesc, sizeof(D3DSURFACE_DESC)); sTextureSize.w = (int)sSurfaceDesc.Width; sTextureSize.h = (int)sSurfaceDesc.Height; // set render viewport size the same size as the texture size (!) sRenderViewport.Pos.x = 0; sRenderViewport.Pos.y = 0; sRenderViewport.Size.w = sTextureSize.w; sRenderViewport.Size.h = sTextureSize.h; // get and set scale and offset if (m_psFOVPortLeft) ovrHmd_GetRenderScaleAndOffset(*m_psFOVPortLeft, sTextureSize, sRenderViewport, UVScaleOffset); else ovrHmd_GetRenderScaleAndOffset(m_sDefaultFOVPortLeft, sTextureSize, sRenderViewport, UVScaleOffset); pcDevice->SetVertexShaderConstantF( 0, ( FLOAT* )&UVScaleOffset[0], 1 ); pcDevice->SetVertexShaderConstantF( 2, ( FLOAT* )&UVScaleOffset[1], 1 ); pcDevice->SetStreamSource( 0, m_pcDistortionVertexBufferLeft,0, sizeof(ovrDistortionVertex) ); pcDevice->SetIndices( m_pcDistortionIndexBufferLeft); // draw pcDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,0,0, m_sVertexBufferDescLeft.Size / sizeof(ovrDistortionVertex) , 0, m_sIndexBufferDescLeft.Size / 6 ); } else { pcDevice->SetSamplerState(1, D3DSAMP_SRGBTEXTURE, 0); pcDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); pcDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); pcDevice->SetSamplerState(1, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP); pcDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC); pcDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC); pcDevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_NONE); // side by side render pcDevice->SetVertexShader(NULL); pcDevice->SetPixelShader(m_pcSideBySidePixelShader); pcDevice->SetVertexDeclaration( NULL ); pcDevice->SetFVF(D3DFVF_TEXVERTEX); // set textures if (m_pcTextureLeft) pcDevice->SetTexture( 0, m_pcTextureLeft ); else if (m_pcTextureLeftTest) pcDevice->SetTexture( 0, m_pcTextureLeftTest ); else pcDevice->SetTexture( 0, 0); if (m_pcTextureRight) pcDevice->SetTexture( 1, m_pcTextureRight ); else if (m_pcTextureRightTest) pcDevice->SetTexture( 1, m_pcTextureRightTest ); else pcDevice->SetTexture( 1, 0); // set stream and draw pcDevice->SetStreamSource( 0, m_pcVertexBufferDefault,0, sizeof(TEXVERTEX) ); pcDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2); } // RIGHT EYE: if (m_bBuffersConnected) { // set texture if (m_pcTextureRight) pcDevice->SetTexture( 0, m_pcTextureRight ); else if (m_pcTextureRightTest) pcDevice->SetTexture( 0, m_pcTextureRightTest ); else pcDevice->SetTexture( 0, 0); // get texture size if (m_pcTextureRight) m_pcTextureRight->GetLevelDesc(0, &sSurfaceDesc); else if (m_pcTextureRightTest) m_pcTextureRightTest->GetLevelDesc(0, &sSurfaceDesc); else ZeroMemory(&sSurfaceDesc, sizeof(D3DSURFACE_DESC)); sTextureSize.w = (int)sSurfaceDesc.Width; sTextureSize.h = (int)sSurfaceDesc.Height; // get and set scale and offset if (m_psFOVPortRight) ovrHmd_GetRenderScaleAndOffset(*m_psFOVPortRight, sTextureSize, sRenderViewport, UVScaleOffset); else ovrHmd_GetRenderScaleAndOffset(m_sDefaultFOVPortRight, sTextureSize, sRenderViewport, UVScaleOffset); pcDevice->SetVertexShaderConstantF( 0, ( FLOAT* )&UVScaleOffset[0], 1 ); pcDevice->SetVertexShaderConstantF( 2, ( FLOAT* )&UVScaleOffset[1], 1 ); // set stream source, indices, draw pcDevice->SetStreamSource( 0, m_pcDistortionVertexBufferRight,0, sizeof(ovrDistortionVertex) ); pcDevice->SetIndices( m_pcDistortionIndexBufferRight); // draw pcDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,0,0, m_sVertexBufferDescRight.Size / sizeof(ovrDistortionVertex) , 0, m_sIndexBufferDescRight.Size / 6 ); } pcDevice->EndScene(); // apply and release state block if (pStateBlock) { pStateBlock->Apply(); pStateBlock->Release(); } // release device if provided by swapchain if (bReleaseDevice) pcDevice->Release(); return nullptr; }
//////////////////////////////////////////////////////////////// // // CRenderItemManager::FlushNonAARenderTarget // // If using AA hacks, change everything back // //////////////////////////////////////////////////////////////// void CRenderItemManager::FlushNonAARenderTarget( void ) { if ( m_pSavedSceneDepthSurface ) { m_pDevice->SetDepthStencilSurface ( m_pSavedSceneDepthSurface ); SAFE_RELEASE( m_pSavedSceneDepthSurface ); } if ( m_pSavedSceneRenderTargetAA ) { // Restore GTA AA render target, and copy our non-AA data to it m_pDevice->SetRenderTarget( 0, m_pSavedSceneRenderTargetAA ); if ( m_pNonAARenderTarget ) { if ( !m_bIsSwiftShader ) m_pDevice->StretchRect( m_pNonAARenderTarget, NULL, m_pSavedSceneRenderTargetAA, NULL, D3DTEXF_POINT ); else { // Emulate StretchRect using DrawPrimitive // Save render states IDirect3DStateBlock9* pSavedStateBlock = NULL; m_pDevice->CreateStateBlock( D3DSBT_ALL, &pSavedStateBlock ); // Prepare vertex buffer float fX1 = -0.5f; float fY1 = -0.5f; float fX2 = m_uiDefaultViewportSizeX + fX1; float fY2 = m_uiDefaultViewportSizeY + fY1; float fU1 = 0; float fV1 = 0; float fU2 = 1; float fV2 = 1; const SRTVertex vertices[] = { { fX1, fY1, 0, 1, fU1, fV1 }, { fX2, fY1, 0, 1, fU2, fV1 }, { fX1, fY2, 0, 1, fU1, fV2 }, { fX2, fY1, 0, 1, fU2, fV1 }, { fX2, fY2, 0, 1, fU2, fV2 }, { fX1, fY2, 0, 1, fU1, fV2 } }; // Set vertex stream uint PrimitiveCount = NUMELMS( vertices ) / 3; const void* pVertexStreamZeroData = &vertices[0]; uint VertexStreamZeroStride = sizeof(SRTVertex); m_pDevice->SetFVF( SRTVertex::FVF ); // Set render states m_pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE ); m_pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); m_pDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE ); m_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE); m_pDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE ); m_pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); m_pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); m_pDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE ); m_pDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); m_pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT ); m_pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ); m_pDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT ); // Draw using texture m_pDevice->SetTexture( 0, m_pNonAARenderTargetTexture ); m_pDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride ); // Restore render states if ( pSavedStateBlock ) { pSavedStateBlock->Apply(); SAFE_RELEASE( pSavedStateBlock ); } } } SAFE_RELEASE( m_pSavedSceneRenderTargetAA ); } }
/// Present the overlay. /// /// If called via IDirect3DDevice9::present() or IDirect3DDevice9Ex::present(), /// idd will be non-NULL and ids ill be NULL. /// /// If called via IDirect3DSwapChain9::present(), both idd and ids will be /// non-NULL. /// /// The doPresent function expects the following assumptions to be valid: /// /// - Only one swap chain used at the same time. /// - Windowed? IDirect3D9SwapChain::present() is used. ("Additional swap chain" is used) /// - Full screen? IDirect3D9Device::present() is used. (Implicit swap chain for IDirect3D9Device is used) /// /// It's either/or. /// /// If doPresent is called multiple times per frame (say, for different swap chains), /// the overlay will break badly when DevState::draw() is called. FPS counting will be off, /// different render targets with different sizes will cause a size-renegotiation with Mumble /// every frame, etc. static void doPresent(IDirect3DDevice9 *idd, IDirect3DSwapChain9 *ids) { DevMapType::iterator it = devMap.find(idd); DevState *ds = it != devMap.end() ? it->second : NULL; HRESULT hres; if (ds && ds->pSB) { if (ds->dwMyThread != 0) { ods("D3D9: doPresent from other thread"); } Stash<DWORD> stashThread(&(ds->dwMyThread), GetCurrentThreadId()); // Get the back buffer. // If we're called via IDirect3DSwapChain9, acquire it via the swap chain object. // Otherwise, acquire it via the device itself. IDirect3DSurface9 *pTarget = NULL; if (ids) { hres = ids->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pTarget); if (FAILED(hres)) { if (hres == D3DERR_INVALIDCALL) { ods("D3D9: IDirect3DSwapChain9::GetBackBuffer failed. BackBuffer index equals or exceeds the total number of back buffers"); } else { ods("D3D9: IDirect3DSwapChain9::GetBackBuffer failed"); } } } else { hres = idd->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pTarget); if (FAILED(hres)) { if (hres == D3DERR_INVALIDCALL) { ods("D3D9: IDirect3DDevice9::GetBackBuffer failed. BackBuffer index equals or exceeds the total number of back buffers"); } else { ods("D3D9: IDirect3DDevice9::GetBackBuffer failed"); } } } IDirect3DSurface9 *pRenderTarget = NULL; hres = idd->GetRenderTarget(0, &pRenderTarget); if (FAILED(hres)) { if (hres == D3DERR_NOTFOUND) { ods("D3D9: IDirect3DDevice9::GetRenderTarget failed. There is no render target with the specified index"); } else if (hres == D3DERR_INVALIDCALL) { ods("D3D9: IDirect3DDevice9::GetRenderTarget failed. One of the passed arguments was invalid"); } else { ods("D3D9: IDirect3DDevice9::GetRenderTarget failed"); } } // Present is called for each frame. Thus, we do not want to always log here. #ifdef EXTENDED_OVERLAY_DEBUGOUTPUT ods("D3D9: doPresent BackB %p RenderT %p", pTarget, pRenderTarget); #endif IDirect3DStateBlock9* pStateBlock = NULL; idd->CreateStateBlock(D3DSBT_ALL, &pStateBlock); pStateBlock->Capture(); ds->pSB->Apply(); if (pTarget != pRenderTarget) { hres = idd->SetRenderTarget(0, pTarget); if (FAILED(hres)) { ods("D3D9: IDirect3DDevice9::SetRenderTarget failed"); } } // If we're called via IDirect3DSwapChain9::present(), we have to // get the size of the back buffer and manually set the viewport size // to match it. // // Although the call to IDirect3DDevice9::SetRenderTarget() above is // documented as updating the device's viewport: // // "Setting a new render target will cause the viewport (see Viewports // and Clipping (Direct3D 9)) to be set to the full size of the new // render target." // // (via https://msdn.microsoft.com/en-us/library/windows/desktop/bb174455(v=vs.85).aspx) // // ...this doesn't happen. At least for some programs such as Final Fantasy XIV // and Battle.net Launcher. For these programs, we get a viewport of 1x1. // // The viewport we set here is used in the call below to DevState::draw() // as the full size of the screen/window. if (ids) { D3DPRESENT_PARAMETERS pp; hres = ids->GetPresentParameters(&pp); if (FAILED(hres)) { ods("D3D9: IDirect3DSwapChain9::GetPresentParameters failed"); } else { if (pp.BackBufferWidth != 0 && pp.BackBufferHeight != 0) { D3DVIEWPORT9 vp; vp.X = 0; vp.Y = 0; vp.Width = pp.BackBufferWidth; vp.Height = pp.BackBufferHeight; vp.MinZ = 0.0f; vp.MaxZ = 1.0f; idd->SetViewport(&vp); } } } idd->BeginScene(); ds->draw(); idd->EndScene(); pStateBlock->Apply(); pStateBlock->Release(); pRenderTarget->Release(); pTarget->Release(); // ods("D3D9: Finished ref is %d %d", ds->myRefCount, ds->refCount); } }
void RSManagerDX9::initResources(bool downsampling, unsigned rw, unsigned rh, unsigned numBBs, D3DFORMAT bbFormat, D3DMULTISAMPLE_TYPE multiSampleType, unsigned multiSampleQuality, D3DSWAPEFFECT swapEff, bool autoDepthStencil, D3DFORMAT depthStencilFormat) { if(inited) releaseResources(); SDLOG(0, "RenderstateManager resource initialization started\n"); this->downsampling = downsampling; renderWidth = rw; renderHeight = rh; numBackBuffers = numBBs; if(bbFormat != D3DFMT_UNKNOWN) backbufferFormat = bbFormat; swapEffect = swapEff == D3DSWAPEFFECT_COPY ? SWAP_COPY : (swapEff == D3DSWAPEFFECT_DISCARD ? SWAP_DISCARD : SWAP_FLIP); if(swapEffect == SWAP_FLIP) numBackBuffers++; // account for the "front buffer" in the swap chain console.initialize(d3ddev, downsampling ? Settings::get().getPresentWidth() : rw, downsampling ? Settings::get().getPresentHeight() : rh); Console::setLatest(&console); imgWriter.reset(new ImageWriter(d3ddev, max(rw, max(Settings::get().getRenderWidth(), Settings::get().getPresentWidth())), max(rh, max(Settings::get().getRenderHeight(), Settings::get().getPresentHeight())))); // performance measurement console.add(frameTimeText); perfMonitor.reset(new D3DPerfMonitor(d3ddev, 60)); console.add(traceText); // store current state temporarily IDirect3DStateBlock9 *startState; d3ddev->CreateStateBlock(D3DSBT_ALL, &startState); // create and capture default state block d3ddev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); d3ddev->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); d3ddev->SetRenderState(D3DRS_STENCILENABLE, FALSE); d3ddev->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); d3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE); d3ddev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); d3ddev->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE); d3ddev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); d3ddev->SetRenderState(D3DRS_CLIPPING, FALSE); d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); d3ddev->SetRenderState(D3DRS_FOGENABLE, FALSE); d3ddev->CreateStateBlock(D3DSBT_ALL, &initStateBlock); if(downsampling) { scaler.reset(new Scaler(d3ddev, rw, rh, Settings::get().getPresentWidth(), Settings::get().getPresentHeight())); // generate backbuffers SDLOG(2, "Generating backbuffers:\n") for(unsigned i = 0; i < numBackBuffers; ++i) { backBuffers.push_back(rtMan->createTexture(rw, rh, backbufferFormat, multiSampleType, multiSampleQuality)); SDLOG(2, "Backbuffer %u: %p\n", i, backBuffers[i]); } // set back buffer 0 as initial rendertarget d3ddev->SetRenderTarget(0, backBuffers[0]->getSurf()); // generate additional buffer to emulate flip if required if(swapEffect == SWAP_FLIP && Settings::get().getEmulateFlipBehaviour()) { extraBuffer = rtMan->createSurface(rw, rh, backbufferFormat); SDLOG(2, "Extra backbuffer: %p\n", extraBuffer); } // if required, determine depth/stencil surf type and create if(autoDepthStencil) { d3ddev->CreateDepthStencilSurface(rw, rh, depthStencilFormat, multiSampleType, multiSampleQuality, FALSE, &depthStencilSurf, NULL); SDLOG(2, "Generated depth stencil surface - format: %s\n", D3DFormatToString(depthStencilFormat)); // set our depth stencil surface d3ddev->SetDepthStencilSurface(depthStencilSurf); } } plugin = GamePlugin::getPlugin(d3ddev, *this); plugin->initialize(rw, rh, bbFormat, depthStencilFormat); // restore initial state startState->Apply(); startState->Release(); SDLOG(0, "RenderstateManager resource initialization completed\n"); inited = true; }
void D3D9statemanager::setSamplerStateBlock( DWORD stage, Texture::ClampMode clampmode, Texture::FilterMode filtermode ) { int hash = stage << 24 | clampmode << 16 | filtermode; HRESULT hr; Dict<int,IDirect3DStateBlock9*>::const_iterator it = m_states.find(hash); if (it != m_states.end()) { if (m_stageSamplerStates[stage] != it->second) { V(it->second->Apply()); m_stageSamplerStates[stage] = it->second; } return; } IDirect3DStateBlock9* state = 0; d3d9Device->BeginStateBlock(); switch (clampmode) { case Texture::CM_Clamp: case Texture::CM_ClampToEdge: d3d9StateManager->SetSamplerState(stage, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); d3d9StateManager->SetSamplerState(stage, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); d3d9StateManager->SetSamplerState(stage, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP); break; case Texture::CM_ClampToBorder: d3d9StateManager->SetSamplerState(stage, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); d3d9StateManager->SetSamplerState(stage, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); d3d9StateManager->SetSamplerState(stage, D3DSAMP_ADDRESSW, D3DTADDRESS_BORDER); d3d9StateManager->SetSamplerState(stage, D3DSAMP_BORDERCOLOR, 0); break; case Texture::CM_Repeat: d3d9StateManager->SetSamplerState(stage, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); d3d9StateManager->SetSamplerState(stage, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); d3d9StateManager->SetSamplerState(stage, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP); } switch (filtermode) { case Texture::FM_Nearest: d3d9StateManager->SetSamplerState(stage, D3DSAMP_MINFILTER, D3DTEXF_POINT); d3d9StateManager->SetSamplerState(stage, D3DSAMP_MAGFILTER, D3DTEXF_POINT); d3d9StateManager->SetSamplerState(stage, D3DSAMP_MIPFILTER, D3DTEXF_NONE); break; case Texture::FM_Linear: d3d9StateManager->SetSamplerState(stage, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); d3d9StateManager->SetSamplerState(stage, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); d3d9StateManager->SetSamplerState(stage, D3DSAMP_MIPFILTER, D3DTEXF_NONE); break; case Texture::FM_Bilinear: d3d9StateManager->SetSamplerState(stage, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); d3d9StateManager->SetSamplerState(stage, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); d3d9StateManager->SetSamplerState(stage, D3DSAMP_MIPFILTER, D3DTEXF_POINT); break; case Texture::FM_Trilinear: d3d9StateManager->SetSamplerState(stage, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); d3d9StateManager->SetSamplerState(stage, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); d3d9StateManager->SetSamplerState(stage, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); break; } d3d9Device->EndStateBlock(&state); m_states[hash] = state; state->Apply(); m_stageSamplerStates[stage] = state; }
void MGEhud::draw() { std::map<std::string, MGEhud::hud_id>::const_iterator i; IDirect3DStateBlock9 *stateSaved; device->CreateStateBlock(D3DSBT_ALL, &stateSaved); D3DXVECTOR4 *vbase; HRESULT hr = vbHUD->Lock(0, 0, (void**)&vbase, D3DLOCK_DISCARD); if(hr != D3D_OK || vbase == 0) return; for(i = element_names.begin(); i != element_names.end(); ++i) { const Element *e = &elements[i->second]; if(e->enabled) { float x0 = e->x, x1 = e->x + e->xscale * e->w; float y0 = e->y, y1 = e->y + e->yscale * e->h; // Correct for D3D9 pixel offset x0 -= 0.5; y0 -= 0.5; x1 -= 0.5; y1 -= 0.5; D3DXVECTOR4 *v = vbase + 8 * i->second; v[0] = D3DXVECTOR4(x0, y1, 0, 1); v[1] = D3DXVECTOR4(0, 1, 0, 0); v[2] = D3DXVECTOR4(x0, y0, 0, 1); v[3] = D3DXVECTOR4(0, 0, 0, 0); v[4] = D3DXVECTOR4(x1, y1, 0, 1); v[5] = D3DXVECTOR4(1, 1, 0, 0); v[6] = D3DXVECTOR4(x1, y0, 0, 1); v[7] = D3DXVECTOR4(1, 0, 0, 0); } } vbHUD->Unlock(); device->SetFVF(fvfHUD); device->SetStreamSource(0, vbHUD, 0, 32); device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); for(i = element_names.begin(); i != element_names.end(); ++i) { const Element *e = &elements[i->second]; if(e->enabled) { ID3DXEffect *effect = e->effect ? e->effect : effectStandard; D3DXHANDLE ehTex = effect->GetParameterByName(0, "tex"); UINT passes; effect->SetTexture(ehTex, e->texture); effect->Begin(&passes, D3DXFX_DONOTSAVESTATE); effect->BeginPass(0); device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4 * i->second, 2); effect->EndPass(); effect->End(); } } stateSaved->Apply(); stateSaved->Release(); }
// renderStage0 - Render distant land at beginning of scene 0, after sky void DistantLand::renderStage0() { DECLARE_MWBRIDGE IDirect3DStateBlock9 *stateSaved; UINT passes; // Get Morrowind camera matrices device->GetTransform(D3DTS_VIEW, &mwView); device->GetTransform(D3DTS_PROJECTION, &mwProj); // Set variables derived from current camera configuration setView(&mwView); adjustFog(); setupCommonEffect(&mwView, &mwProj); // Select distant static set selectDistantCell(); isRenderCached &= (Configuration.MGEFlags & USE_MENU_CACHING) && mwBridge->IsMenu(); if(!isRenderCached) { ///LOG::logline("Sky prims: %d", recordSky.size()); if(isDistantCell()) { // Save state block manually since we can change FVF/decl device->CreateStateBlock(D3DSBT_ALL, &stateSaved); effect->BeginPass(PASS_SETUP); effect->EndPass(); // Shadow map early render if(Configuration.MGEFlags & USE_SHADOWS) { if(mwBridge->CellHasWeather() && !mwBridge->IsMenu()) { effectShadow->Begin(&passes, D3DXFX_DONOTSAVESTATE); renderShadowMap(); effectShadow->End(); } } // Distant everything; bias the projection matrix such that // distant land gets drawn behind anything Morrowind would draw D3DXMATRIX distProj = mwProj; distProj._33 += kDistantZBias; effect->SetMatrix(ehProj, &distProj); effect->Begin(&passes, D3DXFX_DONOTSAVESTATE); if(!mwBridge->IsUnderwater(eyePos.z)) { // Draw distant landscape if(mwBridge->IsExterior()) { effect->BeginPass(PASS_RENDERLAND); renderDistantLand(effect, &mwView, &distProj); effect->EndPass(); } // Draw distant statics, with alpha dissolve as they pass the near view boundary DWORD p = mwBridge->CellHasWeather() ? PASS_RENDERSTATICSEXTERIOR : PASS_RENDERSTATICSINTERIOR; effect->SetFloat(ehDissolveRange, 7168.0); effect->BeginPass(p); cullDistantStatics(&mwView, &distProj); renderDistantStatics(); effect->EndPass(); } // Sky scattering and sky objects (should be drawn late as possible) if((Configuration.MGEFlags & USE_ATM_SCATTER) && mwBridge->CellHasWeather()) { effect->BeginPass(PASS_RENDERSKY); renderSky(); effect->EndPass(); } // Update reflection if(mwBridge->CellHasWater()) renderWaterReflection(&mwView, &distProj); // Update water simulation if(Configuration.MGEFlags & DYNAMIC_RIPPLES) simulateDynamicWaves(); effect->End(); // Reset matrices effect->SetMatrix(ehView, &mwView); effect->SetMatrix(ehProj, &mwProj); // Save distant land only frame to texture if(~Configuration.MGEFlags & NO_MW_MGE_BLEND) texDistantBlend = PostShaders::borrowBuffer(1); // Restore render state stateSaved->Apply(); stateSaved->Release(); } else { // Clear water reflection to avoid seeing previous cell environment reflected // Must be done every frame to react to lighting changes clearReflection(); // Update water simulation if(Configuration.MGEFlags & DYNAMIC_RIPPLES) { // Save state block manually since we can change FVF/decl device->CreateStateBlock(D3DSBT_ALL, &stateSaved); effect->Begin(&passes, D3DXFX_DONOTSAVESTATE); simulateDynamicWaves(); effect->End(); // Restore render state stateSaved->Apply(); stateSaved->Release(); } } } // Clear stray recordings recordMW.clear(); recordSky.clear(); }
void CState::Restore() { if( m_StateBlock ) m_StateBlock->Apply(); }
void CDirect3DEvents9::OnPresent ( IDirect3DDevice9 *pDevice ) { // Start a new scene. This isn't ideal and is not really recommended by MSDN. // I tried disabling EndScene from GTA and just end it after this code ourselves // before present, but that caused graphical issues randomly with the sky. pDevice->BeginScene (); // Notify core CCore::GetSingleton ().DoPostFramePulse (); // Are we allowed to draw the gui? if ( CCore::GetSingleton ().CanDrawGUI () ) { // Create a state block. IDirect3DStateBlock9 * pDeviceState = NULL; pDevice->CreateStateBlock ( D3DSBT_ALL, &pDeviceState ); // Draw pre-GUI primitives CGraphics::GetSingleton ().DrawPreGUIQueue (); // Draw the GUI CLocalGUI::GetSingleton().Draw (); // Draw post-GUI primitives CGraphics::GetSingleton ().DrawPostGUIQueue (); // Redraw the mouse cursor so it will always be over other elements CLocalGUI::GetSingleton().DrawMouseCursor(); // Restore the render states if ( pDeviceState ) { pDeviceState->Apply ( ); pDeviceState->Release ( ); } } // End the scene that we started. pDevice->EndScene (); // Make a screenshot if needed if ( CCore::GetSingleton().bScreenShot ) { RECT ScreenSize; D3DLOCKED_RECT LockedRect; IDirect3DSurface9 *pSurface, *pLockSurface; // Define a screen rectangle ScreenSize.top = ScreenSize.left = 0; ScreenSize.right = CDirect3DData::GetSingleton ().GetViewportWidth (); ScreenSize.bottom = CDirect3DData::GetSingleton ().GetViewportHeight (); pDevice->GetRenderTarget ( 0, &pSurface ); // Create a new render target if ( pDevice->CreateRenderTarget ( ScreenSize.right, ScreenSize.bottom, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pLockSurface, NULL ) != D3D_OK ) { CCore::GetSingleton ().GetConsole ()->Printf("Couldn't create a new render target."); } else { unsigned long ulBeginTime = GetTickCount (); // Copy data from surface to surface if ( pDevice->StretchRect ( pSurface, &ScreenSize, pLockSurface, &ScreenSize, D3DTEXF_NONE ) != D3D_OK ) { CCore::GetSingleton ().GetConsole ()->Printf("Couldn't copy the surface."); } // Lock the surface if ( pLockSurface->LockRect ( &LockedRect, NULL, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK ) != D3D_OK ) { CCore::GetSingleton ().GetConsole ()->Printf("Couldn't lock the surface."); } // Call the pre-screenshot function SString strFileName = CScreenShot::PreScreenShot (); unsigned long ulScreenHeight = ScreenSize.bottom - ScreenSize.top; unsigned long ulScreenWidth = ScreenSize.right - ScreenSize.left; // Create rhe screen data buffer BYTE** ppScreenData = NULL; ppScreenData = new BYTE* [ ulScreenHeight ]; for ( unsigned short y = 0; y < ulScreenHeight; y++ ) { ppScreenData[y] = new BYTE [ ulScreenWidth * 4 ]; } // Copy the surface data into a row-based buffer for libpng #define BYTESPERPIXEL 4 unsigned long ulLineWidth = ulScreenWidth * 4; for ( unsigned int i = 0; i < ulScreenHeight; i++ ) { memcpy ( ppScreenData[i], (BYTE*) LockedRect.pBits + i* LockedRect.Pitch, ulLineWidth ); for ( unsigned int j = 3; j < ulLineWidth; j += BYTESPERPIXEL ) { ppScreenData[i][j] = 0xFF; } } // Unlock and release the surface pLockSurface->UnlockRect (); pLockSurface->Release (); // Save to png (strip the output alpha channel and read as BGR) FILE *file = fopen (strFileName, "wb"); png_struct* png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); png_info* info_ptr = png_create_info_struct ( png_ptr ); png_init_io ( png_ptr, file ); png_set_filter ( png_ptr, 0, PNG_FILTER_NONE ); png_set_compression_level ( png_ptr, 1 ); png_set_IHDR ( png_ptr, info_ptr, ScreenSize.right, ScreenSize.bottom, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); png_set_rows ( png_ptr, info_ptr, ppScreenData ); png_write_png ( png_ptr, info_ptr, PNG_TRANSFORM_BGR | PNG_TRANSFORM_STRIP_ALPHA, NULL ); png_write_end ( png_ptr, info_ptr ); png_destroy_write_struct ( &png_ptr, &info_ptr ); fclose(file); // Clean up the screen data buffer if ( ppScreenData ) { unsigned short height = (unsigned short)CDirect3DData::GetSingleton ().GetViewportHeight (); for ( unsigned short y = 0; y < height; y++ ) { delete [] ppScreenData[y]; } delete [] ppScreenData; } // Call the post-screenshot function CScreenShot::PostScreenShot ( strFileName ); CCore::GetSingleton ().GetConsole ()->Printf ( "Screenshot capture took %.2f seconds.", (float)(GetTickCount () - ulBeginTime) / 1000.0f ); } CCore::GetSingleton().bScreenShot = false; } }
void LODManager::Render(IDirect3DDevice9 *D3DDevice, IDirect3DSurface9 *RenderTo, IDirect3DSurface9 *RenderFrom) { if (EnabledLOD.Get() && Constants.Exteriour && !Constants.Oblivion) { /* we switched worldspace */ if (WorldSpace != Constants.WorldSpace) { Reset(); /* mark this to be the current worldspace */ WorldSpace = Constants.WorldSpace; } #if 1 //def OBGE_STATEBLOCKS /* auto backup (not strictly needed, all states can be changed) */ IDirect3DStateBlock9 *pStateBlock = NULL; D3DDevice->CreateStateBlock(D3DSBT_ALL, &pStateBlock); #endif if ((currentPass == OBGEPASS_MAIN) && 0) markerReset(D3DDevice); /* my settings are: * near 10.0 * far 283408.... ^= sqrt(2 * ((half-tile + full-tile) ^ 2)) * ^= pytagoras of 1.5 tiles radius or 3 tile diameter */ // D3DDevice->SetTransform(D3DTS_PROJECTION, &Constants.proj); // D3DDevice->SetTransform(D3DTS_VIEW, &Constants.view); // D3DDevice->SetTransform(D3DTS_WORLD, &Constants.wrld); D3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); // D3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false); D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); // D3DDevice->SetRenderState(D3DRS_STENCILENABLE, false); D3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); D3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); // D3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS); // works much better D3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); // because geometry is CCW //D3DDevice->SetRenderState(D3DRS_CLIPPING, FALSE); /* don't change anything in the reflection-pass */ if (currentPass == OBGEPASS_MAIN) { D3DDevice->SetTexture(2, passTexture[OBGEPASS_REFLECTION]); /* write to the incoming surface */ D3DDevice->SetRenderTarget(0, RenderFrom); D3DDevice->SetDepthStencilSurface(GetDepthBufferSurface()); // D3DDevice->SetDepthStencilSurface(GetStencilSurface()); } #define INNER (1 >> 1) #define FARNEAR (5 >> 1) #define FARFAR (7 >> 1) #define FARINF (25 >> 1) Render<INNER, FARNEAR, GRID_FARNEAR>(D3DDevice); Render<FARNEAR, FARFAR, GRID_FARFAR >(D3DDevice); Render<FARFAR, FARINF, GRID_FARINF >(D3DDevice); // D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); // menus come after // D3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); // D3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); if ((currentPass == OBGEPASS_MAIN) && 0) markerReset(D3DDevice); /* don't change anything in the reflection-pass */ if (currentPass == OBGEPASS_MAIN) { D3DDevice->SetRenderTarget(0, RenderTo); // D3DDevice->SetDepthStencilSurface(NULL); } #if 1 //def OBGE_STATEBLOCKS /* auto restore (not strictly needed, all states can be changed) */ pStateBlock->Apply(); pStateBlock->Release(); #endif } }