"스키닝 셰이더"의 두 판 사이의 차이
jjuiddong
(새 문서: * FVF 메모리 구조. ** http://msdn.microsoft.com/en-us/library/windows/hardware/ff552826(v=vs.85).aspx - 셰이더 스키닝 하면서 삽질 한 부분. - D3DFVF_TEX3 는...) |
|||
1번째 줄: | 1번째 줄: | ||
+ | * 스키닝에 관련된 소스는 아래 URL을 통해 가져올 수 있다. | ||
+ | ** https://github.com/sgajaejung/Game | ||
* FVF 메모리 구조. | * FVF 메모리 구조. | ||
6번째 줄: | 8번째 줄: | ||
+ | * 셰이더 스키닝 하면서 삽질 한 부분. | ||
+ | ** 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 형태의 행렬을 저장해도 문제 없다. | |
− | + | ** 셰이더 코드는 아래와 같다. | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
+ | // 팔레트 | ||
+ | float4x3 mPalette[ 64]; | ||
+ | |||
+ | // ------------------------------------------------------------- | ||
+ | // 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 를 설정하고 스키닝을 구현 할 수 있다. | |
− | + | * 핵심은 매트릭스 팔레트를 float4x3 으로 하는게 핵심 이었다. 나머지는 그 동안 삽질한 코드와 동일 하다. | |
− | + | 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)}; | ||
+ | }; | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | * 셰이더 코드는 아래와 같다. | ||
− | + | // ------------------------------------------------------------- | |
− | + | // 1패스:정점셰이더 | |
− | + | // ------------------------------------------------------------- | |
− | // ------------------------------------------------------------- | + | VS_OUTPUT VS_pass0( |
− | // 1패스:정점셰이더 | + | float4 Pos : POSITION, // 모델정점 |
− | // ------------------------------------------------------------- | + | float3 Normal : NORMAL, // 법선벡터 |
− | VS_OUTPUT VS_pass0( | + | 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() 함수 때문에 코드가 좀더 복잡해졌다. 때문에 속도도 텍스쳐좌표로 스키닝할 때보다 느리다. | |
− | + |
2014년 7월 27일 (일) 20:41 판
- 스키닝에 관련된 소스는 아래 URL을 통해 가져올 수 있다.
- 셰이더 스키닝 하면서 삽질 한 부분.
- 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 형태의 행렬을 저장해도 문제 없다.
- 셰이더 코드는 아래와 같다.
// 팔레트 float4x3 mPalette[ 64]; // ------------------------------------------------------------- // 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 를 설정하고 스키닝을 구현 할 수 있다.
- 핵심은 매트릭스 팔레트를 float4x3 으로 하는게 핵심 이었다. 나머지는 그 동안 삽질한 코드와 동일 하다.
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)}; };
- 셰이더 코드는 아래와 같다.
// ------------------------------------------------------------- // 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() 함수 때문에 코드가 좀더 복잡해졌다. 때문에 속도도 텍스쳐좌표로 스키닝할 때보다 느리다.