bool AlphaMap::init(bool pAlphaCheck, LPDIRECT3DTEXTURE9 pTexture) { d_solid = true; if (!pAlphaCheck) return false; D3DSURFACE_DESC surfaceDesc; pTexture->GetLevelDesc(0, &surfaceDesc); d_width = surfaceDesc.Width; d_height = surfaceDesc.Height; d_mask.resize(d_width * d_height); D3DLOCKED_RECT lockedRect; if (SUCCEEDED(pTexture->LockRect(0, &lockedRect, NULL, D3DLOCK_DISCARD))) { unsigned char* bits = (unsigned char*)lockedRect.pBits; for (int y = 0; y < d_height; ++y) { for (int x = 0; x < d_width; ++x) { bool solid = (bits[x * 4 + y * lockedRect.Pitch + 3] != 0); d_mask[x + y * d_width] = solid; if (!solid) d_solid = false; } } pTexture->UnlockRect(0); } return true; }
void GetSpriteSize(LPDIRECT3DTEXTURE9 pTex,int& width,int& height) { D3DSURFACE_DESC desc; pTex->GetLevelDesc(0,&desc); width=desc.Width; height=desc.Height; }
//------------------------------------------------------------------------------------------------- sdMemoryTexture::sdMemoryTexture(LPDIRECT3DTEXTURE9 spD3DTexture) { NIASSERT(spD3DTexture); // 获取渲染设备 NiDX9Renderer* spRenderer = NiDX9Renderer::GetRenderer(); NIASSERT(spRenderer); // 提取格式信息 D3DSURFACE_DESC kLevelDesc; spD3DTexture->GetLevelDesc(0, &kLevelDesc); m_uiWidth = kLevelDesc.Width; m_uiHeight = kLevelDesc.Height; m_uiLevel = spD3DTexture->GetLevelCount(); m_eFormat = kLevelDesc.Format; // m_spD3DTexture = spD3DTexture; m_spD3DTexture->AddRef(); // 创建GB纹理对象 m_spTexture = spRenderer->CreateNiTextureFromD3DTexture(m_spD3DTexture); NIASSERT(m_spTexture); }
void CImage::DrawSprite(LPD3DXSPRITE SpriteInterface, LPDIRECT3DTEXTURE9 TextureInterface, int PosX, int PosY, int Rotation, int Align) { if(SpriteInterface == NULL || TextureInterface == NULL) return; D3DXVECTOR3 Vec; Vec.x = (FLOAT)PosX; Vec.y = (FLOAT)PosY; Vec.z = (FLOAT)0.0f; D3DXMATRIX mat; D3DXVECTOR2 scaling(1.0f, 1.0f); D3DSURFACE_DESC desc; TextureInterface->GetLevelDesc(0, &desc); D3DXVECTOR2 spriteCentre; if(Align == 1) spriteCentre = D3DXVECTOR2((FLOAT)desc.Width / 2, (FLOAT)desc.Height / 2); else spriteCentre = D3DXVECTOR2(0, 0); D3DXVECTOR2 trans = D3DXVECTOR2(0, 0); D3DXMatrixTransformation2D(&mat, NULL, 0.0, &scaling, &spriteCentre, (FLOAT)Rotation, &trans); SpriteInterface->SetTransform(&mat); SpriteInterface->Begin(D3DXSPRITE_ALPHABLEND); SpriteInterface->Draw(TextureInterface, NULL, NULL, &Vec, 0xFFFFFFFF); SpriteInterface->End(); }
D3DFORMAT CDxtexDoc::GetFormat(LPDIRECT3DBASETEXTURE9 ptex) { LPDIRECT3DTEXTURE9 pmiptex = NULL; LPDIRECT3DCUBETEXTURE9 pcubetex = NULL; LPDIRECT3DVOLUMETEXTURE9 pvoltex = NULL; D3DFORMAT fmt = D3DFMT_UNKNOWN; if (IsVolumeMap()) pvoltex = (LPDIRECT3DVOLUMETEXTURE9)ptex; else if (IsCubeMap()) pcubetex = (LPDIRECT3DCUBETEXTURE9)ptex; else pmiptex = (LPDIRECT3DTEXTURE9)ptex; if (pvoltex != NULL) { D3DVOLUME_DESC vd; pvoltex->GetLevelDesc(0, &vd); fmt = vd.Format; } else if (pcubetex != NULL) { D3DSURFACE_DESC sd; pcubetex->GetLevelDesc(0, &sd); fmt = sd.Format; } else if( pmiptex != NULL ) { D3DSURFACE_DESC sd; pmiptex->GetLevelDesc(0, &sd); fmt = sd.Format; } return fmt; }
void OpticSprite::init(LPDIRECT3DTEXTURE9 texture) { texture->GetLevelDesc(0, &surfaceDesc); transformCentre = D3DXVECTOR2(surfaceDesc.Width * 0.5f, surfaceDesc.Height * 0.5f); translateCentre = D3DXVECTOR2(0.0f, 0.0f); this->texture = texture; this->spritesheet = false; this->texture = texture; this->lastTime = 0; }
//-------------------------------------------------------------------------------------- // CalculateResourceUsage( ) // // DESC: // Based on the known resources this function attempts to make an accurate // measurement of how much VRAM is being used by this part of the application. // // NOTES: // Whilst the return value should be pretty accurate, it shouldn't be relied // on due to the way drivers/hardware can allocate memory. // // Only the first level of the render target is checked as there should, by // definition, be no mip levels. // //-------------------------------------------------------------------------------------- DWORD CalculateResourceUsage() { DWORD usage = 0; D3DSURFACE_DESC d; if( SUCCEEDED( g_pBrightPassTex->GetLevelDesc( 0, &d ) ) ) usage += ( ( d.Width * d.Height ) * ( PostProcess::g_fmtHDR == D3DFMT_A32B32G32R32F ? 16 : 8 ) ); if( SUCCEEDED( g_pDownSampledTex->GetLevelDesc( 0, &d ) ) ) usage += ( ( d.Width * d.Height ) * ( PostProcess::g_fmtHDR == D3DFMT_A32B32G32R32F ? 16 : 8 ) ); if( SUCCEEDED( g_pBloomHorizontal->GetLevelDesc( 0, &d ) ) ) usage += ( ( d.Width * d.Height ) * ( PostProcess::g_fmtHDR == D3DFMT_A32B32G32R32F ? 16 : 8 ) ); if( SUCCEEDED( g_pBloomVertical->GetLevelDesc( 0, &d ) ) ) usage += ( ( d.Width * d.Height ) * ( PostProcess::g_fmtHDR == D3DFMT_A32B32G32R32F ? 16 : 8 ) ); return usage; }
//------------------------------------------------------------- // Name: InitDeviceObjects() // Desc: 디바이스가 생성된후의 초기화 // 프레임버퍼 포맷과 디바이스 종류가 변한뒤에 호출 // 여기서 확보한 메모리는 DeleteDeviceObjects()에서 해제 //------------------------------------------------------------- HRESULT CMyD3DApplication::InitDeviceObjects() { HRESULT hr; LPDIRECT3DTEXTURE9 pHeightTexture; D3DSURFACE_DESC desc; // 법선맵 생성 D3DUtil_CreateTexture( m_pd3dDevice,// 높이맵 읽기 _T("height.bmp"), &pHeightTexture ); pHeightTexture->GetLevelDesc(0,&desc);// 텍스처 정보 얻기 D3DXCreateTexture(m_pd3dDevice, desc.Width, desc.Height, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &m_pNormalMap);// 텍스처 생성 D3DXComputeNormalMap(m_pNormalMap, // 법선맵 생성 pHeightTexture, NULL, 0, D3DX_CHANNEL_RED, 1.0f); SAFE_RELEASE( pHeightTexture ); // 필요없어진 리소스 해제 // 정점선언 오브젝트 생성 if( FAILED( hr = m_pd3dDevice->CreateVertexDeclaration( decl, &m_pDecl ))) return DXTRACE_ERR ("CreateVertexDeclaration", hr); // 주전자 읽기 if(FAILED(hr=m_pMesh ->Create( m_pd3dDevice, _T("t-pot.x")))) return DXTRACE_ERR( "Load Object", hr ); // 지형 읽기 if(FAILED(hr=m_pMeshBg->Create( m_pd3dDevice, _T("map.x")))) return DXTRACE_ERR( "Load Ground", hr ); // 셰이더 읽기 LPD3DXBUFFER pErr=NULL; if( FAILED( hr = D3DXCreateEffectFromFile( m_pd3dDevice, "hlsl.fx", NULL, NULL, 0 , NULL, &m_pEffect, &pErr ))){ // 셰이더 읽기 실패 MessageBox( NULL, (LPCTSTR)pErr->GetBufferPointer() , "ERROR", MB_OK); }else{ m_hTechnique = m_pEffect->GetTechniqueByName( "TShader" ); m_hmWVP = m_pEffect->GetParameterByName( NULL, "mWVP" ); m_hvLightDir = m_pEffect->GetParameterByName( NULL, "vLightDir" ); m_hvColor = m_pEffect->GetParameterByName( NULL, "vColor" ); m_hvEyePos = m_pEffect->GetParameterByName( NULL, "vEyePos" ); m_htDecaleTex= m_pEffect->GetParameterByName( NULL, "DecaleTex" ); m_htNormalMap= m_pEffect->GetParameterByName( NULL, "NormalMap" ); } SAFE_RELEASE(pErr); // 폰트 m_pFont->InitDeviceObjects( m_pd3dDevice ); return S_OK; }
/**----------------------------------------------------------------------------- * 정점버퍼를 생성하고 정점값을 채워넣는다. * HeightMap정보도 여기서 초기화한다. *------------------------------------------------------------------------------ */ HRESULT InitVB() { D3DSURFACE_DESC ddsd; D3DLOCKED_RECT d3drc; g_pTexHeight->GetLevelDesc( 0, &ddsd ); // 텍스처의 정보 g_cxHeight = ddsd.Width; // 텍스처의 가로크기 g_czHeight = ddsd.Height; // 텍스처의 세로크기 g_pLog->Log( "Texture Size:[%d,%d]", g_cxHeight, g_czHeight ); g_pvHeightMap = new D3DXVECTOR3[g_cxHeight * g_czHeight]; // 높이맵배열 생성 if ( FAILED( g_pd3dDevice->CreateVertexBuffer( ddsd.Width*ddsd.Height*sizeof( CUSTOMVERTEX ), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) ) { return E_FAIL; } // 텍스처 메모리 락! g_pTexHeight->LockRect( 0, &d3drc, NULL, D3DLOCK_READONLY ); VOID* pVertices; // 정점버퍼 락! if ( FAILED( g_pVB->Lock( 0, g_cxHeight*g_czHeight*sizeof( CUSTOMVERTEX ), (void**)&pVertices, 0 ) ) ) { return E_FAIL; } CUSTOMVERTEX v; CUSTOMVERTEX* pV = (CUSTOMVERTEX*)pVertices; for ( DWORD z = 0; z < g_czHeight; z++ ) { for ( DWORD x = 0; x < g_cxHeight; x++ ) { v.p.x = (float)x - g_cxHeight / 2.0f; // 정점의 x좌표(메시를 원점에 정렬) v.p.z = -( (float)z - g_czHeight / 2.0f ); // 정점의 z좌표(메시를 원점에 정렬), z축이 모니터안쪽이므로 -를 곱한다. v.p.y = ( (float)( *( (LPDWORD)d3drc.pBits + x + z*( d3drc.Pitch / 4 ) ) & 0x000000ff ) ) / 10.0f; /// DWORD이므로 pitch/4 v.n.x = v.p.x; v.n.y = v.p.y; v.n.z = v.p.z; D3DXVec3Normalize( &v.n, &v.n ); v.t.x = (float)x / ( g_cxHeight - 1 ); v.t.y = (float)z / ( g_czHeight - 1 ); *pV++ = v; // 정점버퍼에 정점 저장 g_pvHeightMap[z * g_cxHeight + x] = v.p; // 높이맵에 정점 저장 } } g_pVB->Unlock(); g_pTexHeight->UnlockRect( 0 ); return S_OK; }
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; }
// Set Source texture HRESULT ScalingEffect::SetTextures(LPDIRECT3DTEXTURE9 lpSource, LPDIRECT3DTEXTURE9 lpWorking1, LPDIRECT3DTEXTURE9 lpWorking2, LPDIRECT3DVOLUMETEXTURE9 lpHq2xLookupTexture) { if(!m_SourceTextureEffectHandle) { m_strErrors += "Texture with SOURCETEXTURE semantic not found"; return E_FAIL; } HRESULT hr = m_pEffect->SetTexture(m_SourceTextureEffectHandle, lpSource); if(FAILED(hr)) { m_strErrors += "Unable to set SOURCETEXTURE"; return hr; } D3DXVECTOR4 fDims(256,256,1,1), fTexelSize(1,1,1,1); if(lpSource) { D3DSURFACE_DESC Desc; lpSource->GetLevelDesc(0, &Desc); fDims[0] = (FLOAT) Desc.Width; fDims[1] = (FLOAT) Desc.Height; } fTexelSize[0] = 1/fDims[0]; fTexelSize[1] = 1/fDims[1]; if(m_SourceDimsEffectHandle) { hr = m_pEffect->SetVector(m_SourceDimsEffectHandle, &fDims); if(FAILED(hr)) { m_strErrors += "Unable to set SOURCEDIMS"; return hr; } } if(m_TexelSizeEffectHandle) { hr = m_pEffect->SetVector(m_TexelSizeEffectHandle, &fTexelSize); if(FAILED(hr)) { m_strErrors += "Unable to set TEXELSIZE"; return hr; } } return hr; }
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"; }
// returns the index this texture is in class int CNumberToSprite::AddTexture(IDirect3DDevice9* pd3dDevice, LPCWSTR numberFileName) { HRESULT hr; LPDIRECT3DTEXTURE9 pTex; V( D3DXCreateTextureFromFile(pd3dDevice, numberFileName, &pTex) ); // get length D3DSURFACE_DESC desc; V( pTex->GetLevelDesc(0, &desc) ); m_vSpacing.push_back((float)desc.Width / m_nSYMBOLS); m_vpTex.push_back(pTex); return (int)(m_vpTex.size() - 1); }
//----[ begin ]-------------------------------------------------------------- bool PreviewImageDialog::begin(Evidyon::Tools::CompleteEditor* editor, Evidyon::Image::Tools::Image* image) { if (!image->loadD3DTexture(editor->getD3DDevice(), true)) return false; LPDIRECT3DTEXTURE9 texture = image->getD3DTexture(); texture->GetLevelDesc(0, &desc); editor_ = editor; image_ = image; dcx::dcxWin32DialogTemplate dialog; dialog.setStyleAsResizeableAppWindow(); dialog.setTitle("Image Preview"); BYTE buffer[256]; LPCDLGTEMPLATE dlg_template = dialog.compile(buffer, sizeof(buffer)); dialog_handle_ = createDialog(GetModuleHandle(NULL), dlg_template, editor->topWindow()); dcx::dcxWin32SetWindowClientSize(dialog_handle_, desc.Width, desc.Height); return editor->addD3DWindow(this); }
//************************************************************************************************************* 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(); }
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 ); } }
//----------------------------------------------------------------------------- // Name: create // Desc: //----------------------------------------------------------------------------- bool GUIFont::create(LPDIRECT3DTEXTURE9 fontTexture, DWORD letterWidth, DWORD letterHeight, const DWORD characterIndices[128-32], float lineSpacingFactor, DWORD characterSpacing) { destroy(); if (!fontTexture || !characterIndices) return false; (myTexture = fontTexture)->AddRef(); // Store the texture internally D3DSURFACE_DESC desc; fontTexture->GetLevelDesc(0, &desc); myTexWidth = desc.Width; myTexHeight = desc.Height; myTextScale = 1.0f; myLineHeightInPixels = lineSpacingFactor * letterHeight; mySpacing = characterSpacing; int charactersWide = myTexWidth / letterWidth; int lastCharacterRowIndex = myTexHeight / letterHeight - 1; float x_pixel_to_texcoord = 1.0f / desc.Width; float y_pixel_to_texcoord = 1.0f / desc.Height; for (int character = 32; character < 128; ++character) { DWORD index = characterIndices[character-32]; int characterX = index % charactersWide; int characterY = index / charactersWide; if (characterY > lastCharacterRowIndex) lastCharacterRowIndex; int x = (characterX * letterWidth); int y = (characterY * letterHeight); myTexCoords[character-32][0] = x_pixel_to_texcoord * (float)(x); myTexCoords[character-32][1] = y_pixel_to_texcoord * (float)(y); myTexCoords[character-32][2] = x_pixel_to_texcoord * (float)(x + letterWidth); myTexCoords[character-32][3] = y_pixel_to_texcoord * (float)(y + letterHeight); } return true; }
static void copy_texture_bits( LPTEXTURE srcT, LPTEXTURE dstT ) { HRESULT hr; D3DLOCKED_RECT srcRect; D3DLOCKED_RECT dstRect; unsigned int y, x; BYTE* srcBits; BYTE* dstBits; D3DSURFACE_DESC srcDesc; LPDIRECT3DTEXTURE9 srcTexture = (LPDIRECT3DTEXTURE9) srcT; LPDIRECT3DTEXTURE9 dstTexture = (LPDIRECT3DTEXTURE9) dstT; srcTexture->GetLevelDesc(0,&srcDesc); hr = srcTexture->LockRect(0,&srcRect,NULL,D3DLOCK_READONLY); if(FAILED(hr)) return; hr = dstTexture->LockRect(0,&dstRect,NULL,D3DLOCK_DISCARD); if(FAILED(hr)) return; srcBits = (BYTE*)srcRect.pBits; dstBits = (BYTE*)dstRect.pBits; for (y = 0; y < srcDesc.Height; y++) { for (x = 0; x < srcDesc.Width; x++) { // move to the correct off set in the table // pitch is the width of a row // (x*size) is the length of each pixel data DWORD srcIndex = (x*4)+(y*srcRect.Pitch); DWORD dstIndex = (x*4)+(y*dstRect.Pitch); // D3DFMT_A8R8G8B8 data will be accessible backwards: bgra dstBits[dstIndex] = (BYTE)gamma_table[srcBits[srcIndex]]; // Blue dstBits[dstIndex+1] = (BYTE)gamma_table[srcBits[srcIndex+1]]; // Green dstBits[dstIndex+2] = (BYTE)gamma_table[srcBits[srcIndex+2]]; // Red dstBits[dstIndex+3] = (BYTE)gamma_table[srcBits[srcIndex+3]]; // Alpha } } dstTexture->UnlockRect(0); srcTexture->UnlockRect(0); }
void WaterEffect::UpdateTexture( Real FrameTime, Screen3D& Screen ) { //Disperse the water /*for(int y=1; y<WATERDIM-1; y++) { for(int x=1; x<WATERDIM-1; x++) { if(NewWater[x+y*WATERDIM] == -1) continue; NewWater[x+y * WATERDIM] = ((OldWater[x+ ((y-1)*WATERDIM)] + OldWater[x+ ((y+1)*WATERDIM)] + OldWater[(x+1)+ (y*WATERDIM)] + OldWater[(x-1)+ (y*WATERDIM)] )*.5f) - NewWater[x+y * WATERDIM]; NewWater[x+y * WATERDIM] -= (NewWater[x+y * WATERDIM]*0.0625) ; if(NewWater[x+y * WATERDIM] < 0) NewWater[x+y * WATERDIM] =0; if(NewWater[x+y * WATERDIM] > 250) NewWater[x+y * WATERDIM] = 250; } }*/ for(int i=0; i<GRID_DIM*GRID_DIM; i++) { if(JumpTable[i]) { for(int y=JumpTable[i]->StartY; y<JumpTable[i]->EndY; y++) { for(int x=JumpTable[i]->StartX; x<JumpTable[i]->EndX; x++) { if(NewWater[x+y*WATERDIM] == -1) continue; NewWater[x+y * WATERDIM] = ((OldWater[x+ ((y-1)*WATERDIM)] + OldWater[x+ ((y+1)*WATERDIM)] + OldWater[(x+1)+ (y*WATERDIM)] + OldWater[(x-1)+ (y*WATERDIM)] )*.5f) - NewWater[x+y * WATERDIM]; NewWater[x+y * WATERDIM] -= (NewWater[x+y * WATERDIM]*0.0625) * FrameTime; if(NewWater[x+y * WATERDIM] < 0) NewWater[x+y * WATERDIM] =0; if(NewWater[x+y * WATERDIM] > 250) NewWater[x+y * WATERDIM] = 250; } } } } //Update the texture LPDIRECT3DTEXTURE9 TextureSurface; D3DSURFACE_DESC SurfDesc; D3DLOCKED_RECT LockedArea; BYTE* Surface; Texture* T = Screen.TM.GetTexture(RippleTexture); TextureSurface = T->GetTextureSurface(); //Figure out how many "levels" (mip-maps) there are //in the texture int nLevels = TextureSurface->GetLevelCount(); TextureSurface->GetLevelDesc(0, &SurfDesc); Real DivFactor=1; //loop through each level for(int l=0; l<nLevels; l++) { //Get the surface's attributes TextureSurface->GetLevelDesc(l, &SurfDesc); //lock down a pointer TextureSurface->LockRect(l, &LockedArea, NULL, NULL); //draw the pixel to the surface Surface = (BYTE*)LockedArea.pBits; if(SurfDesc.Format == D3DFMT_A8R8G8B8) { for(int y=0; y<WATERDIM/DivFactor; y++) { for(int x=0; x<WATERDIM/DivFactor; x++) { int rx=x*DivFactor; int ry=y*DivFactor; Surface[(x*4)+0+y*(SurfDesc.Width*4)] = 128+NewWater[rx+ry * WATERDIM]; Surface[(x*4)+1+y*(SurfDesc.Width*4)] = 128+NewWater[rx+ry * WATERDIM]; Surface[(x*4)+2+y*(SurfDesc.Width*4)] = 128+NewWater[rx+ry * WATERDIM]; } } } if(SurfDesc.Format == D3DFMT_L8) { for(int y=0; y<WATERDIM/DivFactor; y++) { for(int x=0; x<WATERDIM/DivFactor; x++) { int rx=x*DivFactor; int ry=y*DivFactor; Surface[(x+y*SurfDesc.Width)] = 128+NewWater[rx+ry * WATERDIM]; } } } DivFactor *=2; //unlock the surface TextureSurface->UnlockRect(l); } //Swap the buffers Real* Temp = NewWater; NewWater = OldWater; OldWater = Temp; }
bool SegmentImage(LPDIRECT3DTEXTURE9 texture, int subimage_width, int subimage_height, int rows, int columns, int selected_index, LPDIRECT3DTEXTURE9* segment) { D3DSURFACE_DESC desc; HRESULT hr = texture->GetLevelDesc(0, &desc); CONFIRM(SUCCEEDED(hr)) else return false; // Locate the source rectangle UINT sii = selected_index; // The sub-image index (sii) UINT sixc = sii % columns; // sub-image x-coordinate UINT siyc = sii / columns; // sub-image y-coordinate RECT sourceRect = { (sixc+0) * subimage_width, (siyc+0) * subimage_height, (sixc+1) * subimage_width, (siyc+1) * subimage_height }; // Create a texture for the sub-image LPDIRECT3DTEXTURE9 subimageTexture = NULL; { LPDIRECT3DDEVICE9 d3d_device; texture->GetDevice(&d3d_device); hr = D3DXCreateTexture(d3d_device, subimage_width, subimage_height, -1, 0, desc.Format, desc.Pool, &subimageTexture); SAFE_RELEASE(d3d_device); // If we can't make this texture, something is wrong, but we can't do much about it if (APP_WARNING(FAILED(hr))("Unable to create sub-image texture")) { return false; } //D3DSURFACE_DESC desc; //subimageTexture->GetLevelDesc(0, &desc); //DEBUG_INFO("creating image: %lu, %lu; actual size: %lu, %lu", // subimage_width, // subimage_height, // desc.Width, // desc.Height); } DWORD format_byte_size = 4; switch (desc.Format) { default: DEBUG_ERROR("Unknown image format"); return false; case D3DFMT_A8R8G8B8: case D3DFMT_X8R8G8B8: format_byte_size = sizeof(D3DCOLOR); break; case D3DFMT_A8P8: case D3DFMT_R5G6B5: case D3DFMT_X1R5G5B5: case D3DFMT_X4R4G4B4: format_byte_size = sizeof(WORD); break; } // Copy the texture D3DLOCKED_RECT sourceLR, destLR; texture->LockRect(0, &sourceLR, &sourceRect, D3DLOCK_READONLY); subimageTexture->LockRect(0, &destLR, NULL, 0); BYTE* sourceBits = (BYTE*)sourceLR.pBits; BYTE* destBits = (BYTE*)destLR.pBits; // Copy each row for (long y = 0; y < subimage_height; ++y) { memcpy(&destBits[destLR.Pitch*y], &sourceBits[sourceLR.Pitch*y], subimage_width*format_byte_size); } // Unlock the source and destination texture->UnlockRect(0); subimageTexture->UnlockRect(0); // Generate mipmaps, if necessary // TODO: this generates an error...why?! //if (mipmap) // subimageTexture->GenerateMipSubLevels(); // Save the sub-image as the output texture *segment = subimageTexture; return true; }
void Atlas::renderSprite_( const MAGIC_CHANGE_ATLAS & c, LPDIRECT3DTEXTURE9 _texture ) { D3DSURFACE_DESC texDesc; DXCALL _texture->GetLevelDesc( 0, &texDesc ); float cw = (float)c.width; float ch = (float)c.height; float tw = (float)texDesc.Width; float th = (float)texDesc.Height; float uv_x = cw / tw; float uv_y = ch / th; VERTEX_SPRITE v[4]; v[0].x = c.x; v[0].y = c.y; v[0].z = 0.f; v[0].color = 0xffffffff; v[0].u = 0.f; v[0].v = 0.f; v[1].x = c.x + c.width; v[1].y = c.y; v[1].z = 0.f; v[1].color = 0xffffffff; v[1].u = uv_x; v[1].v = 0.f; v[2].x = c.x; v[2].y = c.y + c.height; v[2].z = 0.f; v[2].color = 0xffffffff; v[2].u = 0.f; v[2].v = uv_y; v[3].x = c.x + c.width; v[3].y = c.y + c.height; v[3].z = 0.f; v[3].color = 0xffffffff; v[3].u = uv_x; v[3].v = uv_y; D3DVIEWPORT9 VP; VP.X = 0; VP.Y = 0; VP.Width = m_width; VP.Height = m_height; VP.MinZ = 0; VP.MaxZ = 1.f; DXCALL m_pDevice->SetViewport( &VP ); D3DXMATRIX ortho; MyD3DXMatrixOrthoOffCenterLH( &ortho, 0, (float)m_width, (float)m_height, 0, -1000.f, 1000.f ); DXCALL m_pDevice->SetTransform( D3DTS_PROJECTION, &ortho ); D3DXMATRIX view; D3DXMatrixIdentity( &view ); DXCALL m_pDevice->SetTransform( D3DTS_VIEW, &view ); DXCALL m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); for( int stage = 0; stage != 8; ++stage ) { DXCALL m_pDevice->SetTexture( stage, nullptr ); DXCALL m_pDevice->SetTextureStageState( stage, D3DTSS_COLOROP, D3DTOP_DISABLE ); DXCALL m_pDevice->SetTextureStageState( stage, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); } DXCALL m_pDevice->SetTexture( 0, _texture ); DXCALL m_pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); DXCALL m_pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); DXCALL m_pDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); DXCALL m_pDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); DXCALL m_pDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ); DXCALL m_pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); DXCALL m_pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); DXCALL m_pDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_CURRENT ); DXCALL m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); DXCALL m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); DXCALL m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_CURRENT ); DXCALL m_pDevice->SetFVF( FVF_SPRITE ); DXCALL m_pDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, v, sizeof(VERTEX_SPRITE) ); }
HRESULT KModelWater::InitBumpMap() { //创建水面bump纹理 HRESULT hr; LPDIRECT3DTEXTURE9 psBumpSrc; D3DSURFACE_DESC d3dsd; D3DLOCKED_RECT d3dlr; TCHAR Name[256]; wsprintf(Name,"%s\\%s",g_Def_AppDirectory,"Textures\\Water.bmp"); hr = D3DXCreateTextureFromFile(g_pd3dDevice, Name, &psBumpSrc); if (FAILED(hr)) return hr; psBumpSrc->GetLevelDesc( 0, &d3dsd ); // Create the bumpmap's surface and texture objects if( FAILED( g_pd3dDevice->CreateTexture( d3dsd.Width, d3dsd.Height, 1, 0, D3DFMT_V8U8, D3DPOOL_MANAGED, &m_pBumpMapTexture,NULL ) ) ) { return E_FAIL; } // Fill the bits of the new texture surface with bits from // a private format. psBumpSrc->LockRect( 0, &d3dlr, 0, 0 ); DWORD dwSrcPitch = (DWORD)d3dlr.Pitch; BYTE* pSrcTopRow = (BYTE*)d3dlr.pBits; BYTE* pSrcCurRow = pSrcTopRow; BYTE* pSrcBotRow = pSrcTopRow + (dwSrcPitch * (d3dsd.Height - 1) ); m_pBumpMapTexture->LockRect( 0, &d3dlr, 0, 0 ); DWORD dwDstPitch = (DWORD)d3dlr.Pitch; BYTE* pDstTopRow = (BYTE*)d3dlr.pBits; BYTE* pDstCurRow = pDstTopRow; for( DWORD y=0; y<d3dsd.Height; y++ ) { BYTE* pSrcB0; // addr of current pixel BYTE* pSrcB1; // addr of pixel below current pixel, wrapping to top if necessary BYTE* pSrcB2; // addr of pixel above current pixel, wrapping to bottom if necessary BYTE* pDstT; // addr of dest pixel; pSrcB0 = pSrcCurRow; if( y == d3dsd.Height - 1) pSrcB1 = pSrcTopRow; else pSrcB1 = pSrcCurRow + dwSrcPitch; if( y == 0 ) pSrcB2 = pSrcBotRow; else pSrcB2 = pSrcCurRow - dwSrcPitch; pDstT = pDstCurRow; for( DWORD x=0; x<d3dsd.Width; x++ ) { LONG v00; // Current pixel LONG v01; // Pixel to the right of current pixel, wrapping to left edge if necessary LONG vM1; // Pixel to the left of current pixel, wrapping to right edge if necessary LONG v10; // Pixel one line below. LONG v1M; // Pixel one line above. v00 = *(pSrcB0+0); if( x == d3dsd.Width - 1 ) v01 = *(pSrcCurRow); else v01 = *(pSrcB0+4); if( x == 0 ) vM1 = *(pSrcCurRow + (4 * (d3dsd.Width - 1))); else vM1 = *(pSrcB0-4); v10 = *(pSrcB1+0); v1M = *(pSrcB2+0); LONG iDu = (vM1-v01); // The delta-u bump value LONG iDv = (v1M-v10); // The delta-v bump value *pDstT++ = (BYTE)(iDu / 2); *pDstT++ = (BYTE)(iDv / 2); // Move one pixel to the right (src is 32-bpp) pSrcB0+=4; pSrcB1+=4; pSrcB2+=4; } // Move to the next line pSrcCurRow += dwSrcPitch; pDstCurRow += dwDstPitch; } m_pBumpMapTexture->UnlockRect(0); psBumpSrc->UnlockRect(0); return S_OK; }
//---------------------------------------------------------------------------- SEImage* SEImageConverter::CreateImageFromFile(const char* acFilename, const char* acImageName, bool bInsert) { if( !acFilename ) { return 0; } HRESULT hResult; LPDIRECT3DTEXTURE9 pDXTex; SEImage* pImage; hResult = D3DXCreateTextureFromFile(m_pDXDevice, acFilename, &pDXTex); if( !SUCCEEDED(hResult) ) { return 0; } D3DSURFACE_DESC tempDesc; pDXTex->GetLevelDesc(0, &tempDesc); int iWidth = tempDesc.Width; int iHeight = tempDesc.Height; int eFormat = D3DFMT_UNKNOWN; int iBytesPerPixel = 0; switch( tempDesc.Format ) { case D3DFMT_R8G8B8: { eFormat = SEImage::IT_RGB888; iBytesPerPixel = 3; break; } case D3DFMT_A8R8G8B8: case D3DFMT_X8R8G8B8: { eFormat = SEImage::IT_RGBA8888; iBytesPerPixel = 4; break; } case D3DFMT_L8: { eFormat = SEImage::IT_L8; iBytesPerPixel = 1; break; } case D3DFMT_L16: { eFormat = SEImage::IT_L16; iBytesPerPixel = 2; break; } default: { // 尚未支持的情况. SE_ASSERT( 0 ); break; } } int iCount = iWidth * iHeight; int iByteCount = iCount * iBytesPerPixel; unsigned char* aucDst = SE_NEW unsigned char[iByteCount]; unsigned char* pDst, * pSrc; D3DLOCKED_RECT tempLockRect; hResult = pDXTex->LockRect(0, &tempLockRect, 0, 0); SE_ASSERT( SUCCEEDED(hResult) ); pSrc = (unsigned char*)tempLockRect.pBits; pDst = aucDst; int i, iBase = 0; switch( eFormat ) { case SEImage::IT_RGB888: { for( i = 0; i < iCount; i++, iBase += 3 ) { pDst[iBase ] = pSrc[iBase + 2]; pDst[iBase + 1] = pSrc[iBase + 1]; pDst[iBase + 2] = pSrc[iBase ]; } break; } case SEImage::IT_RGBA8888: { for( i = 0; i < iCount; i++, iBase += 4 ) { pDst[iBase ] = pSrc[iBase + 2]; pDst[iBase + 1] = pSrc[iBase + 1]; pDst[iBase + 2] = pSrc[iBase ]; pDst[iBase + 3] = pSrc[iBase + 3]; } break; } case SEImage::IT_L8: { for( i = 0; i < iCount; i++, iBase += 1 ) { pDst[iBase] = pSrc[iBase]; } break; } case SEImage::IT_L16: { for( i = 0; i < iCount; i++, iBase += 2 ) { pDst[iBase ] = pSrc[iBase ]; pDst[iBase + 1] = pSrc[iBase + 1]; } break; } default: { // 尚未支持的情况. SE_ASSERT( 0 ); break; } } hResult = pDXTex->UnlockRect(0); SE_ASSERT( SUCCEEDED(hResult) ); pDXTex->Release(); if( acImageName ) { pImage = SE_NEW SEImage((SEImage::FormatMode)eFormat, iWidth, iHeight, aucDst, acImageName, bInsert); } else { pImage = SE_NEW SEImage((SEImage::FormatMode)eFormat, iWidth, iHeight, aucDst, acFilename, bInsert); } SE_ASSERT( pImage ); return pImage; }
//-------------------------------------------------------------------------------------- // MeasureLuminance( ) // // DESC: // This is the core function for this particular part of the application, it's // job is to take the previously rendered (in the 'HDRScene' namespace) HDR // image and compute the overall luminance for the scene. This is done by // repeatedly downsampling the image until it is only 1x1 in size. Doing it // this way (pixel shaders and render targets) keeps as much of the work on // the GPU as possible, consequently avoiding any resource transfers, locking // and modification. // // PARAMS: // pDevice : The currently active device that will be used for rendering. // // NOTES: // The results from this function will eventually be used to compose the final // image. See OnFrameRender() in 'HDRDemo.cpp'. // //-------------------------------------------------------------------------------------- HRESULT MeasureLuminance( IDirect3DDevice9* pDevice ) { //[ 0 ] DECLARE VARIABLES AND ALIASES //----------------------------------- LPDIRECT3DTEXTURE9 pSourceTex = NULL; // We use this texture as the input LPDIRECT3DTEXTURE9 pDestTex = NULL; // We render to this texture... LPDIRECT3DSURFACE9 pDestSurf = NULL; // ... Using this ptr to it's top-level surface //[ 1 ] SET THE DEVICE TO RENDER TO THE HIGHEST // RESOLUTION LUMINANCE MAP. //--------------------------------------------- HDRScene::GetOutputTexture( &pSourceTex ); pDestTex = Luminance::g_pTexLuminance[ Luminance::g_dwLumTextures - 1 ]; if( FAILED( pDestTex->GetSurfaceLevel( 0, &pDestSurf ) ) ) { // Couldn't acquire this surface level. Odd! OutputDebugString( L"Luminance::MeasureLuminance( ) : Couldn't acquire surface level for hi-res luminance map!\n" ); return E_FAIL; } pDevice->SetRenderTarget( 0, pDestSurf ); pDevice->SetTexture( 0, pSourceTex ); pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); //[ 2 ] RENDER AND DOWNSAMPLE THE HDR TEXTURE // TO THE LUMINANCE MAP. //------------------------------------------- // Set which shader we're going to use. g_pLum1PS corresponds // to the 'GreyScaleDownSample' entry point in 'Luminance.psh'. pDevice->SetPixelShader( Luminance::g_pLum1PS ); // We need to compute the sampling offsets used for this pass. // A 2x2 sampling pattern is used, so we need to generate 4 offsets. // // NOTE: It is worth noting that some information will likely be lost // due to the luminance map being less than 1/2 the size of the // original render-target. This mis-match does not have a particularly // big impact on the final luminance measurement. If necessary, // the same process could be used - but with many more samples, so as // to correctly map from HDR->Luminance without losing information. D3DXVECTOR4 offsets[4]; // Find the dimensions for the source data D3DSURFACE_DESC srcDesc; pSourceTex->GetLevelDesc( 0, &srcDesc ); // Because the source and destination are NOT the same sizes, we // need to provide offsets to correctly map between them. float sU = ( 1.0f / static_cast< float >( srcDesc.Width ) ); float sV = ( 1.0f / static_cast< float >( srcDesc.Height ) ); // The last two components (z,w) are unused. This makes for simpler code, but if // constant-storage is limited then it is possible to pack 4 offsets into 2 float4's offsets[0] = D3DXVECTOR4( -0.5f * sU, 0.5f * sV, 0.0f, 0.0f ); offsets[1] = D3DXVECTOR4( 0.5f * sU, 0.5f * sV, 0.0f, 0.0f ); offsets[2] = D3DXVECTOR4( -0.5f * sU, -0.5f * sV, 0.0f, 0.0f ); offsets[3] = D3DXVECTOR4( 0.5f * sU, -0.5f * sV, 0.0f, 0.0f ); // Set the offsets to the constant table Luminance::g_pLum1PSConsts->SetVectorArray( pDevice, "tcLumOffsets", offsets, 4 ); // With everything configured we can now render the first, initial, pass // to the luminance textures. RenderToTexture( pDevice ); // Make sure we clean up the remaining reference SAFE_RELEASE( pDestSurf ); SAFE_RELEASE( pSourceTex ); //[ 3 ] SCALE EACH RENDER TARGET DOWN // The results ("dest") of each pass feeds into the next ("src") //------------------------------------------------------------------- for( int i = ( Luminance::g_dwLumTextures - 1 ); i > 0; i-- ) { // Configure the render targets for this iteration pSourceTex = Luminance::g_pTexLuminance[ i ]; pDestTex = Luminance::g_pTexLuminance[ i - 1 ]; if( FAILED( pDestTex->GetSurfaceLevel( 0, &pDestSurf ) ) ) { // Couldn't acquire this surface level. Odd! OutputDebugString( L"Luminance::MeasureLuminance( ) : Couldn't acquire surface level for luminance map!\n" ); return E_FAIL; } pDevice->SetRenderTarget( 0, pDestSurf ); pDevice->SetTexture( 0, pSourceTex ); // We don't want any filtering for this pass pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); // Because each of these textures is a factor of 3 // different in dimension, we use a 3x3 set of sampling // points to downscale. D3DSURFACE_DESC srcTexDesc; pSourceTex->GetLevelDesc( 0, &srcTexDesc ); // Create the 3x3 grid of offsets D3DXVECTOR4 DSoffsets[9]; int idx = 0; for( int x = -1; x < 2; x++ ) { for( int y = -1; y < 2; y++ ) { DSoffsets[idx++] = D3DXVECTOR4( static_cast< float >( x ) / static_cast< float >( srcTexDesc.Width ), static_cast< float >( y ) / static_cast< float >( srcTexDesc.Height ), 0.0f, //unused 0.0f //unused ); } } // Set them to the current pixel shader pDevice->SetPixelShader( Luminance::g_pLum3x3DSPS ); Luminance::g_pLum3x3DSPSConsts->SetVectorArray( pDevice, "tcDSOffsets", DSoffsets, 9 ); // Render the display to this texture RenderToTexture( pDevice ); // Clean-up by releasing the level-0 surface SAFE_RELEASE( pDestSurf ); } // ============================================================= // At this point, the g_pTexLuminance[0] texture will contain // a 1x1 texture that has the downsampled luminance for the // scene as it has currently been rendered. // ============================================================= return S_OK; }
UINT Direct3D::GetTexHeight(LPDIRECT3DTEXTURE9 Texture) { D3DSURFACE_DESC surfaceDesc; Texture->GetLevelDesc(0, &surfaceDesc); return surfaceDesc.Height; }
bool CD3DMGEng::Render2DSpriteEx ( LPDIRECT3DTEXTURE9 pTexture, D3DXVECTOR2 *pScaling, D3DXVECTOR2 *pTranslation, DWORD dwColorTL, DWORD dwColorTR, DWORD dwColorBL, DWORD dwColorBR ) { D3DSURFACE_DESC myDesc; D3DSPRITEVERTEX2D *pVertices; //////////////////////////////////////////////////// // Make sure we have a valid vertex buffer. if ( m_pVB == NULL ) { return false; } //////////////////////////////////////////////////// // If we have a NULL translation, use point 0,0. float x = 0; float y = 0; if ( pTranslation != NULL ) { x = pTranslation->x; y = pTranslation->y; } //////////////////////////////////////////////////// // Get the width and height of the image to render. float tx, ty; if ( pTexture ) { pTexture->GetLevelDesc( 0, &myDesc ); tx = static_cast<float>(myDesc.Width); ty = static_cast<float>(myDesc.Height); } else { tx = 1.0f; ty = 1.0f; } /////////////////////////////////////////////////// // Scale the image if necessary. if ( pScaling != NULL ) { tx *= pScaling->x; ty *= pScaling->y; } /////////////////////////////////////////////////// // Setup the rendering. m_pDevice->SetFVF( D3DFVF_SPRITEVERTEX2DTEX ); m_pDevice->SetStreamSource( 0, m_pVB, 0, sizeof(D3DSPRITEVERTEX2D) ); if ( pTexture ) m_pDevice->SetTexture( 0, pTexture ); ////////////////////////////////////////////////// // Lock the vertex buffer and copy in the verts. m_pVB->Lock( 0, 0, (void**)&pVertices, 0 ); { pVertices[0].fX = x; pVertices[0].fY = y; pVertices[0].fZ = 0.0f; pVertices[0].fRHW = 1.0f; pVertices[0].tu = 0.0f; pVertices[0].tv = 0.0f; pVertices[0].dwColor = dwColorTL; //TOP LEFT pVertices[1].fX = x+tx; pVertices[1].fY = y; pVertices[1].fZ = 0.0f; pVertices[1].fRHW = 1.0f; pVertices[1].tu = 1.0f; pVertices[1].tv = 0.0f; pVertices[1].dwColor = dwColorTR; //TOP RIGHT pVertices[2].fX = x+tx; pVertices[2].fY = y+ty; pVertices[2].fZ = 0.0f; pVertices[2].fRHW = 1.0f; pVertices[2].tu = 1.0f; pVertices[2].tv = 1.0f; pVertices[2].dwColor = dwColorBR; //BOTTOM RIGHT pVertices[3].fX = x; pVertices[3].fY = y+ty; pVertices[3].fZ = 0.0f; pVertices[3].fRHW = 1.0f; pVertices[3].tu = 0.0f; pVertices[3].tv = 1.0f; pVertices[3].dwColor = dwColorBL; //BOTTOM LEFT } m_pVB->Unlock(); //////////////////////////////////////////////////// // Draw! m_pDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 ); if ( pTexture ) m_pDevice->SetTexture( 0, NULL ); return true; }
/// \brief Loads a texture /// \param file = the filename bool CDX9TextureObject::LoadFromFile( const TCHAR * file ) { StdString szFilePath(file); szFilePath.MakeSafeFileName(); DeInit(); if (!m_Renderer) return false; LPDIRECT3DDEVICE9 pDevice = (LPDIRECT3DDEVICE9)m_Renderer->GetAPIDevice(); if( !pDevice ) return false; D3DXIMAGE_INFO srcInfo; LPDIRECT3DTEXTURE9 pTexture; /* if( _tcsstr( file, _T(".hdr" ) )!= NULL ) { bool retval = LoadHDRFile( (TCHAR*)file ); return retval; } */ LPVOID pFileData = NULL; UINT iFileDataSize = 0; if (!LoadFileIntoBuffer( szFilePath, pFileData, iFileDataSize, true )) { m_ToolBox->Log(LOGERROR, _T("Texture Object: %s failed to load\n"), szFilePath.c_str() ); return false; } D3DFORMAT requestedFormat = EEDX9RequestedInternalFormatFromFileInMemory( pFileData, iFileDataSize ); HRESULT hr = D3DXCreateTextureFromFileInMemoryEx( pDevice, pFileData, iFileDataSize, D3DX_DEFAULT, //width D3DX_DEFAULT, //height D3DX_DEFAULT, //number of mips 0, //usage - 0 unless for render targets requestedFormat, D3DPOOL_MANAGED, D3DX_DEFAULT, //regular filter D3DX_DEFAULT, //mip filter 0, //color key, opaque black default &srcInfo, //src info NULL, //palette &pTexture ); SAFE_DELETE_ARRAY( pFileData ); if( hr != D3D_OK ) { m_ToolBox->Log(LOGERROR, _T("Texture Object: %s failed to load\n"), szFilePath.c_str() ); return false; } D3DSURFACE_DESC textureDesc; pTexture->GetLevelDesc( 0, &textureDesc ); m_Width = textureDesc.Width; m_Height = textureDesc.Height; m_Texture = pTexture; m_Filename = file; m_bRenderTarget = false; m_ColorDepth = EEDX9ColorBitsFromFormat( textureDesc.Format ); m_Compressed = EEDX9IsCompressedFormat( textureDesc.Format ); if( m_AutoGenMips ) { pTexture->GenerateMipSubLevels(); } return true; }
//-------------------------------------------------------------------------------------- // PerformPostProcessing( ) // // DESC: // This is the core function for this module - it takes the raw HDR image // generated by the 'HDRScene' component and puts it through 4 post // processing stages - to end up with a bloom effect on the over-exposed // (HDR) parts of the image. // // PARAMS: // pDevice : The device that will be rendered to // // NOTES: // n/a // //-------------------------------------------------------------------------------------- HRESULT PerformPostProcessing( IDirect3DDevice9* pDevice ) { // [ 0 ] BRIGHT PASS //------------------ LPDIRECT3DTEXTURE9 pHDRSource = NULL; if( FAILED( HDRScene::GetOutputTexture( &pHDRSource ) ) ) { // Couldn't get the input - means that none of the subsequent // work is worth attempting! OutputDebugString( L"PostProcess::PerformPostProcessing() - Unable to retrieve source HDR information!\n" ); return E_FAIL; } LPDIRECT3DSURFACE9 pBrightPassSurf = NULL; if( FAILED( PostProcess::g_pBrightPassTex->GetSurfaceLevel( 0, &pBrightPassSurf ) ) ) { // Can't get the render target. Not good news! OutputDebugString( L"PostProcess::PerformPostProcessing() - Couldn't retrieve top level surface for bright pass render target.\n" ); return E_FAIL; } pDevice->SetRenderTarget( 0, pBrightPassSurf ); // Configure the output of this stage pDevice->SetTexture( 0, pHDRSource ); // Configure the input.. pDevice->SetPixelShader( PostProcess::g_pBrightPassPS ); PostProcess::g_pBrightPassConstants->SetFloat( pDevice, "fBrightPassThreshold", PostProcess::g_BrightThreshold ); // We need to compute the sampling offsets used for this pass. // A 2x2 sampling pattern is used, so we need to generate 4 offsets D3DXVECTOR4 offsets[4]; // Find the dimensions for the source data D3DSURFACE_DESC srcDesc; pHDRSource->GetLevelDesc( 0, &srcDesc ); // Because the source and destination are NOT the same sizes, we // need to provide offsets to correctly map between them. float sU = ( 1.0f / static_cast< float >( srcDesc.Width ) ); float sV = ( 1.0f / static_cast< float >( srcDesc.Height ) ); // The last two components (z,w) are unused. This makes for simpler code, but if // constant-storage is limited then it is possible to pack 4 offsets into 2 float4's offsets[0] = D3DXVECTOR4( -0.5f * sU, 0.5f * sV, 0.0f, 0.0f ); offsets[1] = D3DXVECTOR4( 0.5f * sU, 0.5f * sV, 0.0f, 0.0f ); offsets[2] = D3DXVECTOR4( -0.5f * sU, -0.5f * sV, 0.0f, 0.0f ); offsets[3] = D3DXVECTOR4( 0.5f * sU, -0.5f * sV, 0.0f, 0.0f ); PostProcess::g_pBrightPassConstants->SetVectorArray( pDevice, "tcDownSampleOffsets", offsets, 4 ); RenderToTexture( pDevice ); // [ 1 ] DOWN SAMPLE //------------------ LPDIRECT3DSURFACE9 pDownSampleSurf = NULL; if( FAILED( PostProcess::g_pDownSampledTex->GetSurfaceLevel( 0, &pDownSampleSurf ) ) ) { // Can't get the render target. Not good news! OutputDebugString( L"PostProcess::PerformPostProcessing() - Couldn't retrieve top level surface for down sample render target.\n" ); return E_FAIL; } pDevice->SetRenderTarget( 0, pDownSampleSurf ); pDevice->SetTexture( 0, PostProcess::g_pBrightPassTex ); pDevice->SetPixelShader( PostProcess::g_pDownSamplePS ); // We need to compute the sampling offsets used for this pass. // A 4x4 sampling pattern is used, so we need to generate 16 offsets // Find the dimensions for the source data PostProcess::g_pBrightPassTex->GetLevelDesc( 0, &srcDesc ); // Find the dimensions for the destination data D3DSURFACE_DESC destDesc; pDownSampleSurf->GetDesc( &destDesc ); // Compute the offsets required for down-sampling. If constant-storage space // is important then this code could be packed into 8xFloat4's. The code here // is intentionally less efficient to aid readability... D3DXVECTOR4 dsOffsets[16]; int idx = 0; for( int i = -2; i < 2; i++ ) { for( int j = -2; j < 2; j++ ) { dsOffsets[idx++] = D3DXVECTOR4( ( static_cast< float >( i ) + 0.5f ) * ( 1.0f / static_cast< float >( destDesc.Width ) ), ( static_cast< float >( j ) + 0.5f ) * ( 1.0f / static_cast< float >( destDesc.Height ) ), 0.0f, // unused 0.0f // unused ); } } PostProcess::g_pDownSampleConstants->SetVectorArray( pDevice, "tcDownSampleOffsets", dsOffsets, 16 ); RenderToTexture( pDevice ); // [ 2 ] BLUR HORIZONTALLY //------------------------ LPDIRECT3DSURFACE9 pHBloomSurf = NULL; if( FAILED( PostProcess::g_pBloomHorizontal->GetSurfaceLevel( 0, &pHBloomSurf ) ) ) { // Can't get the render target. Not good news! OutputDebugString( L"PostProcess::PerformPostProcessing() - Couldn't retrieve top level surface for horizontal bloom render target.\n" ); return E_FAIL; } pDevice->SetRenderTarget( 0, pHBloomSurf ); pDevice->SetTexture( 0, PostProcess::g_pDownSampledTex ); pDevice->SetPixelShader( PostProcess::g_pHBloomPS ); // Configure the sampling offsets and their weights float HBloomWeights[9]; float HBloomOffsets[9]; for( int i = 0; i < 9; i++ ) { // Compute the offsets. We take 9 samples - 4 either side and one in the middle: // i = 0, 1, 2, 3, 4, 5, 6, 7, 8 //Offset = -4, -3, -2, -1, 0, +1, +2, +3, +4 HBloomOffsets[i] = ( static_cast< float >( i ) - 4.0f ) * ( 1.0f / static_cast< float >( destDesc.Width ) ); // 'x' is just a simple alias to map the [0,8] range down to a [-1,+1] float x = ( static_cast< float >( i ) - 4.0f ) / 4.0f; // Use a gaussian distribution. Changing the standard-deviation // (second parameter) as well as the amplitude (multiplier) gives // distinctly different results. HBloomWeights[i] = g_GaussMultiplier * ComputeGaussianValue( x, g_GaussMean, g_GaussStdDev ); } // Commit both arrays to the device: PostProcess::g_pHBloomConstants->SetFloatArray( pDevice, "HBloomWeights", HBloomWeights, 9 ); PostProcess::g_pHBloomConstants->SetFloatArray( pDevice, "HBloomOffsets", HBloomOffsets, 9 ); RenderToTexture( pDevice ); // [ 3 ] BLUR VERTICALLY //---------------------- LPDIRECT3DSURFACE9 pVBloomSurf = NULL; if( FAILED( PostProcess::g_pBloomVertical->GetSurfaceLevel( 0, &pVBloomSurf ) ) ) { // Can't get the render target. Not good news! OutputDebugString( L"PostProcess::PerformPostProcessing() - Couldn't retrieve top level surface for vertical bloom render target.\n" ); return E_FAIL; } pDevice->SetRenderTarget( 0, pVBloomSurf ); pDevice->SetTexture( 0, PostProcess::g_pBloomHorizontal ); pDevice->SetPixelShader( PostProcess::g_pVBloomPS ); // Configure the sampling offsets and their weights // It is worth noting that although this code is almost identical to the // previous section ('H' weights, above) there is an important difference: destDesc.Height. // The bloom render targets are *not* square, such that you can't re-use the same offsets in // both directions. float VBloomWeights[9]; float VBloomOffsets[9]; for( int i = 0; i < 9; i++ ) { // Compute the offsets. We take 9 samples - 4 either side and one in the middle: // i = 0, 1, 2, 3, 4, 5, 6, 7, 8 //Offset = -4, -3, -2, -1, 0, +1, +2, +3, +4 VBloomOffsets[i] = ( static_cast< float >( i ) - 4.0f ) * ( 1.0f / static_cast< float >( destDesc.Height ) ); // 'x' is just a simple alias to map the [0,8] range down to a [-1,+1] float x = ( static_cast< float >( i ) - 4.0f ) / 4.0f; // Use a gaussian distribution. Changing the standard-deviation // (second parameter) as well as the amplitude (multiplier) gives // distinctly different results. VBloomWeights[i] = g_GaussMultiplier * ComputeGaussianValue( x, g_GaussMean, g_GaussStdDev ); } // Commit both arrays to the device: PostProcess::g_pVBloomConstants->SetFloatArray( pDevice, "VBloomWeights", VBloomWeights, 9 ); PostProcess::g_pVBloomConstants->SetFloatArray( pDevice, "VBloomOffsets", VBloomOffsets, 9 ); RenderToTexture( pDevice ); // [ 4 ] CLEAN UP //--------------- SAFE_RELEASE( pHDRSource ); SAFE_RELEASE( pBrightPassSurf ); SAFE_RELEASE( pDownSampleSurf ); SAFE_RELEASE( pHBloomSurf ); SAFE_RELEASE( pVBloomSurf ); return S_OK; }
IDirect3DTexture9* Core::LoadTexture( IDirect3DDevice9* device, const tstring& file, u32* textureSize, bool* hasAlpha, D3DPOOL pool ) { IDirect3DTexture9* texture = NULL; bool alpha = false; if (!file.empty()) { if ( Helium::Path( file ).Exists() ) { D3DFORMAT textureFormat = D3DFMT_DXT1; D3DXIMAGE_INFO sourceInfo; LPDIRECT3DTEXTURE9 tempTexture; if ( D3DXCreateTextureFromFileEx( device, file.c_str(), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, NULL, D3DFMT_A8R8G8B8, pool, D3DX_DEFAULT, // filter? D3DX_FILTER_NONE, // mip filter NULL, &sourceInfo, NULL, &tempTexture ) == D3D_OK ) { // lock the first mip level, and iterate over all pixels looking for // alpha != 0 || alpha != 255 D3DLOCKED_RECT lockedRect; HRESULT locked = tempTexture->LockRect(0, &lockedRect, NULL, D3DLOCK_READONLY); D3DSURFACE_DESC desc; tempTexture->GetLevelDesc(0, &desc); for(u32 r = 0; r < desc.Height && textureFormat == D3DFMT_DXT1; r++) { u32* pixels = (u32*) (((u8*)lockedRect.pBits) + lockedRect.Pitch * r); for(u32 c = 0; c < desc.Width; c++) { u32 masked = pixels[c] & 0xFF000000; if(masked != 0xFF000000) { alpha = true; } if(masked != 0xFF000000 && masked != 0x00000000) { textureFormat = D3DFMT_DXT5; break; } } } tempTexture->UnlockRect(0); tempTexture->Release(); } int compressionRatio; switch ( textureFormat ) { case D3DFMT_DXT1: { if (alpha) { compressionRatio = 8; } else { compressionRatio = 6; } break; } case D3DFMT_DXT5: { compressionRatio = 4; break; } default: { compressionRatio = 1; HELIUM_BREAK(); break; } } if ( D3DXCreateTextureFromFileEx( device, file.c_str(), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, NULL, textureFormat, pool, D3DX_DEFAULT, D3DX_DEFAULT, NULL, &sourceInfo, NULL, &texture ) == D3D_OK ) { texture->SetAutoGenFilterType( D3DTEXF_ANISOTROPIC ); if ( textureSize ) { *textureSize = 0; for(u32 i = 0; i < texture->GetLevelCount(); i++) { D3DSURFACE_DESC desc; texture->GetLevelDesc(i, &desc); *textureSize += desc.Width * desc.Height * 4 / compressionRatio; } } } else { Log::Warning( TXT( "Unable to create texture from file '%s'\n" ), file.c_str() ); } } else { Log::Warning( TXT( "File '%s' does not exist\n" ), file.c_str() ); } } if ( hasAlpha ) { *hasAlpha = alpha; } return texture; }