bool CN3Texture::CreateFromSurface(LPDIRECT3DSURFACE8 lpSurf, D3DFORMAT Format, BOOL bGenerateMipMap) { if(lpSurf == NULL) return false; D3DSURFACE_DESC sd; lpSurf->GetDesc(&sd); if(this->Create(sd.Width, sd.Height, Format, bGenerateMipMap) == false) return false; if(bGenerateMipMap) { this->GenerateMipMap(lpSurf); } return true; }
void SimpleBitmapDraw(char* PathName, LPDIRECT3DSURFACE8 pBackSurf, int dpx, int dpy){ LPDIRECT3DSURFACE8 pSurface = 0; LoadBitmapToSurface(PathName, &pSurface, g_pDevice); D3DSURFACE_DESC d3dsd; pSurface->GetDesc(&d3dsd);//get info about surface POINT DestPoint = {dpx, dpy}; RECT rect = {0,0, d3dsd.Width, d3dsd.Height};//source dimensions g_pDevice->CopyRects(pSurface, &rect, 1, pBackSurf, &DestPoint);//copy surface to buffer (like a bitblt) // pSurface->Release(); // pSurface = 0; // pBackSurf->Release(); // pBackSurf = 0; // // g_pDevice->Present(NULL, NULL, NULL, NULL);//put it on the primary surface }
// Converts any fully transparent pixels to black so that the mse calcs work for dxt void FixTransparency(LPDIRECT3DSURFACE8 pSrcSurf) { D3DSURFACE_DESC desc; pSrcSurf->GetDesc(&desc); D3DLOCKED_RECT slr; if (FAILED(pSrcSurf->LockRect(&slr, NULL, 0))) return; DWORD* pix = (DWORD*)slr.pBits; for (UINT y = 0; y < desc.Width; ++y) { for (UINT x = 0; x < desc.Height; ++x) { if (!(*pix & 0xff000000)) *pix = 0; ++pix; } } pSrcSurf->UnlockRect(); }
int Render(){ HRESULT r; // D3DLOCKED_RECT LockedRect;//locked area of display memory(buffer really) we are drawing to LPDIRECT3DSURFACE8 pBackSurf = 0; if(!g_pDevice){ SetError("Cannot render because there is no device"); return E_FAIL; } //clear the display arera with colour black, ignore stencil buffer g_pDevice->Clear(0,0,D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,25), 1.0f, 0); //get pointer to backbuffer r=g_pDevice->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO, &pBackSurf); if(FAILED(r)){ SetError("Couldn't get backbuffer"); } /* //get a lock on the surface r=pBackSurf->LockRect(&LockedRect, NULL, 0); if(FAILED(r)){ SetError("Could not lock the back buffer"); } DWORD* pData = (DWORD*)(LockedRect.pBits); //DRAW CODE GOES HERE - use pData Draw(LockedRect.Pitch, pData); */ LPDIRECT3DSURFACE8 pSurface = 0; r=LoadBitmapToSurface("baboon.bmp", &pSurface, g_pDevice); if(FAILED(r)){ SetError("could not load bitmap surface"); } D3DSURFACE_DESC d3dsd; pSurface->GetDesc(&d3dsd);//get info about surface POINT DestPoint = {0, 0}; RECT rect = {0,0, d3dsd.Width, d3dsd.Height};//source dimensions // SetError("size x=%d size y=%d format=%d",d3dsd.Width, d3dsd.Height, d3dsd.Format); // r=g_pDevice->CopyRects(pSurface, &rect, 1, pBackSurf, &DestPoint);//copy surface to buffer (like a bitblt) r=D3DXLoadSurfaceFromSurface(pBackSurf, NULL, NULL, pSurface, NULL, &rect, D3DX_FILTER_TRIANGLE,0); // r=D3DXLoadSurfaceFromSurface(pBackSurf, NULL, NULL, pSurface, NULL, &rect, D3DX_FILTER_POINT, 0); if(ERROR(r)) SetError("did not copy surface"); // SimpleBitmapDraw("baboon.bmp", pBackSurf, 10,10); pSurface->Release(); pSurface = 0; // pBackSurf->UnlockRect(); // pData = 0; // pBackSurf->Release();//release lock // pBackSurf = 0; g_pDevice->Present(NULL, NULL, NULL, NULL);//swap over buffer to primary surface return S_OK; }
void CApplicationRenderer::Process() { #ifndef HAS_SDL int iWidth = 0; int iHeight = 0; int iLeft = 0; int iTop = 0; LPDIRECT3DSURFACE8 lpSurfaceBack = NULL; LPDIRECT3DSURFACE8 lpSurfaceFront = NULL; while (!m_bStop) { if (!m_enabled || g_graphicsContext.IsFullScreenVideo()) { Sleep(50); continue; } if (!m_pWindow || iWidth == 0 || iHeight == 0 || m_Resolution != g_graphicsContext.GetVideoResolution()) { m_pWindow = (CGUIDialogBusy*)m_gWindowManager.GetWindow(WINDOW_DIALOG_BUSY); if (m_pWindow) { m_pWindow->Initialize();//need to load the window to determine size. if (m_pWindow->GetID() == WINDOW_INVALID) { //busywindow couldn't be loaded so stop this thread. m_pWindow = NULL; m_bStop = true; break; } SAFE_RELEASE(m_lpSurface); FRECT rect = m_pWindow->GetScaledBounds(); m_pWindow->ClearAll(); //unload iLeft = (int)floor(rect.left); iTop = (int)floor(rect.top); iWidth = (int)ceil(rect.right - rect.left); iHeight = (int)ceil(rect.bottom - rect.top); m_Resolution = g_graphicsContext.GetVideoResolution(); } } float t0 = (1000.0f/g_graphicsContext.GetFPS()); float t1 = m_time + t0; //time when we expect a new render float t2 = (float)timeGetTime(); if (t1 < t2) //we're late rendering { try { if (timeGetTime() >= (m_time + g_advancedSettings.m_busyDialogDelay)) { CSingleLock lockg (g_graphicsContext); if (m_prevbusycount != m_busycount) { Sleep(1); continue; } if (!m_pWindow || iWidth == 0 || iHeight == 0) { Sleep(1000); continue; } if (m_Resolution != g_graphicsContext.GetVideoResolution()) { continue; } if (m_busycount > 0) m_busycount--; //no busy indicator if a progress dialog is showing if ((m_gWindowManager.HasModalDialog() && (m_gWindowManager.GetTopMostModalDialogID() != WINDOW_VIDEO_INFO) && (m_gWindowManager.GetTopMostModalDialogID() != WINDOW_MUSIC_INFO)) || (m_gWindowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_PROGRESS)) { //TODO: render progress dialog here instead of in dialog::Progress m_time = timeGetTime(); lockg.Leave(); Sleep(1); continue; } if (m_lpSurface == NULL) { D3DSURFACE_DESC desc; g_application.RenderNoPresent(); HRESULT result = g_graphicsContext.Get3DDevice()->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &lpSurfaceFront); if (SUCCEEDED(result)) { lpSurfaceFront->GetDesc( &desc ); iLeft = 0; iTop = 0; iWidth = desc.Width; iHeight = desc.Height; } else { lockg.Leave(); Sleep(1000); continue; } if (!SUCCEEDED(g_graphicsContext.Get3DDevice()->CreateImageSurface(iWidth, iHeight, desc.Format, &m_lpSurface))) { SAFE_RELEASE(lpSurfaceFront); lockg.Leave(); Sleep(1000); continue; } //copy part underneeth busy dialog const RECT rc = { iLeft, iTop, iLeft + iWidth, iTop + iHeight }; const RECT rcDest = { 0, 0, iWidth, iHeight }; if (!CopySurface(lpSurfaceFront, &rc, m_lpSurface, &rcDest)) { SAFE_RELEASE(lpSurfaceFront); SAFE_RELEASE(m_lpSurface); lockg.Leave(); Sleep(1000); continue; } //copy front buffer to backbuffer(s) to avoid jumping bool bBufferCopied = true; for (int i = 0; i < g_graphicsContext.GetBackbufferCount(); i++) { if (!SUCCEEDED(g_graphicsContext.Get3DDevice()->GetBackBuffer( i, D3DBACKBUFFER_TYPE_MONO, &lpSurfaceBack))) { bBufferCopied = false; break; } if (!CopySurface(lpSurfaceFront, NULL, lpSurfaceBack, NULL)) { bBufferCopied = false; break; } SAFE_RELEASE(lpSurfaceBack); } if (!bBufferCopied) { SAFE_RELEASE(lpSurfaceFront); SAFE_RELEASE(lpSurfaceBack); SAFE_RELEASE(m_lpSurface); lockg.Leave(); Sleep(1000); continue; } SAFE_RELEASE(lpSurfaceFront); } if (!SUCCEEDED(g_graphicsContext.Get3DDevice()->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &lpSurfaceBack))) { lockg.Leave(); Sleep(1000); continue; } g_graphicsContext.Get3DDevice()->BeginScene(); //copy dialog background to backbuffer const RECT rc = { 0, 0, iWidth, iHeight }; const RECT rcDest = { iLeft, iTop, iLeft + iWidth, iTop + iHeight }; const D3DRECT rc2 = { iLeft, iTop, iLeft + iWidth, iTop + iHeight }; g_graphicsContext.Get3DDevice()->Clear(1, &rc2, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00010001, 1.0f, 0L); if (!CopySurface(m_lpSurface, &rc, lpSurfaceBack, &rcDest)) { SAFE_RELEASE(lpSurfaceBack); g_graphicsContext.Get3DDevice()->EndScene(); lockg.Leave(); Sleep(1000); continue; } SAFE_RELEASE(lpSurfaceBack); if (!m_busyShown) { m_pWindow->Show(); m_busyShown = true; } m_pWindow->Render(); g_graphicsContext.Get3DDevice()->EndScene(); //D3DSWAPEFFECT_DISCARD is used so we can't just present the busy rect but can only present the entire screen. g_graphicsContext.Get3DDevice()->Present( NULL, NULL, NULL, NULL ); } m_busycount++; m_prevbusycount = m_busycount; } catch (...) { CLog::Log(LOGERROR, __FUNCTION__" - Exception caught when busy rendering"); SAFE_RELEASE(lpSurfaceFront); SAFE_RELEASE(lpSurfaceBack); SAFE_RELEASE(m_lpSurface); } } Sleep(1); } #endif }
// Converts to P8 format is colours <= 256 bool ConvertP8(LPDIRECT3DSURFACE8 pSrcSurf, LPDIRECT3DSURFACE8& pDstSurf, DWORD* pal, D3DXIMAGE_INFO &info) { pDstSurf = 0; D3DSURFACE_DESC desc; pSrcSurf->GetDesc(&desc); // convert to p8 UINT Width = PadPow2(desc.Width); UINT Height = PadPow2(desc.Height); HRESULT hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &pDstSurf); CheckHR(hr); D3DLOCKED_RECT slr, dlr; hr = pDstSurf->LockRect(&dlr, NULL, 0); CheckHR(hr); hr = pSrcSurf->LockRect(&slr, NULL, D3DLOCK_READONLY); CheckHR(hr); DWORD* src = (DWORD*)slr.pBits; BYTE* dst = (BYTE*)dlr.pBits; int n = 0, i; for (UINT y = 0; y < info.Height; ++y) { for (UINT x = 0; x < info.Width; ++x) { for (i = 0; i < n; ++i) { if (pal[i] == *src) break; } if (i == n) { if (n >= 256) { TRACE0(" Too many colours for P8\n"); pSrcSurf->UnlockRect(); pDstSurf->UnlockRect(); pDstSurf->Release(); return false; } pal[n++] = *src; } *dst++ = i; ++src; } for (UINT x = info.Width; x < Width; ++x) { *dst++ = 0; // we don't care about the colour outside of our real image ++src; } } for (UINT y = info.Height; y < Height; ++y) { for (UINT x = 0; x < Width; ++x) { *dst++ = 0; // we don't care about the colour outside of our real image ++src; } } TRACE1(" Colours Used: %d\n", n); pDstSurf->UnlockRect(); pSrcSurf->UnlockRect(); return true; }
void AppendXPRImage(const D3DXIMAGE_INFO& info, LPDIRECT3DSURFACE8 pSrcSurf, XB_D3DFORMAT fmt) { D3DSURFACE_DESC desc; pSrcSurf->GetDesc(&desc); HRESULT hr; UINT Pitch; UINT Size; if (fmt == XB_D3DFMT_DXT1 || fmt == XB_D3DFMT_DXT3 || fmt == XB_D3DFMT_DXT5) { if (fmt == XB_D3DFMT_DXT1) Pitch = desc.Width / 2; else Pitch = desc.Width; Size = ((Pitch * desc.Height) + 127) & ~127; // must be 128-byte aligned for any following images Pitch *= 4; VirtualAlloc(XPRFile.Data, Size, MEM_COMMIT, PAGE_READWRITE); D3DLOCKED_RECT slr; hr = pSrcSurf->LockRect(&slr, NULL, D3DLOCK_READONLY); if (FAILED(hr)) { printf("ERROR: %08x\n", hr); return; } hr = CompressRect(XPRFile.Data, fmt, Pitch, desc.Width, desc.Height, slr.pBits, XB_D3DFMT_LIN_A8R8G8B8, slr.Pitch, 0.5f, 0); if (FAILED(hr)) { printf("ERROR: %08x\n", hr); return; } pSrcSurf->UnlockRect(); } else { UINT bpp = BytesPerPixelFromFormat(fmt); Pitch = desc.Width * bpp; Size = ((Pitch * desc.Height) + 127) & ~127; // must be 128-byte aligned for any following images VirtualAlloc(XPRFile.Data, Size, MEM_COMMIT, PAGE_READWRITE); D3DLOCKED_RECT slr; hr = pSrcSurf->LockRect(&slr, NULL, D3DLOCK_READONLY); if (FAILED(hr)) { printf("ERROR: %08x\n", hr); return; } if (IsSwizzledFormat(fmt)) { // Swizzle for xbox SwizzleRect(slr.pBits, 0, NULL, XPRFile.Data, desc.Width, desc.Height, NULL, bpp); } else { // copy BYTE* src = (BYTE*)slr.pBits; BYTE* dst = (BYTE*)XPRFile.Data; for (UINT y = 0; y < desc.Height; ++y) { memcpy(dst, src, desc.Width * bpp); src += slr.Pitch; dst += Pitch; } } pSrcSurf->UnlockRect(); } SetTextureHeader(desc.Width, desc.Height, 1, 0, fmt, D3DPOOL_DEFAULT, &XPRFile.Texture[XPRFile.nImages].D3DTex, XPRFile.Data - XPRFile.DataStart, Pitch); if (!(*XPRFile.flags & XPRFLAG_ANIM)) XPRFile.Texture[XPRFile.nImages].RealSize = (info.Width & 0xffff) | ((info.Height & 0xffff) << 16); ++XPRFile.nImages; XPRFile.Data += Size; CompressedSize += Size; }
//----------------------------------------------------------------------------- // Name: XBUtil_DumpSurface() // Desc: Writes the contents of a surface (32-bit only) to a .tga file. This // could be a backbuffer, texture, or any other 32-bit surface. //----------------------------------------------------------------------------- HRESULT XBUtil_DumpSurface( LPDIRECT3DSURFACE8 pSurface, const CHAR* strFileName, BOOL bSurfaceIsTiled ) { // Get the surface description. Make sure it's a 32-bit format D3DSURFACE_DESC desc; pSurface->GetDesc( &desc ); if( desc.Size != ( desc.Width * desc.Height * sizeof(DWORD) ) ) return E_NOTIMPL; // Lock the surface D3DLOCKED_RECT lock; if( FAILED( pSurface->LockRect( &lock, 0, bSurfaceIsTiled ? D3DLOCK_TILED : 0 ) ) ) return E_FAIL; // Allocate memory for storing the surface bits VOID* pBits = (VOID*)new DWORD[desc.Width*desc.Height]; // Unswizzle the bits, if necessary if( XGIsSwizzledFormat( desc.Format ) ) XGUnswizzleRect( lock.pBits, desc.Width, desc.Height, NULL, pBits, lock.Pitch, NULL, sizeof(DWORD) ); else memcpy( pBits, lock.pBits, desc.Size ); // Unlock the surface pSurface->UnlockRect(); // Setup the TGA file header struct TargaHeader { BYTE IDLength; BYTE ColormapType; BYTE ImageType; BYTE ColormapSpecification[5]; WORD XOrigin; WORD YOrigin; WORD ImageWidth; WORD ImageHeight; BYTE PixelDepth; BYTE ImageDescriptor; } tgaHeader; ZeroMemory( &tgaHeader, sizeof(tgaHeader) ); tgaHeader.IDLength = 0; tgaHeader.ImageType = 2; tgaHeader.ImageWidth = (WORD)desc.Width; tgaHeader.ImageHeight = (WORD)desc.Height; tgaHeader.PixelDepth = 32; tgaHeader.ImageDescriptor = 0x28; // Create a new file FILE* file = fopen( strFileName, "wb" ); if( NULL == file ) { pSurface->UnlockRect(); return E_FAIL; } // Write the Targa header and the surface pixels to the file fwrite( &tgaHeader, sizeof(TargaHeader), 1, file ); fwrite( pBits, sizeof(BYTE), desc.Size, file ); fclose( file ); // Cleanup and return delete[] pBits; return S_OK; }
//----------------------------------------------------------------------------- // Name: RestoreDeviceObjects // Desc: //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::RestoreDeviceObjects() { HRESULT hr; // Restore the font m_pFont->RestoreDeviceObjects(); m_pFontSmall->RestoreDeviceObjects(); // Create light D3DLIGHT8 light; ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_DIRECTIONAL; light.Diffuse.r = m_colorLight.r; light.Diffuse.g = m_colorLight.g; light.Diffuse.b = m_colorLight.b; light.Diffuse.a = m_colorLight.a; light.Specular.r = 1.0f; light.Specular.g = 1.0f; light.Specular.b = 1.0f; light.Specular.a = 0.0f; light.Direction.x = m_vecLight.x; light.Direction.y = m_vecLight.y; light.Direction.z = m_vecLight.z; m_pd3dDevice->SetLight(0, &light); m_pd3dDevice->LightEnable(0, TRUE); // Create material D3DMATERIAL8 material; ZeroMemory(&material, sizeof(material)); material.Diffuse.a = 1.0f; material.Specular.r = 0.5f; material.Specular.g = 0.5f; material.Specular.b = 0.5f; material.Power = 20.0f; m_pd3dDevice->SetMaterial(&material); // Setup render states m_pd3dDevice->SetVertexShader(D3DFVF_XYZ); m_pd3dDevice->SetTransform(D3DTS_VIEW, &m_matView); m_pd3dDevice->SetTransform(D3DTS_WORLD, &m_matIdentity); m_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); m_pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE); m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); m_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT); m_pd3dDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR); m_pd3dDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); m_pd3dDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_POINT); m_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); m_pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); m_pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); m_pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); m_pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); m_pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); m_pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT); m_pd3dDevice->SetTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR); m_pd3dDevice->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); m_pd3dDevice->SetTextureStageState(1, D3DTSS_MIPFILTER, D3DTEXF_POINT); m_pd3dDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); // Create caustic texture D3DDISPLAYMODE mode; m_pd3dDevice->GetDisplayMode(&mode); if(FAILED(hr = D3DXCreateTexture(m_pd3dDevice, WATER_CAUSTICS_SIZE, WATER_CAUSTICS_SIZE, 1, D3DUSAGE_RENDERTARGET, mode.Format, D3DPOOL_DEFAULT, &m_pCausticTex)) && FAILED(hr = D3DXCreateTexture(m_pd3dDevice, WATER_CAUSTICS_SIZE, WATER_CAUSTICS_SIZE, 1, 0, mode.Format, D3DPOOL_DEFAULT, &m_pCausticTex))) { return hr; } D3DSURFACE_DESC desc; m_pCausticTex->GetSurfaceLevel(0, &m_pCausticSurf); m_pCausticSurf->GetDesc(&desc); if(FAILED(hr = D3DXCreateRenderToSurface(m_pd3dDevice, desc.Width, desc.Height, desc.Format, FALSE, D3DFMT_UNKNOWN, &m_pRenderToSurface))) { return hr; } // Shader TCHAR sz[512]; DXUtil_FindMediaFile(sz, _T("water.sha")); if(FAILED(hr = D3DXCreateEffectFromFile(m_pd3dDevice, sz, &m_pEffect, NULL))) return hr; m_pEffect->SetMatrix("mID", &m_matIdentity); m_pEffect->SetMatrix("mENV", &m_matIdentity); m_pEffect->SetTexture("tFLR", m_pFloorTex); m_pEffect->SetTexture("tCAU", m_pCausticTex); m_pEffect->SetTexture("tENV", m_pSkyCubeTex); if(FAILED(hr = GetNextTechnique(0, FALSE))) return hr; // Set surfaces if(FAILED(hr = m_Environment.SetSurfaces( m_pSkyTex[D3DCUBEMAP_FACE_NEGATIVE_X], m_pSkyTex[D3DCUBEMAP_FACE_POSITIVE_X], m_pSkyTex[D3DCUBEMAP_FACE_NEGATIVE_Y], m_pSkyTex[D3DCUBEMAP_FACE_POSITIVE_Y], m_pSkyTex[D3DCUBEMAP_FACE_POSITIVE_Z], m_pSkyTex[D3DCUBEMAP_FACE_NEGATIVE_Z]))) { return hr; } // OnResetDevice if(FAILED(hr = m_Water.OnResetDevice())) return hr; if(FAILED(hr = m_Environment.OnResetDevice())) return hr; return S_OK; }
// read depth buffer and update visibility flag of depth points static void UpdateDepthPointsVisibility( const CDrawPort *pdp, const INDEX iMirrorLevel, DepthInfo *pdi, const INDEX ctCount) { const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; ASSERT(GfxValidApi(eAPI)); ASSERT( pdp!=NULL && ctCount>0); const CRaster *pra = pdp->dp_Raster; // OpenGL if( eAPI==GAT_OGL) { _sfStats.StartTimer(CStatForm::STI_GFXAPI); FLOAT fPointOoK; // for each stored point for( INDEX idi=0; idi<ctCount; idi++) { DepthInfo &di = pdi[idi]; // skip if not in required mirror level or was already checked in this iteration if( iMirrorLevel!=di.di_iMirrorLevel || _iCheckIteration!=di.di_iSwapLastRequest) continue; const PIX pixJ = pra->ra_Height-1 - di.di_pixJ; // OpenGL has Y-inversed buffer! pglReadPixels( di.di_pixI, pixJ, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &fPointOoK); OGL_CHECKERROR; // it is visible if there is nothing nearer in z-buffer already di.di_bVisible = (di.di_fOoK<fPointOoK); } // done _sfStats.StopTimer(CStatForm::STI_GFXAPI); return; } // Direct3D #ifdef SE1_D3D if( eAPI==GAT_D3D) { _sfStats.StartTimer(CStatForm::STI_GFXAPI); // ok, this will get really complicated ... // We'll have to do it thru back buffer because darn DX8 won't let us have values from z-buffer; // Anyway, we'll lock backbuffer, read color from the lens location and try to write little triangle there // with slightly modified color. Then we'll readout that color and see if triangle passes z-test. Voila! :) // P.S. To avoid lock-modify-lock, we need to batch all the locks in one. Uhhhh ... :( COLOR col; INDEX idi; SLONG slColSize; HRESULT hr; D3DLOCKED_RECT rectLocked; D3DSURFACE_DESC surfDesc; LPDIRECT3DSURFACE8 pBackBuffer; // fetch back buffer (different for full screen and windowed mode) const BOOL bFullScreen = _pGfx->gl_ulFlags & GLF_FULLSCREEN; if( bFullScreen) { hr = _pGfx->gl_pd3dDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer); } else { hr = pra->ra_pvpViewPort->vp_pSwapChain->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer); } // what, cannot get a back buffer? if( hr!=D3D_OK) { // to hell with it all _sfStats.StopTimer(CStatForm::STI_GFXAPI); return; } // keep format of back-buffer pBackBuffer->GetDesc(&surfDesc); const D3DFORMAT d3dfBack = surfDesc.Format; // prepare array that'll back-buffer colors from depth point locations _acolDelayed.Push(ctCount); // store all colors for( idi=0; idi<ctCount; idi++) { DepthInfo &di = pdi[idi]; // skip if not in required mirror level or was already checked in this iteration if( iMirrorLevel!=di.di_iMirrorLevel || _iCheckIteration!=di.di_iSwapLastRequest) continue; // fetch pixel _acolDelayed[idi] = 0; const RECT rectToLock = { di.di_pixI, di.di_pixJ, di.di_pixI+1, di.di_pixJ+1 }; hr = pBackBuffer->LockRect( &rectLocked, &rectToLock, D3DLOCK_READONLY); if( hr!=D3D_OK) continue; // skip if lock didn't make it // read, convert and store original color _acolDelayed[idi] = UnpackColor_D3D( (UBYTE*)rectLocked.pBits, d3dfBack, slColSize) | CT_OPAQUE; pBackBuffer->UnlockRect(); } // prepare to draw little triangles there with slightly adjusted colors _sfStats.StopTimer(CStatForm::STI_GFXAPI); gfxEnableDepthTest(); gfxDisableDepthWrite(); gfxDisableBlend(); gfxDisableAlphaTest(); gfxDisableTexture(); _sfStats.StartTimer(CStatForm::STI_GFXAPI); // prepare array and shader _avtxDelayed.Push(ctCount*3); d3dSetVertexShader(D3DFVF_CTVERTEX); // draw one trianle around each depth point INDEX ctVertex = 0; for( idi=0; idi<ctCount; idi++) { DepthInfo &di = pdi[idi]; col = _acolDelayed[idi]; // skip if not in required mirror level or was already checked in this iteration, or wasn't fetched at all if( iMirrorLevel!=di.di_iMirrorLevel || _iCheckIteration!=di.di_iSwapLastRequest || col==0) continue; const ULONG d3dCol = rgba2argb(col^0x20103000); const PIX pixI = di.di_pixI - pdp->dp_MinI; // convert raster loc to drawport loc const PIX pixJ = di.di_pixJ - pdp->dp_MinJ; // batch it and advance to next triangle CTVERTEX &vtx0 = _avtxDelayed[ctVertex++]; CTVERTEX &vtx1 = _avtxDelayed[ctVertex++]; CTVERTEX &vtx2 = _avtxDelayed[ctVertex++]; vtx0.fX=pixI; vtx0.fY=pixJ-2; vtx0.fZ=di.di_fOoK; vtx0.ulColor=d3dCol; vtx0.fU=vtx0.fV=0; vtx1.fX=pixI-2; vtx1.fY=pixJ+2; vtx1.fZ=di.di_fOoK; vtx1.ulColor=d3dCol; vtx1.fU=vtx0.fV=0; vtx2.fX=pixI+2; vtx2.fY=pixJ; vtx2.fZ=di.di_fOoK; vtx2.ulColor=d3dCol; vtx2.fU=vtx0.fV=0; } // draw a bunch hr = _pGfx->gl_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, ctVertex/3, &_avtxDelayed[0], sizeof(CTVERTEX)); D3D_CHECKERROR(hr); // readout colors again and compare to old ones for( idi=0; idi<ctCount; idi++) { DepthInfo &di = pdi[idi]; col = _acolDelayed[idi]; // skip if not in required mirror level or was already checked in this iteration, or wasn't fetched at all if( iMirrorLevel!=di.di_iMirrorLevel || _iCheckIteration!=di.di_iSwapLastRequest || col==0) continue; // fetch pixel const RECT rectToLock = { di.di_pixI, di.di_pixJ, di.di_pixI+1, di.di_pixJ+1 }; hr = pBackBuffer->LockRect( &rectLocked, &rectToLock, D3DLOCK_READONLY); if( hr!=D3D_OK) continue; // skip if lock didn't make it // read new color const COLOR colNew = UnpackColor_D3D( (UBYTE*)rectLocked.pBits, d3dfBack, slColSize) | CT_OPAQUE; pBackBuffer->UnlockRect(); // if we managed to write adjusted color, point is visible! di.di_bVisible = (col!=colNew); } // phew, done! :) D3DRELEASE( pBackBuffer, TRUE); _acolDelayed.PopAll(); _avtxDelayed.PopAll(); _sfStats.StopTimer(CStatForm::STI_GFXAPI); return; } #endif // SE1_D3D }