"스키닝 셰이더"의 두 판 사이의 차이

jjuiddong
이동: 둘러보기, 찾기
(새 문서: * FVF 메모리 구조. ** http://msdn.microsoft.com/en-us/library/windows/hardware/ff552826(v=vs.85).aspx - 셰이더 스키닝 하면서 삽질 한 부분. - D3DFVF_TEX3 는...)

2014년 7월 27일 (일) 20:33 판



- 셰이더 스키닝 하면서 삽질 한 부분.

- D3DFVF_TEX3 는 텍스쳐 좌표를 3개 쓰겠다는 뜻이다. - D3DFVF_TEX0 은 텍스쳐를 쓰지 않겠다는 뜻이다.

- D3DFVF_TEXCOORDSIZE2(index) 는 멀티 텍스쳐를 쓸 때, 각 텍스쳐의 좌표 차원을 설정할 때 쓰이는 매크로다.


- 버텍스 구조체는 해골책을 참조해서 만들었다.

struct sVertexNormTexSkin { Vector3 p; Vector3 n; float u,v; float weights[4]; float matrixIndices[4];

enum {FVF = (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE2(0)| // texture D3DFVF_TEXCOORDSIZE4(1)| // blend weight D3DFVF_TEXCOORDSIZE4(2)) }; // blend indices };


- VertexDeclaration 은 설정할 필요가 없었다. SetFVF() 만으로 충분하다.

- 매트릭스 팔레트는 flot4x3 으로 선언해서 POSITION 값과 곱할 때 여분의 w 값을 무시하도록 해야 한다.

- application 에서 4x4 형태의 행렬을 저장해도 문제 없다.


- 셰이더 코드는 아래와 같다.

// ------------------------------------------------------------- // 1패스:정점셰이더 // ------------------------------------------------------------- VS_OUTPUT VS_pass0( float4 Pos : POSITION, // 모델정점 float3 Normal : NORMAL, // 법선벡터 float2 Tex : TEXCOORD0, // 텍스쳐 좌표 float4 Weights : TEXCOORD1, // 버텍스 가중치 float4 BoneIndices : TEXCOORD2 // 본 인덱스 (4개 저장) ) { VS_OUTPUT Out = (VS_OUTPUT)0; // 출력데이터

// 좌표변환 float4x4 mWVP = mul(mWorld, mVP);

float3 p = {0,0,0}; float3 n = {0,0,0};

p += mul(Pos, mPalette[ BoneIndices.x]) * Weights.x; p += mul(Pos, mPalette[ BoneIndices.y]) * Weights.y; p += mul(Pos, mPalette[ BoneIndices.z]) * Weights.z; p += mul(Pos, mPalette[ BoneIndices.w]) * Weights.w;

n += mul(Normal, mPalette[ BoneIndices.x]) * Weights.x; n += mul(Normal, mPalette[ BoneIndices.y]) * Weights.y; n += mul(Normal, mPalette[ BoneIndices.z]) * Weights.z; n += mul(Normal, mPalette[ BoneIndices.w]) * Weights.w;

Out.Pos = mul( float4(p,1), mWVP ); n = normalize(n);

// 법선 벡터 계산. float3 N = normalize( mul(n, (float3x3)mWIT) ); // 월드 좌표계에서의 법선.

Out.N = N; Out.Eye = vEyePos - Pos.xyz; Out.Tex = Tex;

   return Out;

}


//////////////////////////////////////////////////////////////////////////////////////

- D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR 타입으로 fvf 를 설정하고 스키닝을 구현 할 수 있다.

struct sVertexNormTexSkin2 { Vector3 p; float weights[4]; DWORD matrixIndices; Vector3 n; float u,v;

enum {FVF = (D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_NORMAL | D3DFVF_TEX1)}; };

핵심은 매트릭스 팔레트를 float4x3 으로 하는게 핵심 이었다. 나머지는 그 동안 삽질한 코드와 동일 하다.


- 셰이더 코드는 아래와 같다.


// ------------------------------------------------------------- // 1패스:정점셰이더 // ------------------------------------------------------------- VS_OUTPUT VS_pass0( float4 Pos : POSITION, // 모델정점 float3 Normal : NORMAL, // 법선벡터 float2 Tex : TEXCOORD0, // 텍스쳐 좌표 float4 Weights : BLENDWEIGHT, // 버텍스 가중치 float4 BoneIndices : BLENDINDICES// 본 인덱스 (4개 저장)

) { VS_OUTPUT Out = (VS_OUTPUT)0; // 출력데이터

// 좌표변환 float4x4 mWVP = mul(mWorld, mVP);

// BoneIndices 는 0~1 사이 값으로 스케일링된 상태이기 때문에 // rgba * 255 를 해줘야 어플리케이션에서 저장한 BoneIndex를 // 얻어올 수 있다. D3DCOLORtoUBYTE4() 함수가 그 역할을 하게 된다. // // ARGB 형태로 어플리케이션 단에서 저장 한 값이 // D3DCOLORtoUBYTE4() 함수를 거치면서 BGRA 형태로 바뀐다. // 저장한 순서대로 Bone Index 를 접근하려면 wzyx 순으로 접근해야 한다. int4 IndexVector = D3DCOLORtoUBYTE4(BoneIndices);

float3 p = {0,0,0}; float3 n = {0,0,0};

p += mul(Pos, mPalette[ IndexVector.w]) * Weights.x; p += mul(Pos, mPalette[ IndexVector.z]) * Weights.y; p += mul(Pos, mPalette[ IndexVector.y]) * Weights.z; p += mul(Pos, mPalette[ IndexVector.x]) * Weights.w;

n += mul(Normal, mPalette[ IndexVector.w]) * Weights.x; n += mul(Normal, mPalette[ IndexVector.z]) * Weights.y; n += mul(Normal, mPalette[ IndexVector.y]) * Weights.z; n += mul(Normal, mPalette[ IndexVector.x]) * Weights.w;

Out.Pos = mul( float4(p,1), mWVP ); n = normalize(n);

// 법선 벡터 계산. float3 N = normalize( mul(n, (float3x3)mWIT) ); // 월드 좌표계에서의 법선.

Out.N = N; Out.Eye = vEyePos - Pos.xyz; Out.Tex = Tex;

   return Out;

}


- D3DCOLORtoUBYTE4() 함수 때문에 코드가 좀더 복잡해졌다. 때문에 속도도 텍스쳐좌표로 스키닝할 때보다 느리다.

개인 도구
이름공간

변수
행위
둘러보기
도구모음