D3D9學習筆記(九) effect (hlsl)

effect其實整合了shaderrender state的控制兩大部分內容

9.1 effect文件基本框架

part1 shader state包括全局變量 shader數據結構定義,shader的實現

part2 texture and sampler state,這個通常是全局變量,用於shader中,通常要定義在shader的實現之前

part3 其他的render state設置,寫在techniquepass裏,這纔是effect文件的主入口

effet中任何一個變量後面都可以接一個語意:XXX

1.可以使用的變量類型

Data  Buffer Scalar Vector Matrix Sample Shader Texture Struct UserDefined

 

9.1.1參數類型

hlsl中使用的參數有兩種:Uniform varying

Uniform存儲在常量緩存中的,是對shader的每一次調用值都是一樣的,可以在D3D中訪問的 前面可以加uniform(可不加),通常是全局的

varying只對一次調用起作用的,是來自vertext stream中的,通常要有語意的修飾,通產是寫在shader的輸入輸出參數裏的

9.1.2 sampler紋理採樣器

要包含三個信息

  • A texture :紋理物體(tex0 tex1 tex2...NULL)
  • A sampler (with sampler state)
  • A sampling instruction

例如定義這樣一個sampler

 
sampler s = sampler_state 
{ 
  texture = NULL; 
  mipfilter = LINEAR; 
};
 
就可以在shader中使用
float2 sample_2D(float2 tex : TEXCOORD0) : COLOR
{
  return tex2D(s, tex);
}
來採樣紋理

9.1.3 shader的函數體

函數通常要包含這樣幾部分:

  • A return type
  • A function name
  • An argument list (optional)
  • An output semantic (optional)
  • An annotation (optional)
float4 VertexShader_Tutorial_1(float4 inPos : POSITION ) : POSITION
{
   ...
}
struct VS_OUTPUT
{
    float4  vPosition        : POSITION;
    float4  vDiffuse         : COLOR;
}; 
 
VS_OUTPUT VertexShader_Tutorial_1(float4 inPos : POSITION )
{
   ...
}

 

9.2D3D9中使用effect

1.首先從effect file創建effect(編譯),使用函數

D3DXCreateEffectFromFile( 
        pd3dDevice, 
        str, 
        NULL, // CONST D3DXMACRO* pDefines,
        NULL, // LPD3DXINCLUDE pInclude,
        dwShaderFlags, 
               NULL, // LPD3DXEFFECTPOOL pPool,
        &g_pEffect, 
        NULL );
 

dwShaderFlags

    • Skipping validation, 如果已知這是沒有問題的 那麼就跳過檢查
    • Skipping optimization 有時開啓優化會導致debug 困難,就可以跳過優化
    • Requesting debug information to be included in the shader so it can be debugged.

這個函數的調用實際上是在從文件編譯出一個effect

你還可以利用工具fxc.exe離線的編譯出一個effect,他會直接編出一個彙編的shader指令,這樣在程序中就不用編譯了。發佈產品時這樣做應該更好。

 

 2.調用一個effectrender

ID3DXEffect::Begin set technique

ID3DXEffect::BeginPass set pass

ID3DXEffect::CommitChanges提交對當前pass的各種參數修改,要在draw之前調用

ID3DXEffect::EndPass

ID3DXEffect::End

一個典型調用

3  effect 的參數設置(指effect文件中定義的全局變量(uniform))

設置與獲取

m_pEffect->SetValue

m_pEffect->GetValue

函數的第一個參數都是變量的名字

 
不同的effect 可以共享參數:如果一個effect變量定義爲shared,並且多個effect創建的時候使用同一個pool(D3DXCreateEffectFromFile的第六個參數)就可以共享這個參數。
 
創建參數block,可以像使用render state的block那樣 創建parament state,這時是通過創建Parameter Blocks的方式。把effect 的參數設置操作寫在
m_pEffect->BeginParameterBlock();與m_pEffect->EndParameterBlock();
之間。得到的block可以用在effect 上

 

用戶註釋

用戶可以在effect pass 或者某個變量上附加一個用戶的註釋。他其實就是一個stringnumeric格式的變量。格式

 
texture Tex0 < string name = "tiger.bmp"; >;意味着給tex0 附加一個註釋,告訴這個texture使用的紋理文件的路徑。註釋可以理解爲用戶在D3D層面去擴充effect 文件的定義。

ID3DXBaseEffect::GetAnnotation orID3DXBaseEffect::GetAnnotationByName可以獲取

 

5 preshader技術

對於shader中的常量計算,D3D會將其提取出來,在shader執行之前,先由CPU計算,這樣會提高GPU的效率,防止每個頂點或pixcel都重複這個同樣的運算,使不使用preshader可一在編譯時指定優化的flag,關閉使用參數D3DXSHADER_NO_PRESHADER。所以基於這個技術我們可以在shader中做常量矩陣運算,不用擔心這個運算會在每個頂點處做一次。

9.3 語法備忘

9.3.1 語義

VS:

輸入:

