// 法相贴图.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "法相贴图.h"
#include<d3d9.h>
#include<d3dx9.h>
#include<mmsystem.h>
#include<windows.h>
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
HWND g_hWnd ;
LPDIRECT3D9 g_pD3D = NULL ;
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL ;
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL ;
LPDIRECT3DTEXTURE9 g_pTexDiffuse = NULL ; //纹理壁画
LPDIRECT3DTEXTURE9 g_pTexNormal = NULL ; //纹理法线贴画
LPDIRECT3DVERTEXBUFFER9 g_pVB1 = NULL ;
D3DXMATRIXA16 g_matAni ;
D3DXVECTOR3 g_vLighter ; //光源
struct CUSTOMVERTEX
{
FLOAT x,y,z;
DWORD color;
FLOAT u,v; //纹理坐标
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ |D3DFVF_DIFFUSE|D3DFVF_TEX1|D3DFVF_TEXCOORDSIZE2(0))
HRESULT InitD3D (HWND hWnd )
{
//创建D3D对象
if(NULL == ( g_pD3D =Direct3DCreate9 ( D3D_SDK_VERSION ) ))
return E_FAIL;
//创建设备的结构体
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp ,sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
return E_FAIL;
//实现卷起功能
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE , D3DCULL_NONE);
//起到z缓冲的功能
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE , TRUE );
//顶点具有颜色,能起到光源的功能
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING ,FALSE);
return S_OK;
}
HRESULT InitVB()
{
CUSTOMVERTEX vertices[]=
{
{-0.5, 0.5,0,0xffffffff,0,0}, //v0
{ 0.5, 0.5,0,0xffffffff,1,0}, //v1
{-0.5,-0.5,0,0xffffffff,0,1}, //v2
{ 0.5,-0.5,0,0xffffffff,1,1} //v3
};
if(FAILED (g_pd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT ,&g_pVB ,NULL)))
return E_FAIL;
void *pVertices;
if(FAILED (g_pVB->Lock(0, sizeof(CUSTOMVERTEX), (void **) &pVertices, 0 )))
return E_FAIL;
memcpy(pVertices ,vertices ,sizeof(vertices));
g_pVB->Unlock();
return S_OK;
}
HRESULT InitTexture()
{
//壁面纹理
if(FAILED( D3DXCreateTextureFromFile(g_pd3dDevice , L"env2.bmp",&g_pTexDiffuse )))
return E_FAIL;
//然后我们现在写法线贴图初始化
if(FAILED( D3DXCreateTextureFromFile(g_pd3dDevice , L"normal.bmp",&g_pTexNormal )))
return E_FAIL;
return S_OK;
}
HRESULT InitGeometry()
{
if(FAILED(InitVB())) return E_FAIL;
if(FAILED(InitTexture())) return E_FAIL;
g_vLighter = D3DXVECTOR3(0.0f ,0.0f ,1.0f); //这个是在写光源的初始化
return S_OK;
}
void SetupCamera()
{
//创建一个世界矩阵
D3DXMATRIXA16 matWorld;
D3DXMatrixIdentity( &matWorld );
g_pd3dDevice->SetTransform( D3DTS_WORLD , &matWorld );
//创建视图矩阵
D3DXVECTOR3 vEyePt ( 0.0f , 0.0f , -4.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 ,100.0f ); //近裁面和远裁面都是1.0
g_pd3dDevice->SetTransform( D3DTS_PROJECTION , &matProj );
}
//光源设置
void Animate()
{
D3DXMatrixIdentity( &g_matAni);
POINT pt;
GetCursorPos( &pt);
ScreenToClient( g_hWnd , &pt);
g_vLighter.x = -((2.0 *pt.x)/500.0-1);
g_vLighter.y = -((2.0 *pt.y)/500.0-1);
g_vLighter.z = 0.0f;
if(D3DXVec3Length(&g_vLighter)>1.0f)
D3DXVec3Normalize( &g_vLighter ,&g_vLighter );
else
g_vLighter.z =sqrtf(1.0f - g_vLighter.x *g_vLighter.x -g_vLighter.y* g_vLighter.y); //sqrt是更号
}
void CleanUp()
{
if(g_pVB !=NULL)
g_pVB->Release();
if(g_pD3D!=NULL)
g_pD3D->Release();
if(g_pd3dDevice!=NULL)
g_pd3dDevice->Release();
}
void DrawMesh(D3DXMATRIXA16 * pMat)
{
g_pd3dDevice->SetTransform(D3DTS_WORLD ,pMat);
g_pd3dDevice->SetStreamSource( 0 ,g_pVB , 0, sizeof(CUSTOMVERTEX));
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP , 0 , 2 );
}
DWORD VectortoRGBA(D3DXVECTOR3 *v,FLOAT fHeight)
{
DWORD r = (DWORD)(127.0f *v->x +128.0f);
DWORD g = (DWORD)(127.0f *v->y +128.0f);
DWORD b = (DWORD)(127.0f *v->z +128.0f);
DWORD a = (DWORD)(255.0f *fHeight);
return ((a<<24L)+(r<<16L)+(g<<8L)+(b<<0L));
}
void Render()
{
D3DXMATRIXA16 matWorld;
//后置缓冲和Z缓冲以及背景初始化
g_pd3dDevice->Clear(0 , NULL , D3DCLEAR_TARGET |D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB(0,0,255),1.0f,0);
//创建动画矩阵,设定灯光的位置
Animate();
if(SUCCEEDED(g_pd3dDevice->BeginScene()))
{
g_pd3dDevice->SetTexture(0,g_pTexNormal);
//法线贴图
g_pd3dDevice->SetTexture(1,g_pTexDiffuse);
//壁画贴图
g_pd3dDevice->SetSamplerState(0 ,D3DSAMP_MAGFILTER ,D3DTEXF_LINEAR);
//0号纹理的放大滤镜
g_pd3dDevice->SetSamplerState(1 ,D3DSAMP_MAGFILTER ,D3DTEXF_LINEAR);
//1号纹理的放大滤镜
g_pd3dDevice->SetTextureStageState( 0 , D3DTSS_TEXCOORDINDEX , 0);
//0号纹理使用0号纹理索引
g_pd3dDevice->SetTextureStageState( 1 , D3DTSS_TEXCOORDINDEX , 0);
//1号纹理使用0号纹理索引
DWORD dwFactor = VectortoRGBA(&g_vLighter ,0.0f);
g_pd3dDevice->SetRenderState( D3DRS_TEXTUREFACTOR, dwFactor ); /// 变换为RGB的向量登录为TextureFactor值
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); /// 纹理的RGB和光源向量内积运算
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3 ); /// 运算中使用内积
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR );
g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MULTIPLYADD ); /// 合成壁面贴图纹理和法线贴图后输出
g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
DrawMesh(&g_matAni);
g_pd3dDevice->EndScene();
}
g_pd3dDevice->Present(NULL ,NULL , NULL , NULL );
}
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);
}
INT WINAPI WinMain( HINSTANCE hInst , HINSTANCE ,LPSTR ,INT )
{
WNDCLASSEX wc = { sizeof(WNDCLASSEX) , CS_CLASSDC , MsgProc , 0L ,0L,
GetModuleHandle(NULL), NULL , NULL , NULL , NULL,
L"BasicFrame", NULL};
RegisterClassEx(&wc);
HWND hWnd = CreateWindow( L"BasicFrame", L"LightMappint",WS_OVERLAPPEDWINDOW,
100,100,500,500 ,GetDesktopWindow() ,NULL ,wc.hInstance,NULL);
g_hWnd = hWnd ;
MSG msg;
ZeroMemory (&msg ,sizeof (msg));
if( SUCCEEDED( InitD3D(hWnd ) ) )
if(SUCCEEDED (InitGeometry()))
{
SetupCamera();
ShowWindow(hWnd , SW_SHOWDEFAULT );
UpdateWindow(hWnd);
while(msg.message!=WM_QUIT)
{
if (PeekMessage (&msg,NULL,0U ,0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
Render();
}
UnregisterClass(L"D3D Tutorial",wc.hInstance);
return 0;
}
}