Direct3D进行Alpha混合实现半透明效果
演示程序下载地址:http://download.csdn.net/detail/jiangcaiyang123/4091157
这次给大家奉献的是我最近学习DirectX基础的一些内容:进行Alpha混合。虽然我在很多的游戏中看到了美轮美奂的半透明效果,但是能够自己制作出半透明的效果还是一件非常欣慰的事情。因为这不仅仅是自己目的的达成,还是自己自学能力的提升。
【Direct3D进行Alpha混合实现半透明效果】Alpha是像素颜色中的一个值,但是改变它并不能改变任何颜色,而是改变它的透明度。它占一个字节,也就是说它的取值范围为从0到255。0代表完全看不见,255表示完全不透明。为此我记住了两个英文单词:transparent和opaque。为了能够使用Alpha制作出半透明的效果,要在D3D设备上调用一个函数来启用它。这个函数就是SetRenderState。下面就是启用Alpha混合的典型用法:
// 设置Alpha混合
m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
m_pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
m_pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
//其它复杂的我也没有看懂,反正Alpha混合是在光栅化(Rasterization)上进行的。其中还有很多其它的操作,但是在初级阶段是用不着啦。所以我也暂时不研究了。它在《Real Time Rendering》这本书里有。这里是我的修改的项目,就是将以前的项目稍微进行了修改,就可以显示这样的效果了:// RenderByFileDialog.cpp Alpha半透明效果的实现文件
// 2012年2月26日13:35:02 最后编辑#include// ATL应用程序基础库
#include// ATL应用程序必须有的文件
#include// 包含WTL打开文件的对话框
#include "RenderByFileDialog.h"
#include "resource.h"// 资源头文件#define SAFE_RELEASE( p )if ( p ) { p->Release( );
p = 0;
}CRenderByFileDialog::CRenderByFileDialog( HINSTANCE hInst, HWND hWnd,
LPDIRECT3DDEVICE9 pDevice,
int width, int height )// 构造函数
{
// 成员赋值
m_pDevice= pDevice;
m_MoveFact= 0.01f;
m_CurImageFile= TEXT( "" );
// 设置视角
ZeroMemory( &m_Viewport, sizeof( m_Viewport ) );
// 清零
m_Viewport.X= 0;
m_Viewport.Y= 0;
m_Viewport.Width= width;
m_Viewport.Height= height;
m_Viewport.MinZ= 0.0f;
m_Viewport.MaxZ= 1.0f;
m_pDevice->SetViewport( &m_Viewport );
// 创建顶点缓存
HRESULT hr;
hr = m_pDevice->CreateVertexBuffer( 8 * sizeof( STVertex ), D3DUSAGE_WRITEONLY,
TEXTURE_FVF, D3DPOOL_MANAGED, &m_pBuffer, NULL );
ThrowIfFailed( hr, "不会吧,这都无法创建顶点缓存。⊙﹏⊙b汗" );
hr = m_pBuffer->Lock( 0, 8 * sizeof( STVertex ), (void**)&m_pVtxBackground, D3DLOCK_DISCARD );
ThrowIfFailed( hr, "不可能,顶点怎么会锁住失败呢??o(>﹏<)o" );
m_pVertices = &m_pVtxBackground[4];
hr = m_pBuffer->Unlock( );
ThrowIfFailed( hr, "不可能,顶点怎么会也会解锁失败呢??o(>﹏<)o" );
D3DXIMAGE_INFOimageInfo;
hr = D3DXCreateTextureFromResourceEx(// 从资源创建纹理
m_pDevice,// DIRECT3DDEVICE9结构指针
NULL,// 模块句柄
MAKEINTRESOURCE( IDR_RCDATA1 ),// 载入的图像资源名称
D3DX_DEFAULT,// 宽
D3DX_DEFAULT,// 高
D3DX_FROM_FILE,// mip级别
0,// 用途
D3DFMT_A8R8G8B8,// 格式
D3DPOOL_MANAGED,// 内存池格式
D3DX_DEFAULT,// 滤波器
D3DX_DEFAULT,// mip滤波器
0,// 关键色(作掩码用)
&imageInfo,// 源文件信息
NULL,// 调色板
&m_pTexBackground );
ThrowIfFailed( hr, "怎么可能啊,这个错误不应该出现的啊。找找jiangcaiyang,他最知道是什么原因。" );
CenterImage( imageInfo, m_pVtxBackground );
// 调整纹理至居中// 初始化前景纹理的顶点
hr = D3DXCreateTextureFromResourceEx(// 从资源创建纹理
m_pDevice,// DIRECT3DDEVICE9结构指针
NULL,// 模块句柄
MAKEINTRESOURCE( IDR_RCDATA2 ),// 载入的图像资源名称
D3DX_DEFAULT,// 宽
D3DX_DEFAULT,// 高
D3DX_FROM_FILE,// mip级别
0,// 用途
D3DFMT_A8R8G8B8,// 格式
D3DPOOL_MANAGED,// 内存池格式
D3DX_DEFAULT,// 滤波器
D3DX_DEFAULT,// mip滤波器
0,// 关键色(作掩码用)
&imageInfo,// 源文件信息
NULL,// 调色板
&m_pTexture );
ThrowIfFailed( hr, "怎么可能啊,这个错误不应该出现的啊。找找jiangcaiyang,他最知道是什么原因。" );
CenterImage( imageInfo, m_pVertices );
// 调整纹理至居中// 设置顶点缓存和灵活顶点格式
m_pDevice->SetStreamSource( 0, m_pBuffer, 0, sizeof( STVertex ) );
// 相同资源的顶点缓存要在一起为好
m_pDevice->SetTexture( 0, m_pTexBackground );
// 设置背景纹理
m_pDevice->SetFVF( TEXTURE_FVF );
// 设置关灯
hr = m_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
ThrowIfFailed( hr, "怎么不能关灯了呢?" );
// 设置Alpha混合
m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
m_pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
m_pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
// 初始化输入系统
m_ImmediateInput.Initialize( IMMEDIATE, hInst, hWnd );
m_BufferInput.Initialize( BUFFERED, hInst, hWnd );
}unsigned long CRenderByFileDialog::Release( void )// 释放空间
{
SAFE_RELEASE( m_pTexture );
SAFE_RELEASE( m_pTexBackground );
SAFE_RELEASE( m_pBuffer );
return 0;
}void CRenderByFileDialog::CenterImage( D3DXIMAGE_INFO& imageInfo, STVertex* vertices )// 图片居中
{
floatx, y;
x = -1.0f / float( m_Viewport.Width ) * float( imageInfo.Width );
y = -1.0f / float( m_Viewport.Height ) * float( imageInfo.Height );
vertices[0].Set( x, y, 1.0f, 0.0f, 1.0f );
vertices[1].Set( x, -y, 1.0f, 0.0f, 0.0f );
vertices[2].Set( -x, y, 1.0f, 1.0f, 1.0f );
vertices[3].Set( -x, -y, 1.0f, 1.0f, 0.0f );
}void CRenderByFileDialog::BrowseImageFile( void )// 浏览并且获取图像文件的路径
{
CFileDialog imageFileDlg( TRUE,
TEXT( ".jpg" ),
m_CurImageFile.c_str( ),
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
TEXT( "JPG/JPEG文件\0*.jpg\0PNG文件\0*.png\0所有文件\0*.*" ),
NULL );
if ( IDOK == imageFileDlg.DoModal( ) )
{
m_CurImageFile = imageFileDlg.m_szFileName;
}
}void CRenderByFileDialog::Draw( void )// 绘图
{
m_ImmediateInput.UpdateKeyState( );
m_BufferInput.UpdateKeyState( );
m_pDevice->SetTexture( 0, m_pTexBackground );
// 设置背景纹理
m_pDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
m_pDevice->SetTexture( 0, m_pTexture );
// 设置前景纹理
m_pDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 4, 2 );
// 开始进行交互
if ( m_BufferInput.KeyDown( DIK_RETURN ) )
{
D3DXIMAGE_INFOimageInfo;
HRESULT hr;
SAFE_RELEASE( m_pTexture );
// 释放空间
BrowseImageFile( );
// 浏览图片文件并且载入
hr = D3DXCreateTextureFromFileEx(// 从文件创建纹理
m_pDevice,// DIRECT3DDEVICE9结构指针
m_CurImageFile.c_str( ),// 载入的图像文件名
D3DX_DEFAULT,// 宽
D3DX_DEFAULT,// 高
D3DX_FROM_FILE,// mip级别
0,// 用途
D3DFMT_A8R8G8B8,// 格式
D3DPOOL_MANAGED,// 内存池格式
D3DX_DEFAULT,// 滤波器
D3DX_DEFAULT,// mip滤波器
0,// 关键色(作掩码用)
&imageInfo,// 源文件信息
NULL,// 调色板
&m_pTexture );
// IDirect3DTexture9指针ThrowIfFailed( hr, "不可能,载入纹理竟然会失败!是不是文件名错误了呢?" );
CenterImage( imageInfo, m_pVertices );
// 调整纹理至居中
}
if ( m_ImmediateInput.KeyDown( DIK_UP ) )
{
m_pVertices[0].y += m_MoveFact, m_pVertices[1].y += m_MoveFact;
m_pVertices[2].y += m_MoveFact, m_pVertices[3].y += m_MoveFact;
}
if ( m_ImmediateInput.KeyDown( DIK_DOWN ) )
{
m_pVertices[0].y -= m_MoveFact, m_pVertices[1].y -= m_MoveFact;
m_pVertices[2].y -= m_MoveFact, m_pVertices[3].y -= m_MoveFact;
}
if ( m_ImmediateInput.KeyDown( DIK_LEFT ) )
{
m_pVertices[0].x -= m_MoveFact, m_pVertices[1].x -= m_MoveFact;
m_pVertices[2].x -= m_MoveFact, m_pVertices[3].x -= m_MoveFact;
}
if ( m_ImmediateInput.KeyDown( DIK_RIGHT ) )
{
m_pVertices[0].x += m_MoveFact, m_pVertices[1].x += m_MoveFact;
m_pVertices[2].x += m_MoveFact, m_pVertices[3].x += m_MoveFact;
}
}
这样还不够。因为仅仅是实现了启用Alpha载入文件,但是文件在创建的时候也必须是带有Alpha值的。下面我就用自己常用的Photoshop Cs4和EasyPaintToolSAI来演示一下。
在Photoshop新建对话框里,选择背景为透明,如下图:
随后为了简单起见,仅仅使用单图层,并且使用渐变的效果来演示。将渐变的不透明度调整为50%,如下图:
然后随便在图片上使用渐变绘图:
绘制完后保存为png格式文件,然后可以在程序中载入,结果如下图所示:
使用EasyPaintToolSAI也非常简单:在控制面板中调整图层的不透明度,然后点另存为,如下图:
另存为png格式之后提示一个对话框,选择下面带有Alpha值的就是了,要不然你绘制的带有Alpha值的图片是不会显示半透明效果的,因为它根本就没有保存起来嘛。
最后显示的效果如下图所示:
推荐阅读
- 怎么将桌面上的CAD图纸添加到软件中进行BMP格式转换()
- R语言迹检验协整关系式_使用R语言进行协整关系检验
- R|R for data Science(六)(readr 进行数据导入)
- 使用Promise对微信小程序wx.request请求方法进行封装
- 武威市电视台对黄羊镇九年制学校进行采访
- 期中考试
- 520之采桑果
- '2'>'10'==true?|'2'>'10'==true? JS是如何进行隐式类型转换的()
- 一生的旅程进行时
- 初二一班家访进行时