HLSL頂點着色器

頂點着色器替代了固定渲染管線中的 變幻 光照 階段.

實現步驟:

1.在文本文件裏編寫頂點着色器代碼(HLSL語言)

2.編譯着色器代碼(D3DXCompileShaderFromFile)

3.創建頂點着色器(CreateVertexShader)

4.獲取HLSL語言中變量句柄(GetConstantByName)

5.根據句柄給HLSL語言中的變量傳值(ID3DXConstTable->Setxxx)??

在文本文件裏寫頂點着色器代碼:

//----------------------------------begin VertexShader.txt--------------------------------------------
//世界-觀察 矩陣
matrix g_world_view;
//世界-觀察-投影 矩陣
matrix g_world_view_proj;

//顏色
vector g_color;
//光線方向
vector g_dir_to_light;

//輸入
struct VTIN
{
 vector pos :POSITION; //輸入:位置
 vector normal : NORMAL; //輸入:法線
};

//輸出
struct VTOUT
{
 vector pos : POSITION; //輸出:位置
 float2 uv : TEXCOORD; //輸出:紋理座標
 vector diffuse : COLOR; //輸出:顏色
};

//函數入口
VTOUT main(VTIN input)
{
 //初始化輸出結構
 VTOUT output = (VTOUT)0;
 
 //pos由建模空間-世界空間-觀察空間-投影空間 變幻
 output.pos = mul(input.pos, g_world_view_proj);
 
 //轉換光線和法線到觀察空間,設置w分量爲0
 //確保沒有縮放變幻,因爲縮放會弄亂法線的方向
 g_dir_to_light.w = 0.0f;
 input.normal.w = 0.0f;
 g_dir_to_light = mul(g_dir_to_light, g_world_view);
 input.normal   = mul(input.normal,   g_world_view);
 
 //計算出uv
 //其實只要用到紋理的x(即u)就行了
 float u = dot(g_dir_to_light, input.normal);
 //如果u<0.0f,說明角度大於90°,接受不到光線,so
 if(u < 0.0f)
 {
  u = 0.0f;
 }
 float v = 0.5f; //紋理圖片y軸像素(0.0f~1.0f)
 
 output.uv.x = u;
 output.uv.y = v;
 
 output.diffuse = g_color; 
 
 return output;
}
//----------------------------------end VertexShader.txt--------------------------------------------
<pre class="cpp" name="code">//vs中程序代碼:

