Shaders for Game Programmers and Artists代码实现Chapter_0503时间:2021-12-07 16:40:17 该例子实现了纹理的灰度化。 代码: /********************************* Author: rabbit729* E-mail: wlq_729@163.com* Date: 2011-05-07* Description: 实现渲染对象灰度化********************************/#include <d3dx9.h>//-----------------------------------------------------------------------------// Desc: 全局变量//-----------------------------------------------------------------------------LPDIRECT3D9 g_pD3D = NULL; //Direct3D对象LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; //Direct3D设备对象LPD3DXMESH g_pMeshTeapot = NULL; //茶壶网格模型对象LPDIRECT3DTEXTURE9 g_pMeshTeapotTexture = NULL; //茶壶网格模型纹理DWORD g_dwTeapotNumMaterials = 0; //茶壶网格模型材质数量LPD3DXMESH g_pMeshElephant = NULL; //大象网格模型对象LPDIRECT3DTEXTURE9 g_pMeshElephantTexture = NULL; //大象网格模型纹理DWORD g_dwElephantNumMaterials = 0; //大象网格模型材质数量LPDIRECT3DTEXTURE9 g_pTextureScreen = NULL; //待渲染TextureLPDIRECT3DSURFACE9 g_pRTScreen = NULL; //待渲染表面ID3DXEffect* g_pEffect = NULL; //效果指针//常量句柄D3DXHANDLE hWVPMatrixHandle = NULL; //变换矩阵句柄D3DXHANDLE hTexTeapot = NULL; //茶壶纹理句柄D3DXHANDLE hTexElephant = NULL; //大象纹理句柄D3DXHANDLE hTexScreen = NULL; //rt句柄D3DXHANDLE hPos = NULL; //大象位置句柄D3DXHANDLE hTechTeapot = NULL; //茶壶技术句柄D3DXHANDLE hTechElephant = NULL; //大象技术句柄D3DXHANDLE hTechScreen = NULL; //平面板技术句柄D3DXHANDLE hViewPortWidthInv = NULL; //视口宽倒数句柄D3DXHANDLE hViewPortHeightInv = NULL; //视口高倒数句柄LPDIRECT3DVERTEXBUFFER9 g_pScreenSpaceQuad = NULL; //背板VBconst int WIDTH = 600;const int HEIGHT = 500;#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)struct Vertex{Vertex(){}Vertex(float x, float y, float z, float w){_x = x; _y = y; _z = z; _w = w;}float _x, _y, _z, _w;static const DWORD FVF;};const DWORD Vertex::FVF = D3DFVF_XYZW;//-----------------------------------------------------------------------------// Desc: 设置世界矩阵//-----------------------------------------------------------------------------VOID SetWorldMatrix(){ //创建并设置世界矩阵 D3DXMATRIXA16 matWorld, matRotateX, matRotateY;D3DXMATRIXA16 matScale;D3DXMatrixIdentity(&matScale);matScale._11 = matScale._22 = matScale._33 = 0.5f;D3DXMatrixIdentity(&matWorld);D3DXMatrixIdentity(&matRotateX);D3DXMatrixIdentity(&matRotateY); D3DXMatrixRotationX( &matRotateX, D3DX_PI / 3.0 );D3DXMatrixRotationY( &matRotateY, -D3DX_PI / 8.0 );D3DXMatrixMultiply(&matWorld, &matRotateX, &matRotateY);D3DXMatrixMultiply(&matWorld, &matScale, &matWorld); g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );}//-----------------------------------------------------------------------------// Desc: 设置观察矩阵和投影矩阵//-----------------------------------------------------------------------------VOID SetViewAndProjMatrix(){ //创建并设置观察矩阵 D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-250.0f ); D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); D3DXMATRIXA16 matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); //创建并设置投影矩阵 D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 1000.0f ); g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );}//-----------------------------------------------------------------------------// 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_A8R8G8B8; //创建Direct3D设备对象 if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) { return E_FAIL; }//创建EffectID3DXBuffer* errBuffer = NULL;if (FAILED(D3DXCreateEffectFromFile(g_pd3dDevice, L"0401.fx", NULL, NULL, D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION, NULL, &g_pEffect, &errBuffer))){if (errBuffer){MessageBox(0, (LPCTSTR)errBuffer->GetBufferPointer(), 0, 0);errBuffer->Release();}return E_FAIL;}//获取常量句柄hWVPMatrixHandle = g_pEffect->GetParameterByName(0, "matWVP");hTexTeapot = g_pEffect->GetParameterByName(0, "TexTeapot");hTexElephant = g_pEffect->GetParameterByName(0, "TexElephant");hTexScreen = g_pEffect->GetParameterByName(0, "TexScreen");hPos = g_pEffect->GetParameterByName(0, "vPos");hTechTeapot = g_pEffect->GetTechniqueByName("Teapot");hTechElephant = g_pEffect->GetTechniqueByName("Elephant");hTechScreen = g_pEffect->GetTechniqueByName("Screen");hViewPortWidthInv = g_pEffect->GetParameterByName(0, "viewport_inv_width");hViewPortHeightInv = g_pEffect->GetParameterByName(0, "viewport_inv_height");//设置环境光 g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );//设置观察矩阵和投影矩阵SetViewAndProjMatrix(); return S_OK;}//-----------------------------------------------------------------------------// Desc: 从绝对路径中提取纹理文件名//-----------------------------------------------------------------------------void RemovePathFromFileName(LPSTR fullPath, LPWSTR fileName){//先将fullPath的类型变换为LPWSTRWCHAR wszBuf[MAX_PATH];MultiByteToWideChar( CP_ACP, 0, fullPath, -1, wszBuf, MAX_PATH );wszBuf[MAX_PATH-1] = L'/0';WCHAR* wszFullPath = wszBuf;//从绝对路径中提取文件名LPWSTR pch=wcsrchr(wszFullPath,'//');if (pch)lstrcpy(fileName, ++pch);elselstrcpy(fileName, wszFullPath);}//-----------------------------------------------------------------------------// Desc: 创建场景图形//-----------------------------------------------------------------------------HRESULT InitGeometry(){ LPD3DXBUFFER pD3DXMtrlBuffer; //存储网格模型材质的缓冲区对象 //从磁盘文件加载网格模型 茶壶模型 if( FAILED( D3DXLoadMeshFromX( L"teapot.x", D3DXMESH_MANAGED, g_pd3dDevice, NULL, &pD3DXMtrlBuffer, NULL, &g_dwTeapotNumMaterials, &g_pMeshTeapot ) ) ) { MessageBox(NULL, L"Could not find teapot.x", L"Mesh", MB_OK); return E_FAIL; }//从磁盘文件加载网格模型 大象模型if( FAILED( D3DXLoadMeshFromX( L"Elephant.x", D3DXMESH_MANAGED, g_pd3dDevice, NULL, &pD3DXMtrlBuffer, NULL, &g_dwElephantNumMaterials, &g_pMeshElephant ) ) ){MessageBox(NULL, L"Could not find elephant.x", L"Mesh", MB_OK);return E_FAIL;}// 创建屏幕板g_pd3dDevice->CreateVertexBuffer(6 * sizeof(Vertex),D3DUSAGE_WRITEONLY,Vertex::FVF, D3DPOOL_MANAGED,&g_pScreenSpaceQuad,0);Vertex* vertices;g_pScreenSpaceQuad->Lock(0, 0, (void**)&vertices, 0);vertices[0] = Vertex(-1.0f, 1.0f, 0.5f, 1.0f);vertices[1] = Vertex(1.0f, 1.0f, 0.5f, 1.0f);vertices[2] = Vertex( 1.0f, -1.0f, 0.5f, 1.0f);vertices[3] = Vertex(-1.0f, 1.0f, 0.5f, 1.0f);vertices[4] = Vertex( 1.0f, -1.0f, 0.5f, 1.0f);vertices[5] = Vertex( -1.0f, -1.0f, 0.5f, 1.0f);g_pScreenSpaceQuad->Unlock(); //加载纹理HRESULT hr = D3DXCreateTextureFromFile(g_pd3dDevice, L"Fieldstone.tga", &g_pMeshTeapotTexture);if (FAILED(hr)){return E_FAIL;} hr = D3DXCreateTextureFromFile(g_pd3dDevice, L"Earth.jpg", &g_pMeshElephantTexture);if (FAILED(hr)){return E_FAIL;}// 创建rthr = g_pd3dDevice->CreateTexture(WIDTH, HEIGHT, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_pTextureScreen, NULL);if (FAILED(hr)){return E_FAIL;}g_pTextureScreen->GetSurfaceLevel(0, &g_pRTScreen);//释放在加载模型文件时创建的保存模型材质和纹理数据的缓冲区对象 pD3DXMtrlBuffer->Release(); return S_OK;}//-----------------------------------------------------------------------------// Desc: 释放创建的对象//-----------------------------------------------------------------------------VOID Cleanup(){//释放网格模型纹理 if( g_pMeshTeapotTexture ) { g_pMeshTeapotTexture->Release(); }if (g_pMeshElephantTexture){g_pMeshElephantTexture->Release();}//释放网格模型对象 if( g_pMeshTeapot != NULL ) g_pMeshTeapot->Release();if (g_pMeshElephant != NULL){g_pMeshElephant->Release();}if (g_pScreenSpaceQuad != NULL){g_pScreenSpaceQuad->Release();}if (g_pTextureScreen != NULL){g_pTextureScreen->Release();}if (g_pEffect != NULL){g_pEffect->Release();} //释放Direct3D设备对象 if( g_pd3dDevice != NULL ) g_pd3dDevice->Release();//释放Direct3D对象 if( g_pD3D != NULL ) g_pD3D->Release();}void RenderTeapot(){// 设置RenderTargetg_pd3dDevice->SetRenderTarget(0, g_pRTScreen);// 清除缓冲区g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(255,0,0,0), 1.0f, 0 );SetWorldMatrix(); //设置世界矩阵g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);D3DXMATRIX matWorld, matView, matProj;g_pd3dDevice->GetTransform(D3DTS_WORLD, &matWorld);g_pd3dDevice->GetTransform(D3DTS_VIEW, &matView);g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &matProj);D3DXMATRIX matWVP = matWorld * matView * matProj;g_pEffect->SetMatrix(hWVPMatrixHandle, &matWVP);g_pEffect->SetTexture(hTexTeapot, g_pMeshTeapotTexture);// 设置要使用的Techniqueg_pEffect->SetTechnique(hTechTeapot);//遍历技术中包含的所有过程进行多次渲染UINT numPasses = 0;g_pEffect->Begin(&numPasses, 0);for (int i = 0; i < numPasses; i++){g_pEffect->BeginPass(i);//茶壶for( DWORD i=0; i<g_dwTeapotNumMaterials; i++ ){//渲染模型g_pMeshTeapot->DrawSubset( i );}g_pEffect->EndPass();}g_pEffect->End();}void RenderElephant(){// 设置RenderTarget,此处不能清除缓冲区,需要保留上次茶壶渲染结果g_pd3dDevice->SetRenderTarget(0, g_pRTScreen);g_pEffect->SetTexture(hTexElephant, g_pMeshElephantTexture);D3DXVECTOR4 vPos(100.f, -64.f, 100.f, 0.f);g_pEffect->SetValue(hPos, vPos, D3DX_DEFAULT);// 设置要使用的Techniqueg_pEffect->SetTechnique(hTechElephant);//遍历技术中包含的所有过程进行多次渲染UINT numPasses = 0;g_pEffect->Begin(&numPasses, 0);for (int i = 0; i < numPasses; i++){g_pEffect->BeginPass(i);//茶壶for( DWORD i=0; i<g_dwElephantNumMaterials; i++ ){//渲染模型g_pMeshElephant->DrawSubset( i );}g_pEffect->EndPass();}g_pEffect->End();}VOID RenderScreen(){//将RenderTarget作为纹理g_pEffect->SetTexture(hTexScreen, g_pTextureScreen);float fWidthInv = 1.0f / WIDTH;float fHeightInv = 1.0f / HEIGHT;g_pEffect->SetFloat(hViewPortWidthInv, fWidthInv);g_pEffect->SetFloat(hViewPortHeightInv, fHeightInv);g_pd3dDevice->SetStreamSource(0, g_pScreenSpaceQuad, 0, sizeof(Vertex));g_pd3dDevice->SetFVF(Vertex::FVF);// 设置要使用的Techniqueg_pEffect->SetTechnique(hTechScreen);//遍历技术中包含的所有过程进行多次渲染UINT numPasses = 0;g_pEffect->Begin(&numPasses, 0);for (int i = 0; i < numPasses; i++){g_pEffect->BeginPass(i);g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);g_pEffect->EndPass();}g_pEffect->End();}//-----------------------------------------------------------------------------// Desc: 渲染场景//-----------------------------------------------------------------------------VOID Render(){ // 获取backbufferLPDIRECT3DSURFACE9 pBackbuffer;g_pd3dDevice->GetRenderTarget(0, &pBackbuffer); //开始渲染场景 if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) {RenderTeapot();RenderElephant();//设回backbufferg_pd3dDevice->SetRenderTarget(0, pBackbuffer);RenderScreen(); //场景渲染结束 g_pd3dDevice->EndScene(); } //在屏幕上显示场景 g_pd3dDevice->Present( NULL, NULL, NULL, NULL );}//-----------------------------------------------------------------------------// Desc: 窗口过程, 处理消息//-----------------------------------------------------------------------------LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){ switch( msg ) { case WM_DESTROY:Cleanup(); PostQuitMessage( 0 ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam );}//-----------------------------------------------------------------------------// Desc: 入口函数//-----------------------------------------------------------------------------INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ){ //注册窗口类 WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"ClassName", NULL }; RegisterClassEx( &wc ); //创建窗口 HWND hWnd = CreateWindow( L"ClassName", L"Effect 实现", WS_OVERLAPPEDWINDOW, 200, 100, WIDTH, HEIGHT, GetDesktopWindow(), NULL, wc.hInstance, NULL );//初始化Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ) { //创建场景图形 if( SUCCEEDED( InitGeometry() ) ) { //显示窗口 ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); //进入消息循环 MSG msg; ZeroMemory( &msg, sizeof(msg) ); while( msg.message!=WM_QUIT ) { if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else{ Render(); //渲染场景} } } } UnregisterClass( L"ClassName", wc.hInstance ); return 0;} effect代码: /********************************* Author: rabbit729* E-mail: wlq_729@163.com* Date: 2011-05-07********************************////////////////// 茶壶 ////////////////////////------------------------------// 顶点着色器//------------------------------matrix matWVP;float4 vPos;struct VS_OUTPUTTEAPOT{ float4 Pos: POSITION; float2 Txr1: TEXCOORD0;};VS_OUTPUTTEAPOT vs_mainPassTeapot( float4 inPos: POSITION, float2 Txr1: TEXCOORD0){ VS_OUTPUTTEAPOT Out; Out.Pos = mul(inPos, matWVP); Out.Txr1 = Txr1; return Out;}//------------------------------// 像素着色器//------------------------------Texture2D TexTeapot;sampler2D TexMapTeapot { Texture = <TexTeapot>;};float4 ps_mainPassTeapot( float4 inPosition: COLOR0, float2 inTxr1: TEXCOORD0) : COLOR0{ return tex2D(TexMapTeapot,inTxr1);}//////////////// 大象 /////////////////////////------------------------------// 顶点着色器//------------------------------struct VS_OUTPUTPELEPHANT{ float4 Pos: POSITION; float2 Txr1: TEXCOORD0;};VS_OUTPUTPELEPHANT vs_mainPassElephant( float4 inPos: POSITION, float2 Txr1: TEXCOORD0){ VS_OUTPUTPELEPHANT Out; Out.Pos = mul(inPos + vPos, matWVP); Out.Txr1 = Txr1; return Out;}//------------------------------// 像素着色器//------------------------------Texture2D TexElephant;sampler2D TexMapElephant { Texture = <TexElephant>;};float4 ps_mainPassElephant( float4 inPosition: COLOR0, float2 inTxr1: TEXCOORD0) : COLOR0{ return tex2D(TexMapElephant,inTxr1);}///////// 全屏特技 ///////////////////------------------------------// 顶点着色器//------------------------------float viewport_inv_width;float viewport_inv_height;struct VS_OUTPUTSCREEN { float4 Pos: POSITION; float2 texCoord: TEXCOORD0;};VS_OUTPUTSCREEN vs_mainPassScreen(float4 Pos: POSITION){ VS_OUTPUTSCREEN Out; Out.Pos = float4(Pos.xy, 0, 1); Out.texCoord.x = 0.5 * (1 + Pos.x - viewport_inv_width); Out.texCoord.y = 0.5 * (1 - Pos.y - viewport_inv_height); return Out;}//------------------------------// 像素着色器//------------------------------Texture2D TexScreen;sampler2D TexMapScreen { Texture = <TexScreen>;};float4 ps_mainPassScreen(float2 texCoord: TEXCOORD0) : COLOR { float4 col = tex2D(TexMapScreen, texCoord); float Intensity; // Make it B&W, intensity defines as being // I = 0.299*R + 0.587*G + 0.184*B Intensity = 0.299*col.r + 0.587*col.g + 0.184*col.r; return float4(Intensity.xxx,col.a);}//------------------------------// 效果框架//------------------------------technique Teapot{ pass P0 { VertexShader = compile vs_3_0 vs_mainPassTeapot(); PixelShader = compile ps_3_0 ps_mainPassTeapot(); }}technique Elephant{ pass P0 { VertexShader = compile vs_3_0 vs_mainPassElephant(); PixelShader = compile ps_3_0 ps_mainPassElephant(); }}technique Screen{ pass P0 { VertexShader = compile vs_3_0 vs_mainPassScreen(); PixelShader = compile ps_3_0 ps_mainPassScreen(); }}