BINORMAL[n] Binormal float4
BLENDINDICES[n] Blend indices uint
BLENDWEIGHT[n] Blend weights float
COLOR[n] Diffuse and specular color float4
NORMAL[n] Normal vector float4
POSITION[n] Vertex position in object space. float4
POSITIONT Transformed vertex position. float4
PSIZE[n] Point size float
TANGENT[n] Tangent float4
TEXCOORD[n]

輸出

COLOR[n] Diffuse or specular color float4
FOG Vertex fog float
POSITION[n] Position of a vertex in homogenous space. Compute position in screen-space by dividing (x,y,z) by w. Every vertex shader must write out a parameter with this semantic. float4
PSIZE Point size float
TESSFACTOR[n] Tessellation factor float
TEXCOORD[n] Texture coordinates float4

 

PS

輸入:

COLOR[n] Diffuse or specular color. float4
TEXCOORD[n] Texture coordinates float4
VFACE Floating-point scalar that indicates a back-facing primitive. A negative value faces backwards, while a positive value faces the camera. float
VPOS The pixel location (x,y) in screen space. To convert a Direct3D 9 shader (that uses this semantic) to a Direct3D 10 shader, seeDirect3D 9 VPOS and Direct3D 10 SV_Position) float2

輸出:

COLOR[n] Output color float4
DEPTH[n] Output depth float

 9.3.2數據的訪問方式

vector

bool bVector = false;int1 iVector = 1;float3 fVector = { 0.2f, 0.3f, 0.4f };double4 dVector = { 0.2, 0.3, 0.4, 0.5 };

vector <bool, 1> bVector = false;vector <int, 1> iVector = 1;vector <float, 3> fVector = { 0.2f, 0.3f, 0.4f };vector <double, 4> dVector = { 0.2, 0.3, 0.4, 0.5 };


// Given
float4 pos = float4(0,0,2,1);

pos.z    // value is 2
pos.b    // value is 2

 

 


// Given
float4 pos = float4(0,0,2,1);
float2 temp;

temp = pos.xy  // valid
temp = pos.rg  // valid

temp = pos.xg  // NOT VALID because the position and color sets were used.

 


float4 pos = float4(0,0,2,1);
float4 f_4D;
f_4D    = pos;     // write four components          

f_4D.xz = pos.xz;  // write two components        
f_4D.zx = pos.xz;  // change the write order

f_4D.xzyw = pos.w; // write one component to more than one component
f_4D.wzyx = pos;

 

matrix

A matrix can be initialized when it is declared:


float2x2 fMatrix = { 0.0f, 0.1, // row 1
                     2.1f, 2.2f // row 2
                   };   

Or, the matrix type can be used to make the same declarations:


matrix <float, 2, 2> fMatrix = { 0.0f, 0.1, // row 1
                                 2.1f, 2.2f // row 2
                               };

 

  • The zero-based row-column position:
    • _m00, _m01, _m02, _m03
    • _m10, _m11, _m12, _m13
    • _m20, _m21, _m22, _m23
    • _m30, _m31, _m32, _m33
  • The one-based row-column position:
    • _11, _12, _13, _14
    • _21, _22, _23, _24
    • _31, _32, _33, _34
    • _41, _42, _43, _44
    • [0][0], [0][1], [0][2], [0][3]
    • [1][0], [1][1], [1][2], [1][3]
    • [2][0], [2][1], [2][2], [2][3]
    • [3][0], [3][1], [3][2], [3][3]

However, array accessing can read a multi-component vector.


float2 temp;
float2x2 fMatrix;
temp = fMatrix[0] // read the first row

 

Just like vectors, naming sets can use one or more components from either naming set.


// Given
float2x2 fMatrix = { 1.0f, 1.1f, // row 1
                     2.0f, 2.1f  // row 2
                   };
float2 temp;

temp = fMatrix._m00_m11 // valid
temp = fMatrix._m11_m00 // valid
temp = fMatrix._11_22   // valid
temp = fMatrix._22_11   // valid

 

As with vectors, reading more than one matrix component is called swizzling. More than one component can be assigned, assuming only one name space is used. These are all valid assignments:


// Given these variables
float4x4 worldMatrix = float4( {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} );
float4x4 tempMatrix;

tempMatrix._m00_m11 = worldMatrix._m00_m11; // multiple components
tempMatrix._m00_m11 = worldMatrix.m13_m23;

tempMatrix._11_22_33 = worldMatrix._11_22_33; // any order on swizzles
tempMatrix._11_22_33 = worldMatrix._24_23_22;

 

 

 9.3.3 定義shader類型

PixelShader = compile ShaderTarget ShaderFunction(...);

VertexShader = compile ShaderTarget ShaderFunction(...);

ShaderTarget :shade_model 例如vs_2_0

...就是shader中的uniform參數

9.4編譯shader

在VS(2012以下)中直接DEBUG是不能發現shader 的語法錯誤的,這需要使用fxc工具

常用語法是

 

fxc /T fx_2_0 file.fx

Will compile the entire file with vs and ps 2.0.

fxc /T ps_2_0 /E PixelShaderFunction file.fx

Will compile PixelShaderFunction with ps 2.0.

9.5調試

可以使用dx sdk中帶的pix

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