#define MESH_TEAPOT		0
#define MESH_SPHERE		1
#define MESH_TORUS		2
#define MESH_CYLINDER	3
	//-----------頂點着色器相關的變量------------------
	IDirect3DVertexShader9* m_VertexShader;
	ID3DXConstantTable*		m_ConstantTable;
	IDirect3DTexture9*		m_ShadeTexture;

	ID3DXMesh*				m_Meshes[4];
	D3DXMATRIX				m_WorldMatrices[4];
	D3DXVECTOR4				m_MeshColors[4];

	D3DXMATRIX				m_ProjMatrix;

	D3DXHANDLE				m_WorldViewHandle;
	D3DXHANDLE				m_WorldViewProjHandle;
	D3DXHANDLE				m_ColorHandle;
	D3DXHANDLE				m_DirLightHandle;
	
	
	//setup: main函數中調用一次
	void Setup()
	{
		//創建模型們: 茶壺 圓球 圓環 圓桶
		D3DXCreateTeapot(D3DDevice, &m_Meshes[MESH_TEAPOT], NULL);
		D3DXCreateSphere(D3DDevice, 1.0f, 20, 20, &m_Meshes[MESH_SPHERE], NULL);
		D3DXCreateTorus(D3DDevice, 0.5f, 1.0f, 20, 20, &m_Meshes[MESH_TORUS], NULL);
		D3DXCreateCylinder(D3DDevice, 0.5f, 0.5f, 2.0f, 20, 20, &m_Meshes[MESH_CYLINDER], NULL);
		
		//模型們的在世界中的矩陣:
		D3DXMatrixTranslation(&m_WorldMatrices[MESH_TEAPOT], 0.0f, 2.0f, 0.0f);
		D3DXMatrixTranslation(&m_WorldMatrices[MESH_SPHERE], 0.0f, -2.0f, 0.0f);
		D3DXMatrixTranslation(&m_WorldMatrices[MESH_TORUS], -3.0f, 0.0f, 0.0f);
		D3DXMatrixTranslation(&m_WorldMatrices[MESH_CYLINDER], 3.0f, 0.0f, 0.0f);
		//模型們的顏色:
		m_MeshColors[MESH_TEAPOT] = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
		m_MeshColors[MESH_SPHERE] = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
		m_MeshColors[MESH_TORUS] = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
		m_MeshColors[MESH_CYLINDER] = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);

		//編譯着色器:
		ID3DXBuffer*	shader_buffer;
		ID3DXBuffer*	error_buffer;
		HRESULT hr = D3DXCompileShaderFromFile(L"D:\\VertexShader.txt", NULL, NULL, "main", "vs_1_1",
			D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY,
			&shader_buffer, &error_buffer, &m_ConstantTable);
		// 輸出錯誤信息:
		if (error_buffer)
		{
			string str = (char*)error_buffer->GetBufferPointer();
			MessageBox(NULL, Common::StringToWString(str).c_str(), L"ERROR", MB_OK);
			//safe_release<ID3DXBuffer*>(error_buffer);
		}
		if (FAILED(hr))
		{
			MessageBox(NULL, L"D3DXCreateEffectFromFile() - FAILED", L"ERROR", MB_OK);
		}
		//創建頂點着色器
		hr = D3DDevice()CreateVertexShader((DWORD*)shader_buffer->GetBufferPointer(), &m_VertexShader);
		if (FAILED(hr))
		{
			MessageBox(NULL, L"CreateVertexShader - FAILED", L"ERROR", MB_OK);
		}
		//釋放
		//safe_release<ID3DXBuffer*>(shader_buffer);

		//加載紋理:
		D3DXCreateTextureFromFile(D3DDevice, L"D:\\pic1.png", &m_ShadeTexture);
		//設置狀態屬性:
		D3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
		D3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
		D3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);//禁用過濾

		//獲取常量句柄
		m_WorldViewHandle = m_ConstantTable->GetConstantByName(NULL, "g_world_view");
		m_WorldViewProjHandle = m_ConstantTable->GetConstantByName(NULL, "g_world_view_proj");
		m_ColorHandle = m_ConstantTable->GetConstantByName(NULL, "g_color");
		m_DirLightHandle = m_ConstantTable->GetConstantByName(NULL, "g_dir_to_light");

		// set shader constants
		D3DXVECTOR4 dir_to_light(-0.57f, 0.57f, -0.57f, 0.0f);
		m_ConstantTable->SetVector(D3DDevice, m_DirLightHandle, &dir_to_light);
		m_ConstantTable->SetDefaults(D3DDevice);

		//設置投影矩陣
		RECT rt;
		GetClientRect(hwnd, &rt);
		D3DXMatrixPerspectiveFovLH(&m_ProjMatrix, D3DX_PI / 4.0f, (float)rt.right / rt.bottom, 1.0f, 1000.0f);
	}
	
//display: 在消息循環中調用,時時更新
	void Display(float timeDelta)
	{
		static float angle = (3.0f * D3DX_PI) / 2.0f;
		static float height = 5.0f;

		if (GetAsyncKeyState(VK_LEFT) & 0x8000f)
			angle -= 0.5f * timeDelta;

		if (GetAsyncKeyState(VK_RIGHT) & 0x8000f)
			angle += 0.5f * timeDelta;

		if (GetAsyncKeyState(VK_UP) & 0x8000f)
			height += 5.0f * timeDelta;

		if (GetAsyncKeyState(VK_DOWN) & 0x8000f)
			height -= 5.0f * timeDelta;

		D3DXVECTOR3 position(cosf(angle) * 7.0f, height, sinf(angle) * 7.0f);
		D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
		D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);

		D3DXMATRIX view_matrix;
		D3DXMatrixLookAtLH(&view_matrix, &position, &target, &up);

		// render now
		D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
		D3DDevice->BeginScene();
		D3DDevice->SetVertexShader(m_VertexShader);
		D3DDevice->SetTexture(0, m_ShadeTexture);

		D3DXMATRIX world_view, world_view_proj;

		for (int i = 0; i < 4; i++)
		{
			world_view = m_WorldMatrices[i] * view_matrix;
			world_view_proj = m_WorldMatrices[i] * view_matrix * m_ProjMatrix;

			m_ConstantTable->SetMatrix(D3DDevice, m_WorldViewHandle, &world_view);
			m_ConstantTable->SetMatrix(D3DDevice, m_WorldViewProjHandle, &world_view_proj);
			m_ConstantTable->SetVector(D3DDevice, m_ColorHandle, &m_MeshColors[i]);

			m_Meshes[i]->DrawSubset(0);
		}
		D3DDevice()->EndScene();
		D3DDevice()->Present(NULL, NULL, NULL, NULL);
	}


代碼來自博客:天行健君子當自強不息.

效果圖:當紋理圖爲效果圖爲

當紋理圖爲效果圖爲:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章