昨日不可追, 今日尤可为.勤奋,炽诚,不忘初心
手机淘宝二维码 扫描
或者打开连接:程序设计开发 ,掌声鼓励,欢迎光临.
顶点着色器替代了固定渲染管线中的 变幻 和 光照 阶段.
实现步骤:
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);
}