static bool convert_compressed(LPDIRECT3DTEXTURE9 dest, LPDIRECT3DTEXTURE9 src, int x, int y, int width, int height) { #ifdef ALLEGRO_CFG_D3DX9 bool ok = true; LPDIRECT3DSURFACE9 dest_texture_surface = NULL; LPDIRECT3DSURFACE9 src_texture_surface = NULL; if (dest->GetSurfaceLevel(0, &dest_texture_surface) != D3D_OK) { ALLEGRO_ERROR("convert_compressed: GetSurfaceLevel failed on dest.\n"); ok = false; } if (ok && src->GetSurfaceLevel(0, &src_texture_surface) != D3D_OK) { ALLEGRO_ERROR("convert_compressed: GetSurfaceLevel failed on src.\n"); ok = false; } RECT rect; rect.left = x; rect.top = y; rect.right = x + width; rect.bottom = y + height; if (ok && _al_imp_D3DXLoadSurfaceFromSurface && _al_imp_D3DXLoadSurfaceFromSurface(dest_texture_surface, NULL, &rect, src_texture_surface, NULL, &rect, D3DX_FILTER_NONE, 0) != D3D_OK) { ALLEGRO_ERROR("convert_compressed: D3DXLoadSurfaceFromSurface failed.\n"); ok = false; } int i; if (src_texture_surface) { if ((i = src_texture_surface->Release()) != 0) { ALLEGRO_DEBUG("convert_compressed (src) ref count == %d\n", i); } } if (dest_texture_surface) { if ((i = dest_texture_surface->Release()) != 0) { // This can be non-zero ALLEGRO_DEBUG("convert_compressed (dest) ref count == %d\n", i); } } return ok; #else (void)dest; (void)src; (void)x; (void)y; (void)width; (void)height; return false; #endif }
void InitStateDX9(void) { // 取得Direct3D 9裝置 LPDIRECT3DDEVICE9 device = GutGetGraphicsDeviceDX9(); // 關閉打光 device->SetRenderState(D3DRS_LIGHTING, FALSE); // 使用trilinear device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); // device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); // device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE); device->GetRenderTarget(0, &g_pMainFrameBuffer); device->GetDepthStencilSurface(&g_pMainDepthBuffer); int width, height; GutGetWindowSize(width, height); g_iFrameBufferWidth = width * 2; g_iFrameBufferHeight = height * 2; device->CreateTexture(g_iFrameBufferWidth, g_iFrameBufferHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_pTexture, NULL); device->CreateDepthStencilSurface(g_iFrameBufferWidth, g_iFrameBufferHeight, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, FALSE, &g_pDepthStencil, NULL); g_pTexture->GetSurfaceLevel(0, &g_pFrameBuffer); }
int RendererD3D::InitializeTextureFromBits(byte* pImageBits, int width, int height) { HRESULT result; LPDIRECT3DSURFACE9 surface=NULL; LPDIRECT3DTEXTURE9 texture = NULL; result = D3DXCreateTexture( m_pd3dDevice, width, height, D3DX_DEFAULT, 0, D3DFMT_R8G8B8,D3DPOOL_MANAGED, &texture); texture->GetSurfaceLevel(0, &surface); RECT rect; rect.top = 0; rect.left = 0; rect.bottom = height; rect.right = width; result = D3DXLoadSurfaceFromMemory(surface,NULL,NULL,pImageBits,D3DFMT_R8G8B8, width*3*sizeof(byte),NULL,&rect,D3DX_DEFAULT,0); surface->Release(); assert(result == D3D_OK); m_textureList.push_back(texture); return (m_textureList.size()-1); }
//----------------------------------------------------------------------------- // Desc: 初始化Direct3D //----------------------------------------------------------------------------- HRESULT InitD3D(HWND hWnd) { //创建Direct3D对象, 该对象用于创建Direct3D设备对象 if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION))) return E_FAIL; //设置D3DPRESENT_PARAMETERS结构, 准备创建Direct3D设备对象 D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; //创建Direct3D设备对象 if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice))) { return E_FAIL; } //禁用照明效果 g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); HRESULT hr = g_pd3dDevice->CreateTexture(256, 256, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_pRenderTex, NULL); if (FAILED(hr)) { return E_FAIL; } g_pRenderTex->GetSurfaceLevel(0, &g_pRenderSur); hr = g_pd3dDevice->CreateTexture(256, 256, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_pRender2Tex, NULL); if (FAILED(hr)) { return E_FAIL; } g_pRender2Tex->GetSurfaceLevel(0, &g_pRender2Sur); return S_OK; }
//************************************************************************************************************* void BlurTexture(LPDIRECT3DTEXTURE9 tex) { LPDIRECT3DSURFACE9 surface = NULL; LPDIRECT3DSURFACE9 blursurface = NULL; LPDIRECT3DTEXTURE9 blurtex = NULL; D3DXVECTOR4 texelsize(1.0f / SHADOWMAP_SIZE, 0, 0, 0); D3DSURFACE_DESC desc; tex->GetLevelDesc(0, &desc); if( desc.Format == D3DFMT_A8R8G8B8 ) blurtex = blurARGB8; // for convolution else blurtex = blurRGBA32F; // for others blurtex->GetSurfaceLevel(0, &blursurface); tex->GetSurfaceLevel(0, &surface); device->SetRenderTarget(0, blursurface); device->SetTexture(0, tex); device->SetVertexDeclaration(vertexdecl); boxblur5x5->SetVector("texelSize", &texelsize); boxblur5x5->Begin(NULL, 0); boxblur5x5->BeginPass(0); { device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, &vertices[0], 6 * sizeof(float)); std::swap(texelsize.x, texelsize.y); boxblur5x5->SetVector("texelSize", &texelsize); boxblur5x5->CommitChanges(); device->SetRenderTarget(0, surface); device->SetTexture(0, blurtex); device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, &vertices[0], 6 * sizeof(float)); } boxblur5x5->EndPass(); boxblur5x5->End(); surface->Release(); blursurface->Release(); }
HRESULT InitScene() { HRESULT hr; LPD3DXBUFFER errors = NULL; D3DVERTEXELEMENT9 decl[] = { { 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0 }, { 0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() }; SetWindowText(hwnd, TITLE); MYVALID(CreateColorTex(device, 0xff77FF70, &texture)); MYVALID(D3DXLoadMeshFromXA("../media/meshes/knot.X", D3DXMESH_MANAGED, device, NULL, NULL, NULL, NULL, &mesh)); MYVALID(D3DXCreateTextureFromFileA(device, "../media/textures/intensity.png", &intensity)); MYVALID(device->CreateTexture(screenwidth, screenheight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &colortarget, NULL)); MYVALID(device->CreateTexture(screenwidth, screenheight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &normaltarget, NULL)); MYVALID(device->CreateTexture(screenwidth, screenheight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &edgetarget, NULL)); MYVALID(device->CreateVertexDeclaration(decl, &vertexdecl)); edgetarget->GetSurfaceLevel(0, &edgesurface); colortarget->GetSurfaceLevel(0, &colorsurface); normaltarget->GetSurfaceLevel(0, &normalsurface); MYVALID(device->CreateTexture(512, 512, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &text, NULL)); MYVALID(DXCreateEffect("../media/shaders/celshading.fx", device, &effect)); DXRenderText(HELP_TEXT, text, 512, 512); D3DXVECTOR3 eye(0.5f, 0.5f, -1.5f); D3DXVECTOR3 look(0, 0, 0); D3DXVECTOR3 up(0, 1, 0); D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI / 3, (float)screenwidth / (float)screenheight, 0.1f, 10); D3DXMatrixLookAtLH(&view, &eye, &look, &up); D3DXMatrixIdentity(&world); return S_OK; }
void SetD3DResourcePrivateData(LPDIRECT3DRESOURCE9 res, const char* FName) { #if R3D_SET_DEBUG_D3D_NAMES DWORD sz = strlen(FName); res->SetPrivateData(WKPDID_D3DDebugObjectName, FName, sz, 0); void* p = 0; res->QueryInterface(IID_IDirect3DTexture9, &p); if(p) { LPDIRECT3DTEXTURE9 t = (LPDIRECT3DTEXTURE9)p; int mipsCount = t->GetLevelCount(); for (int i = 0; i < mipsCount; ++i) { LPDIRECT3DSURFACE9 surf; t->GetSurfaceLevel(i, &surf); surf->SetPrivateData(WKPDID_D3DDebugObjectName, FName, sz, 0); surf->Release(); } t->Release(); return; } p = 0; res->QueryInterface(IID_IDirect3DCubeTexture9, &p); if(p) { LPDIRECT3DCUBETEXTURE9 t = (LPDIRECT3DCUBETEXTURE9)p; int mipsCount = t->GetLevelCount(); for (int i = 0; i < mipsCount; ++i) { for (int j = D3DCUBEMAP_FACE_POSITIVE_X; j <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++j) { LPDIRECT3DSURFACE9 surf; t->GetCubeMapSurface((D3DCUBEMAP_FACES)j, i, &surf); surf->SetPrivateData(WKPDID_D3DDebugObjectName, FName, sz, 0); surf->Release(); } } t->Release(); return; } #endif }
void AmjuGLDX9::SetTexture( AmjuGL::TextureHandle* th, AmjuGL::TextureType tt, AmjuGL::TextureDepth td, int width, int height, uint8* data) { AMJU_CALL_STACK; HRESULT res = D3DXCreateTexture( dd, //LPDIRECT3DDEVICE9 pDevice, width, //UINT Width, height, //UINT Height, 0, // Mip Levels: 0 means create all D3DUSAGE_DYNAMIC, //DWORD Usage, (td == AmjuGL::AMJU_RGB ? D3DFMT_R8G8B8 : D3DFMT_A8R8G8B8), //D3DFORMAT Format, D3DPOOL_DEFAULT, // Pool, reinterpret_cast<LPDIRECT3DTEXTURE9*>(th) //LPDIRECT3DTEXTURE9 * ppTexture ); LPDIRECT3DTEXTURE9 pTex = reinterpret_cast<LPDIRECT3DTEXTURE9>(*th); D3DLOCKED_RECT lockedRect; pTex->LockRect(0, &lockedRect, NULL, 0); switch (td) { case AmjuGL::AMJU_RGB: CopyRGBTexture((uint8*)lockedRect.pBits, lockedRect.Pitch, data, width, height); break; case AmjuGL::AMJU_RGBA: CopyRGBATexture((uint8*)lockedRect.pBits, lockedRect.Pitch, data, width, height); break; } pTex->UnlockRect(0); // TODO Create data for each mipmap level. // NB We want the same functionality as screenshot shrinking. IDirect3DSurface9 * pSurfaceLevel; for (unsigned int iLevel = 0; iLevel < pTex->GetLevelCount(); iLevel++) { pTex->GetSurfaceLevel(iLevel, &pSurfaceLevel); // TODO Write this mip map pSurfaceLevel->Release(); } }
int surface_create(int width, int height, bool depthbuffer, bool, bool) { LPDIRECT3DTEXTURE9 texture = NULL; d3ddev->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL); enigma::Surface* surface = new enigma::Surface(); enigma::DX9Texture* gmTexture = new enigma::DX9Texture(texture); const int texid = enigma::textures.size(); enigma::textures.push_back(gmTexture); //d3ddev->CreateRenderTarget(width, height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 2, false, &surface->surf, NULL); texture->GetSurfaceLevel(0,&surface->surf); surface->texture = texid; surface->width = width; surface->height = height; enigma::surfaces.push_back(surface); return enigma::surfaces.size() - 1; }
HRESULT VertexObject::CreateTextureFromSurface(LPDIRECT3DSURFACE9 pSurface, RECT* pSrcRect, RECT* pDestRect, LPDIRECT3DTEXTURE9* ppTexture) { int width, height; RECT Src; D3DSURFACE_DESC surfDesc; pSurface->GetDesc(&surfDesc); if( !pSrcRect ) { width = surfDesc.Width; height = surfDesc.Height; Src.left = Src.top = 0; Src.right = width; Src.bottom = height; } else { width = pSrcRect->right - pSrcRect->left; // + 1; height = pSrcRect->bottom - pSrcRect->top; // + 1; Src = *pSrcRect; } D3DXCreateTexture(DDevice, width, height, 1, 0, surfDesc.Format, D3DPOOL_DEFAULT, ppTexture) ; // Retrieve the surface image of the texture. LPDIRECT3DSURFACE9 pTexSurface; LPDIRECT3DTEXTURE9 pTexture = *ppTexture; pTexture->GetLevelDesc(0, &surfDesc); pTexture->GetSurfaceLevel(0, &pTexSurface); // Create a clean surface to clear the texture with. LPDIRECT3DSURFACE9 pCleanSurface; D3DLOCKED_RECT lockRect; DDevice->CreateOffscreenPlainSurface( surfDesc.Width, surfDesc.Height, surfDesc.Format, D3DPOOL_DEFAULT, &pCleanSurface, NULL); pCleanSurface->LockRect(&lockRect, NULL, 0) ; memset((BYTE*)lockRect.pBits, 0, surfDesc.Height * lockRect.Pitch); pCleanSurface->UnlockRect() ; DDevice->UpdateSurface(pCleanSurface, NULL, pTexSurface, NULL); pCleanSurface->Release(); // Copy the image to the texture. POINT destPoint = { 0, 0 }; DDevice->UpdateSurface(pSurface, &Src, pTexSurface, &destPoint); pTexSurface->Release(); return S_OK; }
//-- SetRenderTarget ---------------------------------------------------------- // //----------------------------------------------------------------------------- void Renderer::SetRenderTarget( LPDIRECT3DTEXTURE9 texture ) { IDirect3DSurface9* surface; texture->GetSurfaceLevel( 0, &surface ); m_pD3DDevice->SetRenderTarget( 0, surface ); m_pD3DDevice->SetDepthStencilSurface( g_depthBuffer ); m_pD3DDevice->Clear( 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, 0, 1.0f, 0 ); surface->Release(); // m_renderTargetWidth = texture->Width(); // m_renderTargetHeight = texture->Height(); } // SetRenderTarget
virtual const char* lock_framebuffer( void *& buffer, unsigned & pitch ) { if ( retry_count && !restore_objects() ) return "Lock failed"; lptex->GetLevelDesc(0, &d3dsd); if ( lptex->GetSurfaceLevel(0, &lpsurface) != D3D_OK ) return "Lock failed"; if ( lpsurface->LockRect(&d3dlr, 0, flags.lock) != D3D_OK ) return "Lock failed"; buffer = d3dlr.pBits; pitch = d3dlr.Pitch; return buffer != 0 ? 0 : "Lock failed"; }
bool CAnimationSpooler::SetColorKey(LPDIRECT3DTEXTURE9 pTexture, LPDIRECT3DSURFACE9 pSurface, int iTexSize, COLORREF clrColorKey) { ASSERT(pTexture); ASSERT(pSurface); if( clrColorKey == CLR_INVALID ) return true; // Get colorkey's red, green, and blue components // and put the colorkey in the texture's native format DWORD r = GetRValue(clrColorKey); DWORD g = GetGValue(clrColorKey); DWORD b = GetBValue(clrColorKey); DWORD dwColorKey = D3DCOLOR_ARGB(255,r,g,b); HRESULT Hr; LPDIRECT3DTEXTURE9 pTex = NULL; Hr = m_p3DDevice->CreateTexture(iTexSize, iTexSize, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pTex, NULL); if( FAILED(Hr) ) return false; CSafeRelease<IDirect3DTexture9> RefTex = pTex; LPDIRECT3DSURFACE9 pTexSurf = NULL; Hr = pTex->GetSurfaceLevel(0, &pTexSurf); if( FAILED(Hr) ) return false; CSafeRelease<IDirect3DSurface9> RefTexSurf = pTexSurf; Hr = m_p3DDevice->GetRenderTargetData(pSurface, pTexSurf); if( FAILED(Hr) ) return false; // Lock the texture and scan through each pixel, replacing the colorkey pixels D3DLOCKED_RECT d3dlr; Hr = pTex->LockRect(0, &d3dlr, 0, 0); if( FAILED(Hr) ) return false; DWORD* pBits = static_cast<DWORD*>(d3dlr.pBits); for( int y = 0; y < iTexSize; y++ ) { for( int x = 0; x < iTexSize; x++ ) { if( pBits[x] == dwColorKey ) pBits[x] = 0x00000000; else pBits[x] |= 0xff000000; } pBits += d3dlr.Pitch / sizeof(DWORD); } pTex->UnlockRect(0); // Copy modified data back POINT pt = { 0, 0 }; RECT rcDest = { 0, 0, iTexSize, iTexSize }; Hr = m_p3DDevice->UpdateSurface(pTexSurf, &rcDest, pSurface, &pt); return true; }
void cTexture::BltToTextureSurface(LPDIRECT3DTEXTURE9 pTempTex ) { SafeRelease( m_pTexture ); D3DSURFACE_DESC TexDesc; pTempTex->GetLevelDesc( 0, &TexDesc ); DWORD NumLevels = pTempTex->GetLevelCount(); D3DXCreateTexture( Graphics()->GetDevice(), TexDesc.Width, TexDesc.Height, NumLevels, 0, TexDesc.Format, D3DPOOL_MANAGED, &m_pTexture ); LPDIRECT3DSURFACE9 pSrcSurf = 0; LPDIRECT3DSURFACE9 pDestSurf = 0; for( int i = 0 ; i < NumLevels ; i++ ) { m_pTexture->GetSurfaceLevel( i, &pDestSurf ); pTempTex->GetSurfaceLevel( i, &pSrcSurf ); D3DXLoadSurfaceFromSurface( pDestSurf, 0, 0, pSrcSurf, 0, 0, D3DX_FILTER_NONE, 0 ); pDestSurf->Release(); pSrcSurf->Release(); } }
virtual void clear() { if ( retry_count && !restore_objects() ) return; lptex->GetLevelDesc(0, &d3dsd); lptex->GetSurfaceLevel(0, &lpsurface); if ( lpsurface ) { lpdev->ColorFill( lpsurface, NULL, D3DCOLOR_XRGB(0x00, 0x00, 0x00) ); lpsurface->Release(); lpsurface = 0; } for ( unsigned i = 0; i < 3; i++ ) { lpdev->Clear( 0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0x00, 0x00, 0x00), 1.0f, 0 ); lpdev->Present( 0, 0, 0, 0 ); } }
virtual void OnDistorting() { IDirect3DSurface9* targetSurface = nullptr; IDirect3DSurface9* texSurface = nullptr; HRESULT hr = S_OK; hr = texture->GetSurfaceLevel( 0, &texSurface ); assert(SUCCEEDED(hr)); hr = device->GetRenderTarget( 0, &targetSurface ); assert(SUCCEEDED(hr)); hr = device->StretchRect( targetSurface, NULL, texSurface, NULL, D3DTEXF_NONE); assert(SUCCEEDED(hr)); ES_SAFE_RELEASE( texSurface ); ES_SAFE_RELEASE( targetSurface ); renderer->SetBackground( texture ); }
HRESULT CDxtexDoc::LoadAlphaBmp(CString& strPath) { HRESULT hr; LPDIRECT3DTEXTURE9 pmiptex; LPDIRECT3DSURFACE9 psurf; if (IsCubeMap()) return E_FAIL; pmiptex = (LPDIRECT3DTEXTURE9)m_ptexOrig; hr = pmiptex->GetSurfaceLevel(0, &psurf); if (FAILED(hr)) return hr; hr = LoadAlphaIntoSurface(strPath, psurf); ReleasePpo(&psurf); if (FAILED(hr)) return hr; UpdateAllViews(NULL, 1); // tell CView to pick up new surface pointers return S_OK; }
bool CGUIFontTTFDX::CopyCharToTexture(FT_BitmapGlyph bitGlyph, unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2) { FT_Bitmap bitmap = bitGlyph->bitmap; LPDIRECT3DTEXTURE9 texture = ((CDXTexture *)m_texture)->GetTextureObject(); LPDIRECT3DSURFACE9 target; if (m_speedupTexture) m_speedupTexture->GetSurfaceLevel(0, &target); else texture->GetSurfaceLevel(0, &target); RECT sourcerect = { 0, 0, bitmap.width, bitmap.rows }; RECT targetrect = { x1, y1, x2, y2 }; HRESULT hr = D3DXLoadSurfaceFromMemory( target, NULL, &targetrect, bitmap.buffer, D3DFMT_LIN_A8, bitmap.pitch, NULL, &sourcerect, D3DX_FILTER_NONE, 0x00000000); SAFE_RELEASE(target); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Failed to copy the new character (0x%08X)", hr); return false; } if (m_speedupTexture) { // Upload to GPU - the automatic dirty region tracking takes care of the rect. HRESULT hr = g_Windowing.Get3DDevice()->UpdateTexture(m_speedupTexture->Get(), texture); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Failed to upload from sysmem to vidmem (0x%08X)", hr); return false; } } return TRUE; }
CBaseTexture* CGUIFontTTFDX::ReallocTexture(unsigned int& newHeight) { assert(newHeight != 0); assert(m_textureWidth != 0); if(m_textureHeight == 0) { delete m_texture; m_texture = NULL; delete m_speedupTexture; m_speedupTexture = NULL; } m_staticCache.Flush(); m_dynamicCache.Flush(); CDXTexture* pNewTexture = new CDXTexture(m_textureWidth, newHeight, XB_FMT_A8); pNewTexture->CreateTextureObject(); LPDIRECT3DTEXTURE9 newTexture = pNewTexture->GetTextureObject(); if (newTexture == NULL) { CLog::Log(LOGERROR, __FUNCTION__" - failed to create the new texture h=%d w=%d", m_textureWidth, newHeight); SAFE_DELETE(pNewTexture); return NULL; } // Use a speedup texture in system memory when main texture in default pool+dynamic // Otherwise the texture would have to be copied from vid mem to sys mem, which is too slow for subs while playing video. CD3DTexture* newSpeedupTexture = NULL; if (g_Windowing.DefaultD3DPool() == D3DPOOL_DEFAULT && g_Windowing.DefaultD3DUsage() == D3DUSAGE_DYNAMIC) { newSpeedupTexture = new CD3DTexture(); if (!newSpeedupTexture->Create(m_textureWidth, newHeight, 1, 0, D3DFMT_A8, D3DPOOL_SYSTEMMEM)) { SAFE_DELETE(newSpeedupTexture); SAFE_DELETE(pNewTexture); return NULL; } } LPDIRECT3DSURFACE9 pSource, pTarget; // There might be data to copy from the previous texture if ((newSpeedupTexture && m_speedupTexture) || (newTexture && m_texture)) { if (m_speedupTexture && newSpeedupTexture) { m_speedupTexture->GetSurfaceLevel(0, &pSource); newSpeedupTexture->GetSurfaceLevel(0, &pTarget); } else { ((CDXTexture *)m_texture)->GetTextureObject()->GetSurfaceLevel(0, &pSource); newTexture->GetSurfaceLevel(0, &pTarget); } D3DLOCKED_RECT srclr, dstlr; if(FAILED(pSource->LockRect( &srclr, NULL, 0 )) || FAILED(pTarget->LockRect( &dstlr, NULL, 0 ))) { CLog::Log(LOGERROR, __FUNCTION__" - failed to lock surfaces"); SAFE_DELETE(newSpeedupTexture); SAFE_DELETE(pNewTexture); pSource->Release(); pTarget->Release(); return NULL; } unsigned char *dst = (unsigned char *)dstlr.pBits; unsigned char *src = (unsigned char *)srclr.pBits; unsigned int dstPitch = dstlr.Pitch; unsigned int srcPitch = srclr.Pitch; unsigned int minPitch = std::min(srcPitch, dstPitch); if (srcPitch == dstPitch) { memcpy(dst, src, srcPitch * m_textureHeight); } else { for (unsigned int y = 0; y < m_textureHeight; y++) { memcpy(dst, src, minPitch); src += srcPitch; dst += dstPitch; } } pSource->UnlockRect(); pTarget->UnlockRect(); pSource->Release(); pTarget->Release(); } // Upload from speedup texture to main texture if (newSpeedupTexture && m_speedupTexture) { LPDIRECT3DSURFACE9 pSource, pTarget; newSpeedupTexture->GetSurfaceLevel(0, &pSource); newTexture->GetSurfaceLevel(0, &pTarget); const RECT rect = { 0, 0, m_textureWidth, m_textureHeight }; const POINT point = { 0, 0 }; HRESULT hr = g_Windowing.Get3DDevice()->UpdateSurface(pSource, &rect, pTarget, &point); SAFE_RELEASE(pSource); SAFE_RELEASE(pTarget); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Failed to upload from sysmem to vidmem (0x%08X)", hr); SAFE_DELETE(newSpeedupTexture); SAFE_DELETE(pNewTexture); return NULL; } } SAFE_DELETE(m_texture); SAFE_DELETE(m_speedupTexture); m_textureHeight = newHeight; m_textureScaleY = 1.0f / m_textureHeight; m_speedupTexture = newSpeedupTexture; return pNewTexture; }
INT CrenderTarget::CreateRenderSurface() { HRESULT hr=-1; DWORD dMip = 1; LPDIRECT3DSURFACE9 pSfC = NULL; LPDIRECT3DSURFACE9 pSfD = NULL; D3DSURFACE_DESC dscC; D3DSURFACE_DESC dscD; D3DCAPS9 m_Caps; m_pDev->GetRenderTarget(0,&pSfC); m_pDev->GetDepthStencilSurface(&pSfD); pSfC->GetDesc(&dscC); pSfD->GetDesc(&dscD); m_pDev->GetDeviceCaps(&m_Caps); pSfC->Release(); pSfD->Release(); if(m_iW<0) m_iW = dscC.Width; if(m_iH<0) m_iH = dscC.Height; m_dC = dscC.Format; m_dD = dscD.Format; if(LCX_TARGET_HDR16 == m_nType) m_dC = D3DFMT_A16B16G16R16F; if(LCX_TARGET_HDR32 == m_nType) m_dC = D3DFMT_A32B32G32R32F; hr = D3DXCreateRenderToSurface(m_pDev , m_iW , m_iH , (D3DFORMAT)m_dC , TRUE , (D3DFORMAT)m_dD , &m_pRts); if(FAILED(hr)) return -1; hr = D3DXCreateTexture(m_pDev , m_iW , m_iH , dMip , D3DUSAGE_RENDERTARGET , (D3DFORMAT)m_dC , D3DPOOL_DEFAULT , &m_pTxP); if(FAILED(hr)) return -1; hr = m_pTxP->GetSurfaceLevel(0, &m_pSfc); if(FAILED(hr)) return -1; // Clear 0x0 m_pDev->ColorFill(m_pSfc, NULL, 0x0); return hr; }
// 使用DirectX 9來繪圖 void RenderFrameDX9(void) { LPDIRECT3DDEVICE9 device = GutGetGraphicsDeviceDX9(); Vector4 vPlane(0.0f, 0.0f, 1.0f, -g_mirror_z); // 開始下繪圖指令 device->BeginScene(); { LPDIRECT3DSURFACE9 pFrameBufferBackup, pDepthBufferBackup; device->GetRenderTarget(0, &pFrameBufferBackup); pFrameBufferBackup->Release(); device->GetDepthStencilSurface(&pDepthBufferBackup); pDepthBufferBackup->Release(); LPDIRECT3DSURFACE9 pSurface; g_pTexture->GetSurfaceLevel(0, &pSurface); device->SetRenderTarget(0, pSurface); device->SetDepthStencilSurface(g_pDepthStencil); device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0, 0, 200, 255), 1.0f, 0); RenderModelDX9(true, &vPlane); pSurface->Release(); device->SetRenderTarget(0, pFrameBufferBackup); device->SetDepthStencilSurface(pDepthBufferBackup); } // 把上一個步驟的結果當成貼圖來使用 { // 消除畫面 device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0, 0, 150, 255), 1.0f, 0); RenderModelDX9(false, NULL); Matrix4x4 identMat; identMat.Identity(); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *) &identMat); sModelMaterial_DX9 material; material.m_pTextures[0] = g_pTexture; material.Submit(); device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); device->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); device->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); device->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_NONE); Matrix4x4 uv_offset_matrix; uv_offset_matrix.Scale_Replace(0.5f, -0.5f, 1.0f); uv_offset_matrix[3].Set(0.5f, 0.5f, 0.5f, 1.0f); Matrix4x4 inv_view_matrix = g_Control.GetViewMatrix(); inv_view_matrix.FastInvert(); Matrix4x4 texture_matrix = inv_view_matrix * g_mirror_view_matrix * g_projection_matrix * uv_offset_matrix; device->SetTransform(D3DTS_TEXTURE0, (D3DMATRIX *) &texture_matrix); device->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION); // D3DTTFF_PROJECTED告知direct3d裝置texcoord需要除以w device->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4|D3DTTFF_PROJECTED); float v[12]; for ( int i=0; i<4; i++ ) { g_Quad[i].m_Position.StoreXYZ(&v[i*3]); } // 畫出矩形 device->SetFVF(D3DFVF_XYZ); //device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_Quad, sizeof(Vertex_V)); device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, 12); } // 宣告所有的繪圖指令都下完了 device->EndScene(); // 把背景backbuffer的畫面呈現出來 device->Present( NULL, NULL, NULL, NULL ); }
void C3DCanvas::SaveToFile(const char* sFileName, int nImageSize) { string sFile = sFileName; string sExt = CParaFile::GetFileExtension(sFileName); D3DXIMAGE_FILEFORMAT FileFormat = D3DXIFF_PNG; if(sExt == "dds") { FileFormat = D3DXIFF_DDS; } else if(sExt == "jpg") { FileFormat = D3DXIFF_JPG; } else // if(sExt == "png") { sFile = CParaFile::ChangeFileExtension(sFile, "png"); } if(nImageSize<=0 || nImageSize>= m_nTextureWidth) { if( SUCCEEDED(D3DXSaveTextureToFile(sFile.c_str(), FileFormat, m_canvasTexture->GetTexture(), NULL )) ) { OUTPUT_LOG("canvas portrait %d taken for %s", m_nTextureWidth, sFile.c_str()); } } else { // if the size is somewhere in the middle. /*int nMipLevel = 0; int nWidth = m_nTextureWidth; while (nImageSize <nWidth) { nMipLevel++; nWidth = nWidth / 2; }*/ LPDIRECT3DTEXTURE9 pTex = m_canvasTexture->GetTexture(); if(pTex) { LPDIRECT3DSURFACE9 pSur = NULL; pTex->GetSurfaceLevel(0, &pSur); if(pSur) { LPDIRECT3DDEVICE9 pd3dDevice = CGlobals::GetRenderDevice(); D3DFORMAT colorFormat = D3DFMT_A8R8G8B8; LPDIRECT3DTEXTURE9 pTextureDest = NULL; LPDIRECT3DSURFACE9 pSurDest = NULL; if(FAILED(pd3dDevice->CreateTexture((int)nImageSize, (int)nImageSize, 1, D3DUSAGE_RENDERTARGET, colorFormat, D3DPOOL_DEFAULT, &pTextureDest , NULL))) { SAFE_RELEASE(pSur); return; } if(FAILED(pTextureDest->GetSurfaceLevel(0, &pSurDest))) { SAFE_RELEASE(pTextureDest); SAFE_RELEASE(pSur); return; } // Copy scene to lower resolution render target texture if( SUCCEEDED(pd3dDevice->StretchRect( pSur, NULL, pSurDest, NULL, D3DTEXF_LINEAR )) ) { if(SUCCEEDED(D3DXSaveSurfaceToFile(sFile.c_str(), FileFormat, pSurDest, NULL,NULL ))) { OUTPUT_LOG("canvas portrait %d taken for %s",nImageSize, sFile.c_str()); } } SAFE_RELEASE(pSur); SAFE_RELEASE(pSurDest); SAFE_RELEASE(pTextureDest); } } } }
bool DirectXTextureManager::loadTileSetFromTexture( Game *game, wstring dir, wstring sourceImageFileName, int tileWidth, int tileHeight, int spacing, int margin) { // CONVERT THE FILE NAME INTO A WINDOW LONG CHAR wchar_t (LPCWSTR) wstring sourcePath = dir + sourceImageFileName; LPDIRECT3DTEXTURE9 textureToDivide; LPDIRECT3DSURFACE9 surfaceToDivide; unsigned int result = fillTexture(sourcePath, &textureToDivide); textureToDivide->GetSurfaceLevel(0, &surfaceToDivide); if (result != S_OK) return false; // DETERMINE THE NUMBER OF TILE ROWS AND COLUMNS D3DSURFACE_DESC surfaceDesc; surfaceToDivide->GetDesc(&surfaceDesc); int textureWidth = surfaceDesc.Width; int textureHeight = surfaceDesc.Height; int columns = (textureWidth-margin)/(tileWidth+spacing); int rows = (textureHeight-margin)/(tileHeight+spacing); DirectXGraphics *dxg = (DirectXGraphics*)graphics; LPDIRECT3DDEVICE9 graphicsDevice = ((DirectXGraphics*)graphics)->getGraphicsDevice(); // THE TILE SET IMAGE LOADED SUCCESSFULLY, SO LET'S CUT IT UP for (int row = 0; row < rows; row++) { for (int column = 0; column < columns; column++) { LPDIRECT3DTEXTURE9 extractedTexture; LPDIRECT3DSURFACE9 extractedSurface; result = graphicsDevice->CreateRenderTarget(tileWidth, tileHeight, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, false, &extractedSurface, NULL); if (result != S_OK) return false; RECT sourceRect; sourceRect.left = (column * (tileWidth + spacing)) + margin; sourceRect.right = tileWidth + (sourceRect.left) - 1; sourceRect.top = (row * (tileHeight + spacing)) + margin; sourceRect.bottom = tileHeight + (sourceRect.top) - 1; graphicsDevice->StretchRect(surfaceToDivide, &sourceRect, extractedSurface, NULL, D3DTEXF_NONE); // BUILD A UNIQUE FILE NAME FOR THIS TEXTURE wstring textureFilename = sourceImageFileName; unsigned int id = wstringTable.getNumWStringsInTable(); wchar_t dot = '.'; int dotIndex = textureFilename.rfind(dot); textureFilename = textureFilename.substr(0, dotIndex); wstringstream idWss; idWss << id; wstring idText; idWss >> idText; textureFilename = textureFilename + idText + L".png"; textureFilename = wstring(dir.begin(), dir.end()) + textureFilename; // LET'S PUT THE SURFACE IN AN IMAGE FILE D3DXSaveSurfaceToFileW(textureFilename.c_str(), D3DXIFF_PNG, extractedSurface, NULL, NULL); D3DXIMAGE_INFO info; HRESULT result = D3DXGetImageInfoFromFile(textureFilename.c_str(), &info); if (result != S_OK) return false; // AND THEN LOAD IT BACK IN AS A TEXTURE result = D3DXCreateTextureFromFileEx( graphicsDevice, // GPU textureFilename.c_str(), // BITMAP FILE PATH/NAME tileWidth, // BITMAP IMAGE WIDTH tileHeight, // BITMAP IMAGE HEIGHT 1, // MIP-MAP LEVELS (1 FOR NO CHAIN) D3DPOOL_DEFAULT, // THE TYPE OF SURFACE (STANDARD) D3DFMT_UNKNOWN, // SURFACE FORMAT (DEFAULT) D3DPOOL_DEFAULT, // MEMORY CLASS FOR THE TEXTURE D3DX_DEFAULT, // IMAGE FILTER D3DX_DEFAULT, // MIP FILTER NULL, // COLOR KEY &info, // BITMAP FILE INFO NULL, // COLOR PALETTE &extractedTexture ); // THE TEXTURE WE ARE CREATING AND LOADING if (result != S_OK) return false; // ADD IT TO THE STRING TABLE wstringTable.putWStringInTable(textureFilename); // AND ADD IT TO THE TEXTURES textures[textureFilename] = extractedTexture; } } return true; }
/*=========================================================== Render To Texture ===========================================================*/ bool RendrToTexture(mytex* &tex,D3DPOOL pool,int &x_delta,int &y_delta,int nowx,int nowy,imgbase *img) { bool rlt = true; LPDIRECT3DTEXTURE9 pRenderTexture = NULL; // 目标纹理 LPDIRECT3DSURFACE9 pRenderSurface = NULL,pBackBuffer = NULL; // pRenderSurface是pRenderTexture 对应的Surface // pBackBuffer用于保存原来的Render Target //注意这里的第三个参数必须为D3DUSAGE_RENDERTARGET //第四个参数决定纹理的格式,不同的场景会要求不同的格式 g_pd3dD->CreateTexture(drect.right,drect.bottom,1,D3DUSAGE_RENDERTARGET,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&pRenderTexture,NULL); //获得pRenderTexture对应的Surface pRenderTexture->GetSurfaceLevel(0,&pRenderSurface); //这里保存下原来的Render target,在做完RTT后再恢复 g_pd3dD->GetRenderTarget(0,&pBackBuffer); if( SUCCEEDED( g_pd3dD->BeginScene() ) ) { //设置我们的纹理为render target g_pd3dD->SetRenderTarget(0, pRenderSurface); g_pd3dD->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DXCOLOR(0.0f,0.00f,0.00f,1.00f), 1.0f, 0); //绘制tex img->rtt_draw_func(); //重新将render target设置为帧缓存 g_pd3dD->SetRenderTarget(0, pBackBuffer); g_pd3dD->EndScene(); pBackBuffer->Release(); } else { SAFE_RELEASE(pRenderSurface); SAFE_RELEASE(pRenderTexture); return false; } //获取rendertarget内的值 LPDIRECT3DTEXTURE9 RenderTarget_Tex; LPDIRECT3DSURFACE9 RenderTarget_Surface; g_pd3dD->CreateTexture(drect.right,drect.bottom,1,0,D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &RenderTarget_Tex, NULL); RenderTarget_Tex->GetSurfaceLevel(0,&RenderTarget_Surface); if (g_pd3dD->GetRenderTargetData(pRenderSurface, RenderTarget_Surface) == D3D_OK) { D3DLOCKED_RECT lockbits; if (RenderTarget_Tex->LockRect(0,&lockbits, NULL, 0) == D3D_OK) { BYTE* bits=(BYTE*)(lockbits.pBits); int line_Offset = lockbits.Pitch; //每行字节数 BYTE* bits_head = bits; int left = 0x7fffffff , right = -1, top = 0x7fffffff, bottom = -1; for( int y=0; y<drect.bottom; y++ ) { for( int x=0; x<drect.right; x++ ) { if(bits[3]!=0) //如果alpha不为0 { if(x<left) left=x; if(x>right) right=x; if(y<top) top=y; if(y>bottom) bottom=y; } bits += 4; } } bits = bits_head; int dwidth = right-left ,dheight = bottom-top; int bytenum = dwidth*dheight*4; BYTE* dest_bits = new BYTE[bytenum]; BYTE* dest_head = dest_bits; //定义初始pos bits += top*line_Offset + left*4; //复制目标块 for( int y=0; y<dheight; y++ ) { for( int x=0; x<dwidth; x++ ) { dest_bits[0] = bits[0]; dest_bits[1] = bits[1]; dest_bits[2] = bits[2]; dest_bits[3] = bits[3]; bits += 4; dest_bits +=4; } bits += line_Offset - dwidth*4; } RenderTarget_Tex->UnlockRect(0); D3DLOCKED_RECT lockmapbits; if (g_pd3dD->CreateTexture(dwidth, dheight, 1, 0, D3DFMT_A8R8G8B8, pool, &(tex->tex), NULL) == D3D_OK) { tex->tex->LockRect(0, &lockmapbits, NULL, 0); //直接复制内存块 CopyMemory(lockmapbits.pBits,dest_head,bytenum); tex->tex->UnlockRect(0); } else {rlt = false;} //rendertarget的宽高以及相对于draw之前的偏移量 tex->width = dwidth; tex->height = dheight; x_delta = left - nowx; y_delta = top - nowy; } else {rlt = false;} } else {rlt = false;} /*/保存纹理到图片 if(FAILED(D3DXSaveTextureToFileW(L"rt.png",D3DXIFF_PNG,tex->tex,0))) RenderTarget_Tex = 0;//*/ SAFE_RELEASE(RenderTarget_Tex); SAFE_RELEASE(RenderTarget_Surface); SAFE_RELEASE(pRenderSurface); SAFE_RELEASE(pRenderTexture); return rlt; }
void RenderWithIrregularPCF( const D3DXMATRIX& viewproj, const D3DXVECTOR3& eye, const D3DXMATRIX& lightview, const D3DXMATRIX& lightproj, const D3DXVECTOR4& lightpos, const D3DXVECTOR4& clipplanes, const D3DXVECTOR4& texelsize) { LPDIRECT3DSURFACE9 oldsurface = NULL; LPDIRECT3DSURFACE9 shadowsurface = NULL; D3DXVECTOR4 noisesize(16.0f, 16.0f, 0, 1); // STEP 1: render shadow map shadowmap->GetSurfaceLevel(0, &shadowsurface); device->GetRenderTarget(0, &oldsurface); device->SetRenderTarget(0, shadowsurface); device->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0); //device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); shadowsurface->Release(); pcfirreg->SetTechnique("shadowmap"); pcfirreg->SetMatrix("lightView", &lightview); pcfirreg->SetMatrix("lightProj", &lightproj); pcfirreg->SetVector("clipPlanes", &clipplanes); pcfirreg->Begin(NULL, 0); pcfirreg->BeginPass(0); { RenderScene(pcfirreg, 1); // caster RenderScene(pcfirreg, 3); // caster & receiver } pcfirreg->EndPass(); pcfirreg->End(); // STEP 2: render scene //device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); device->SetRenderTarget(0, oldsurface); device->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0xff6694ed, 1.0f, 0); device->SetRenderState(D3DRS_SRGBWRITEENABLE, TRUE); oldsurface->Release(); device->SetTexture(1, shadowmap); device->SetTexture(2, noise); pcfirreg->SetTechnique("irregular_light"); //pcfirreg->SetTechnique("irregular_screen"); pcfirreg->SetMatrix("matViewProj", &viewproj); pcfirreg->SetMatrix("lightView", &lightview); pcfirreg->SetMatrix("lightProj", &lightproj); pcfirreg->SetVector("clipPlanes", &clipplanes); pcfirreg->SetVector("lightPos", &lightpos); pcfirreg->SetVector("eyePos", (D3DXVECTOR4*)&eye); pcfirreg->SetVector("texelSize", &texelsize); pcfirreg->SetVector("noiseSize", &noisesize); pcfirreg->Begin(NULL, 0); pcfirreg->BeginPass(0); { RenderScene(pcfirreg, 2); // receiver RenderScene(pcfirreg, 3); // caster & receiver } pcfirreg->EndPass(); pcfirreg->End(); device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); }
bool DirectXTextureManager::loadTileSetFromTexture(Game *game, wstring dir, wstring sourceImageFileName, int tileWidth, int tileHeight) { // CONVERT THE FILE NAME INTO A WINDOW LONG CHAR wchar_t (LPCWSTR) wstring sourcePath = dir + sourceImageFileName; LPDIRECT3DTEXTURE9 textureToDivide; LPDIRECT3DSURFACE9 surfaceToDivide; //DXLoad //D3DXLoadSurfaceFromMemory() unsigned int result = fillTexture(sourcePath, &textureToDivide); textureToDivide->GetSurfaceLevel(0, &surfaceToDivide);//~15 seconds if (result != S_OK) return false; // DETERMINE THE NUMBER OF TILE ROWS AND COLUMNS D3DSURFACE_DESC surfaceDesc; surfaceToDivide->GetDesc(&surfaceDesc); int textureWidth = surfaceDesc.Width; int textureHeight = surfaceDesc.Height; int columns = textureWidth / tileWidth; int rows = textureHeight / tileHeight; DirectXGraphics *dxg = (DirectXGraphics*)graphics; LPDIRECT3DDEVICE9 graphicsDevice = ((DirectXGraphics*)graphics)->getGraphicsDevice(); // THE TILE SET IMAGE LOADED SUCCESSFULLY, SO LET'S CUT IT UP // MAYBE IF IM FEELING CRAZY LATER ILL MULTI THREAD THIS for (int row = 0; row < rows; row++) { for (int column = 0; column < columns; column++) { LPDIRECT3DTEXTURE9 extractedTexture; LPDIRECT3DSURFACE9 extractedSurface; result = graphicsDevice->CreateRenderTarget(tileWidth, tileHeight, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, false, &extractedSurface, NULL); if (result != S_OK) return false; RECT sourceRect; sourceRect.left = column * tileWidth; sourceRect.right = tileWidth + (column * tileWidth) - 1; sourceRect.top = row * tileHeight; sourceRect.bottom = tileHeight + (row * tileHeight) - 1; graphicsDevice->StretchRect(surfaceToDivide, &sourceRect, extractedSurface, NULL, D3DTEXF_NONE); // BUILD A UNIQUE FILE NAME FOR THIS TEXTURE wstring textureFilename = sourceImageFileName; unsigned int id = wstringTable.getNumWStringsInTable(); wchar_t dot = '.'; int dotIndex = textureFilename.rfind(dot); textureFilename = textureFilename.substr(0, dotIndex); wstringstream idWss; idWss << id; wstring idText; idWss >> idText; textureFilename = textureFilename + idText + L".png"; textureFilename = wstring(dir.begin(), dir.end()) + textureFilename; //D3DXCreateTextureFromFile() //D3DxCreateTexture HRESULT result = D3DXCreateTexture(graphicsDevice, tileWidth, tileHeight, 1, D3DPOOL_DEFAULT, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, &extractedTexture); if (result != S_OK) return false; LPDIRECT3DSURFACE9 t; extractedTexture->GetSurfaceLevel(0, &t); D3DXLoadSurfaceFromSurface(t, NULL, NULL, extractedSurface, NULL, NULL, D3DX_FILTER_NONE, 0); // ADD IT TO THE STRING TABLE wstringTable.putWStringInTable(textureFilename); // AND ADD IT TO THE TEXTURES textures[textureFilename] = extractedTexture; extractedSurface->Release(); t->Release(); } } surfaceToDivide->Release(); textureToDivide->Release(); return true; }
// Draw a textured quad on the back-buffer bool CDirect3D::D3DSwapBuffers(void) { HRESULT hr; UINT uPasses; if (backbuffer_clear_countdown > 0) { backbuffer_clear_countdown--; pD3DDevice9->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); } #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW // If the SDL drawn menus are visible, copy the SDL surface to the Direct3D surface to keep them visible on-screen if (mainMenu.isVisible() && mainMenu.menuBox.h != 0 && dwY >= mainMenu.menuBox.h) UpdateRectFromSDLSurface(0, 0, mainMenu.menuBox.w, mainMenu.menuBox.h); #endif // begin rendering pD3DDevice9->BeginScene(); #if C_D3DSHADERS /* PS 2.0 path */ if(psActive) { if(preProcess) { // Set preprocess matrices if(FAILED(psEffect->SetMatrices(m_matPreProj, m_matPreView, m_matPreWorld))) { LOG_MSG("D3D:Set matrices failed."); return false; } // Save render target LPDIRECT3DSURFACE9 lpRenderTarget; pD3DDevice9->GetRenderTarget(0, &lpRenderTarget); LPDIRECT3DTEXTURE9 lpWorkTexture = lpWorkTexture1; pass2: // Change the render target LPDIRECT3DSURFACE9 lpNewRenderTarget; lpWorkTexture->GetSurfaceLevel(0, &lpNewRenderTarget); if(FAILED(pD3DDevice9->SetRenderTarget(0, lpNewRenderTarget))) { LOG_MSG("D3D:Failed to set render target"); return false; } SAFE_RELEASE(lpNewRenderTarget); uPasses = 0; if(FAILED(psEffect->Begin((lpWorkTexture==lpWorkTexture1) ? (ScalingEffect::Preprocess1):(ScalingEffect::Preprocess2), &uPasses))) { LOG_MSG("D3D:Failed to begin PS"); return false; } for(UINT uPass=0;uPass<uPasses;uPass++) { hr=psEffect->BeginPass(uPass); if(FAILED(hr)) { LOG_MSG("D3D:Failed to begin pass %d", uPass); return false; } // Render the vertex buffer contents pD3DDevice9->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2); psEffect->EndPass(); } if(FAILED(psEffect->End())) { LOG_MSG("D3D:Failed to end effect"); return false; } #if DEBUG_PS // Save rendertarget data LPDIRECT3DSURFACE9 lpTexRenderTarget; lpWorkTexture->GetSurfaceLevel(0, &lpTexRenderTarget); lpDebugTexture->GetSurfaceLevel(0, &lpNewRenderTarget); if(FAILED(hr=pD3DDevice9->GetRenderTargetData(lpTexRenderTarget, lpNewRenderTarget))) { LOG_MSG("D3D:Unable to get render target data: 0x%x", hr); SAFE_RELEASE(lpTexRenderTarget); SAFE_RELEASE(lpNewRenderTarget); } else { SAFE_RELEASE(lpTexRenderTarget); SAFE_RELEASE(lpNewRenderTarget); LOG_MSG("D3D:Got render target data, writing debug file (%dx%d)", dwTexWidth, dwTexHeight); if(lpDebugTexture->LockRect(0, &d3dlr, NULL, D3DLOCK_READONLY) == D3D_OK) { FILE * debug = fopen(((lpWorkTexture==lpWorkTexture1)?"pass1.raw":"pass2.raw"), "wb"); if(debug == NULL) { LOG_MSG("D3D:Unable to create file!"); } else { for(int i = 0; i < dwTexHeight; i++) { Bit8u * ptr = (Bit8u*)d3dlr.pBits; for(int j = 0; j < dwTexWidth; j++) { fwrite(ptr, 3, sizeof(char), debug); ptr += 4; } d3dlr.pBits = (Bit8u*)d3dlr.pBits + d3dlr.Pitch; } fclose(debug); } lpDebugTexture->UnlockRect(0); } d3dlr.pBits = NULL; } #endif if((psEffect->hasPreprocess2()) && (lpWorkTexture == lpWorkTexture1)) { lpWorkTexture = lpWorkTexture2; goto pass2; } // Reset the rendertarget pD3DDevice9->SetRenderTarget(0, lpRenderTarget); SAFE_RELEASE(lpRenderTarget); // Set matrices for final pass if(FAILED(psEffect->SetMatrices(m_matProj, m_matView, m_matWorld))) { LOG_MSG("D3D:Set matrices failed."); return false; } } uPasses = 0; if(FAILED(psEffect->Begin(ScalingEffect::Combine, &uPasses))) { LOG_MSG("D3D:Failed to begin PS"); return false; } for(UINT uPass=0;uPass<uPasses;uPass++) { hr=psEffect->BeginPass(uPass); if(FAILED(hr)) { LOG_MSG("D3D:Failed to begin pass %d", uPass); return false; } // Render the vertex buffer contents pD3DDevice9->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); psEffect->EndPass(); } if(FAILED(psEffect->End())) { LOG_MSG("D3D:Failed to end effect"); return false; } } else #endif { // Normal path pD3DDevice9->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); } // end rendering pD3DDevice9->EndScene(); if(GCC_UNLIKELY(hr=pD3DDevice9->Present(NULL, NULL, NULL, NULL)) != D3D_OK) { switch(hr) { case D3DERR_DEVICELOST: LOG_MSG("D3D:Driver device lost"); if (!deviceLost) { deviceLost = true; void RENDER_CallBack(GFX_CallBackFunctions_t f); RENDER_CallBack(GFX_CallBackRedraw); } return false; break; case D3DERR_DRIVERINTERNALERROR: LOG_MSG("D3D:Driver internal error"); return false; break; case D3DERR_INVALIDCALL: default: LOG_MSG("D3D:Invalid call"); return false; break; } } return true; }
// Should be scale free. void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture) { u8* srcAddr = Memory::GetPointer(xfbAddr); if (!srcAddr) { WARN_LOG(VIDEO, "Tried to decode from invalid memory address"); return; } int srcFmtWidth = srcWidth / 2; XFBReadBuffer &ReadBuffer = XReadBuffers[xfreadBuffers]; if (ReadBuffer.Width != srcFmtWidth || ReadBuffer.Height != srcHeight) { ReadBuffer.Release(); ReadBuffer.Width = srcFmtWidth; ReadBuffer.Height = srcHeight; ReadBuffer.XFBMEMTexture = D3D::CreateTexture2D(srcFmtWidth, srcHeight, D3DFMT_A8R8G8B8, 1, D3DPOOL_SYSTEMMEM); ReadBuffer.XFBTexture = D3D::CreateTexture2D(srcFmtWidth, srcHeight, D3DFMT_A8R8G8B8); ReadBuffer.XFBMEMTexture->GetSurfaceLevel(0, &ReadBuffer.ReadSurface); ReadBuffer.XFBTexture->GetSurfaceLevel(0, &ReadBuffer.WriteSurface); } D3D::ReplaceTexture2D(ReadBuffer.XFBMEMTexture, srcAddr, srcFmtWidth, srcHeight, srcFmtWidth, D3DFMT_A8R8G8B8, false); RECT srcr{ 0, 0, srcFmtWidth, srcHeight }; POINT dstp{ 0, 0 }; D3D::dev->UpdateSurface(ReadBuffer.ReadSurface, &srcr, ReadBuffer.WriteSurface, &dstp); g_renderer->ResetAPIState(); // reset any game specific settings LPDIRECT3DSURFACE9 Rendersurf = nullptr; destTexture->GetSurfaceLevel(0,&Rendersurf); D3D::dev->SetDepthStencilSurface(nullptr); D3D::dev->SetRenderTarget(0, Rendersurf); D3DVIEWPORT9 vp; // Stretch picture with increased internal resolution vp.X = 0; vp.Y = 0; vp.Width = srcWidth; vp.Height = srcHeight; vp.MinZ = 0.0f; vp.MaxZ = 1.0f; D3D::dev->SetViewport(&vp); RECT destrect; destrect.bottom = srcHeight; destrect.left = 0; destrect.right = srcWidth; destrect.top = 0; RECT sourcerect; sourcerect.bottom = srcHeight; sourcerect.left = 0; sourcerect.right = srcFmtWidth; sourcerect.top = 0; D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); TextureConversionShaderLegacy::SetShaderParameters( (float)srcFmtWidth, (float)srcHeight, 0.0f, 0.0f, 1.0f, 1.0f, (float)srcFmtWidth, (float)srcHeight); D3D::dev->SetPixelShaderConstantF(C_COLORMATRIX, PixelShaderManager::GetBuffer(), 2); D3D::drawShadedTexQuad( ReadBuffer.XFBTexture, &sourcerect, 1, 1, srcWidth, srcHeight, s_yuyvToRgbProgram, VertexShaderCache::GetSimpleVertexShader(0)); D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER); D3D::SetTexture(0,nullptr); D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); g_renderer->RestoreAPIState(); Rendersurf->Release(); xfreadBuffers = (xfreadBuffers + 1) % NUM_XFBREAD_BUFFER; }
/* Renders all tiles and sprites. Note that these objects can be rotated. */ void DirectXGraphics::renderWorldRenderList() { worldRenderList->resetIterator(); RenderItem itemToRender; LPDIRECT3DTEXTURE9 texture; RECT *rect = NULL; GameGUI *gui = game->getGUI(); Viewport *viewport = gui->getViewport(); // GO THROUGH EACH ITEM IN THE LIST while (worldRenderList->hasNext()) { float translationX; float translationY; if (rect != NULL) delete rect; rect = NULL; itemToRender = worldRenderList->next(); // LET'S GET THE TEXTURE WE WANT TO RENDER int id = itemToRender.id; if (id >= 0) { texture = ((DirectXTextureManager*)worldTextureManager)->getTexture(id); D3DXVECTOR3 position = D3DXVECTOR3( (FLOAT)(itemToRender.x), (FLOAT)(itemToRender.y), 0); position.x += viewport->getViewportOffsetX(); position.y += viewport->getViewportOffsetY(); // ADJUST FOR THE GUI OFFSET if ((position.x < viewport->getViewportOffsetX()) || (position.y < viewport->getViewportOffsetY())) { IDirect3DSurface9 *surface; UINT level = 0; HRESULT result = texture->GetSurfaceLevel(level, &surface); D3DSURFACE_DESC surfaceDescription; surface->GetDesc(&surfaceDescription); rect = new RECT(); rect->left = 0; rect->top = 0; rect->right = surfaceDescription.Width; rect->bottom = surfaceDescription.Height; if (position.x < viewport->getViewportOffsetX()) { int xDiff = viewport->getViewportOffsetX() - (int)position.x; rect->left = xDiff; position.x += xDiff; } if (position.y < viewport->getViewportOffsetY()) { int yDiff = viewport->getViewportOffsetY() - (int)position.y; rect->top = yDiff; position.y += yDiff; } } // LET'S PUT THE STANDARD ROTATION MATRIX ASIDE // FOR A SECOND. IT WILL BE USED FOR RENDERING THE // GUI, BUT WE'LL WANT A CUSTOM ONE FOR WORLD OBJECTS D3DXMATRIX defaultTransform; D3DXMatrixIdentity(&defaultTransform); // TO RENDER A PROPERLY ROTATED OBJECT TO THE WORLD, // FIRST WE NEED TO MOVE IT TO THE ORIGIN, CENTERED // ABOUT THE ORIGIN SO WE SET UP THIS MATRIX // TO DO THIS D3DXMATRIX translationToOrigin; D3DXMatrixIdentity(&translationToOrigin); translationToOrigin._41 = -(itemToRender.width/2); translationToOrigin._42 = -(itemToRender.height/2); // THEN WE NEED A MATRIX TO DO THE ROTATION D3DXMATRIX rotationAboutOrigin; D3DXMatrixIdentity(&rotationAboutOrigin); // THE PROBLEM ANGLES ARE 0, 90, 180, and 270 float cosTheta = cos(itemToRender.rotationInRadians); float sinTheta = sin(itemToRender.rotationInRadians); if (cosTheta != cosTheta) cosTheta = 0; if (sinTheta != sinTheta) sinTheta = 0; rotationAboutOrigin._11 = cosTheta; rotationAboutOrigin._21 = -sinTheta; rotationAboutOrigin._12 = sinTheta; rotationAboutOrigin._22 = cosTheta; // AND THEN WE NEED A MATRIX TO ROTATE THE OBJECT // TO THE LOCATION WE WANT IT RENDERED D3DXMATRIX translationBackToCenter; D3DXMatrixIdentity(&translationBackToCenter); translationBackToCenter._41 = ((position.x) + (itemToRender.width/2)); translationBackToCenter._42 = ((position.y) + (itemToRender.height/2)); // THE COMBINED MATRIX COMBINES THESE 3 OPERATIONS // INTO A SINGLE MATRIX D3DXMATRIX combinedMatrix = translationToOrigin; combinedMatrix *= rotationAboutOrigin; combinedMatrix *= translationBackToCenter; // NOW LET'S USE THE COMBINED MATRIX TO POSITION AND ROTATE THE ITEM spriteHandler->SetTransform(&combinedMatrix); // RENDER THE OPAQUE ITEMS if (itemToRender.a == 255) { if (FAILED(spriteHandler->Draw( texture, rect, NULL, NULL, DEFAULT_ALPHA_COLOR))) { game->getText()->writeDebugOutput("\nspriteHandler->Draw: FAILED"); } // RENDER THE ITEMS WITH CUSTOM TRANSPARENCY else { if (itemToRender.a < 0) itemToRender.a = 0; else if (itemToRender.a > 255) itemToRender.a = 255; if (FAILED(spriteHandler->Draw( texture, rect, NULL, NULL, D3DCOLOR_ARGB(itemToRender.a, 255, 255, 255)))) { game->getText()->writeDebugOutput("\nspriteHandler->Draw: FAILED"); } } } } } // NOW EMPTY THE LIST, WE'RE ALL DONE WITH IT worldRenderList->clear(); if (rect != NULL) delete rect; // AND RESTORE THE MATRIX USED FOR RENDERING THE GUI D3DXMATRIX identityMatrix; D3DXMatrixIdentity(&identityMatrix); spriteHandler->SetTransform(&identityMatrix); }
// 使用DirectX 9來繪圖 void RenderFrameDX9(void) { LPDIRECT3DDEVICE9 device = GutGetGraphicsDeviceDX9(); LPDIRECT3DTEXTURE9 pBlurredTexture = NULL; Matrix4x4 light_projection_matrix; Matrix4x4 light_view_matrix; Matrix4x4 view_matrix = g_Control.GetViewMatrix(); Matrix4x4 world_matrix = g_Control.GetObjectMatrix(); // 開始下繪圖指令 device->BeginScene(); { // 保存主framebuffer LPDIRECT3DSURFACE9 pFrameBufferBackup, pDepthBufferBackup; device->GetRenderTarget(0, &pFrameBufferBackup); pFrameBufferBackup->Release(); device->GetDepthStencilSurface(&pDepthBufferBackup); pDepthBufferBackup->Release(); // 取出動態貼圖中的surface LPDIRECT3DSURFACE9 pSurface; g_pTexture->GetSurfaceLevel(0, &pSurface); // 把繪圖結果輸出到動態貼圖中 device->SetRenderTarget(0, pSurface); device->SetDepthStencilSurface(g_pDepthStencil); // 清除畫面 device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(255, 255, 255, 255), 1.0f, 0); // 設定光源位置 Vector4 vLightPos = g_Light.m_Position; Vector4 vLightUp(0.0f, 1.0f, 0.0f); Vector4 vLightLookat(0.0f, 0.0f, 0.0f); light_projection_matrix = GutMatrixPerspectiveRH_DirectX(60.0f, 1.0f, 0.1f, 100.0f); light_view_matrix = GutMatrixLookAtRH(vLightPos, vLightLookat, vLightUp); // 把鏡頭放到光源位置來畫陰影 device->SetTransform(D3DTS_PROJECTION, (D3DMATRIX *)&light_projection_matrix); device->SetTransform(D3DTS_VIEW, (D3DMATRIX *)&light_view_matrix); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *)&world_matrix); // 把所有反射關閉,讓模型在畫面上呈現黑色。 D3DCOLORVALUE zero = {0.0f, 0.0f, 0.0f, 1.0f}; sModelMaterial_DX9 material; material.m_Material.Ambient = zero; material.m_Material.Emissive = zero; material.m_Material.Diffuse = zero; material.m_Material.Specular = zero; material.m_bCullFace = false; material.Submit(); SetupLightingDX9(); // 畫出模型 g_Model_DX9.Render(0); // 告知direct3d9裝置rendertarget使用完畢 pSurface->Release(); // 還原主framebuffer device->SetRenderTarget(0, pFrameBufferBackup); device->SetDepthStencilSurface(pDepthBufferBackup); } // 把影子柔化 { pBlurredTexture = BlurTexture(g_pTexture); } // 把上一個步驟的結果當成貼圖來使用 { // 消除畫面 device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0, 0, 150, 255), 1.0f, 0); // 設定轉換矩陣 device->SetTransform(D3DTS_PROJECTION, (D3DMATRIX *) &g_projection_matrix); device->SetTransform(D3DTS_VIEW, (D3DMATRIX *) &view_matrix); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *) &world_matrix); // 設定光源 SetupLightingDX9(); device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); device->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); device->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); // 畫出茶壼 g_Model_DX9.Render(); sModelMaterial_DX9 material; material.m_pTextures[0] = pBlurredTexture; material.Submit(); // 計算貼圖矩陣 Matrix4x4 inv_view_matrix = g_Control.GetCameraMatrix(); Matrix4x4 uv_offset_matrix; uv_offset_matrix.Identity(); uv_offset_matrix.Scale(0.5f, -0.5f, 0.5f); uv_offset_matrix[3].Set(0.5f, 0.5f, 0.5f, 1.0f); Matrix4x4 texture_matrix = inv_view_matrix * light_view_matrix * light_projection_matrix * uv_offset_matrix; Matrix4x4 indent_matrix = Matrix4x4::IdentityMatrix(); // 設定轉換矩陣 device->SetTransform(D3DTS_TEXTURE0, (D3DMATRIX *) &texture_matrix); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *) &indent_matrix); // 開啟自動產生貼圖座標功能 device->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION); device->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4 | D3DTTFF_PROJECTED); device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); device->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); device->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); // 畫出地表 g_Terrain_DX9.Render(0); device->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); device->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); } // 宣告所有的繪圖指令都下完了 device->EndScene(); // 把背景backbuffer的畫面呈現出來 device->Present( NULL, NULL, NULL, NULL ); }