//
	//	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;
	}
Esempio n. 2
0
// 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;
	}
Esempio n. 4
0
// 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();
}
Esempio n. 5
0
void DevState::releaseAll() {
	ods("D3D9: Release All");
	releaseData();
	if (pSB)
		pSB->Release();
	pSB = NULL;
}
Esempio n. 6
0
void CState::Save()
{
    if( !m_StateBlock && m_D3DDev )
        m_D3DDev->CreateStateBlock(D3DSBT_ALL, &m_StateBlock);

    if( m_StateBlock )
        m_StateBlock->Capture();
}
Esempio n. 7
0
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();
    }
}
Esempio n. 8
0
// 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();
}
Esempio n. 9
0
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();
}
Esempio n. 10
0
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);
	}
}
Esempio n. 11
0
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;
	}
}
Esempio n. 12
0
		//--------------------------------------------------------------------------------
		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();
			}
		}
Esempio n. 13
0
// 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();
    }
}
Esempio n. 14
0
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);
}
Esempio n. 15
0
STDMETHODIMP CDirect3DDevice8::DeleteStateBlock(THIS_ DWORD Token)
{
	IDirect3DStateBlock9* pBlock = (IDirect3DStateBlock9*)Token;
	pBlock->Release();
	return D3D_OK;
}
Esempio n. 16
0
STDMETHODIMP CDirect3DDevice8::CaptureStateBlock(THIS_ DWORD Token)
{
	IDirect3DStateBlock9* pBlock = (IDirect3DStateBlock9*)Token;
	return pBlock->Capture();
}
Esempio n. 17
0
STDMETHODIMP CDirect3DDevice8::ApplyStateBlock(THIS_ DWORD Token)
{
	IDirect3DStateBlock9* pBlock = (IDirect3DStateBlock9*)Token;
	return pBlock->Apply();
}
Esempio n. 18
0
/******************************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;
}
Esempio n. 20
0
////////////////////////////////////////////////////////////////
//
// 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 );
    }
}
Esempio n. 21
0
/// 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;
}
Esempio n. 23
0
	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;
	}
Esempio n. 24
0
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();
}
Esempio n. 25
0
// 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();
}
Esempio n. 26
0
void CState::Restore()
{
    if( m_StateBlock )
        m_StateBlock->Apply();
}
Esempio n. 27
0
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
  }
}