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

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
 +
};
  
- D3DFVF_TEX3 는 텍스쳐 좌표를 3개 쓰겠다는 뜻이다.
+
* 계속
- D3DFVF_TEX0 은 텍스쳐를 쓰지 않겠다는 뜻이다.
+
** VertexDeclaration 은 설정할 필요가 없었다. SetFVF() 만으로 충분하다.
 
+
** 매트릭스 팔레트는 flot4x3 으로 선언해서 POSITION 값과 곱할 때 여분의 w 값을 무시하도록 해야 한다.
- D3DFVF_TEXCOORDSIZE2(index) 는 멀티 텍스쳐를 쓸 때, 각 텍스쳐의
+
** application 에서 4x4 형태의 행렬을 저장해도 문제 없다.
  좌표 차원을 설정할 때 쓰이는 매크로다.
+
** 셰이더 코드는 아래와 같다.
 
+
 
+
- 버텍스 구조체는 해골책을 참조해서 만들었다.
+
 
+
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;
+
}
+
  
 +
// 팔레트
 +
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 를 설정하고
+
* D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR 타입으로 fvf 를 설정하고 스키닝을 구현 할 수 있다.
  스키닝을 구현 할 수 있다.
+
* 핵심은 매트릭스 팔레트를 float4x3 으로 하는게 핵심 이었다. 나머지는 그 동안 삽질한 코드와 동일 하다.
  
struct sVertexNormTexSkin2
+
struct sVertexNormTexSkin2
{
+
{
Vector3 p;
+
Vector3 p;
float weights[4];
+
float weights[4];
DWORD matrixIndices;
+
DWORD matrixIndices;
Vector3 n;
+
Vector3 n;
float u,v;
+
float u,v;
 +
 +
enum {FVF = (D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR |
 +
D3DFVF_NORMAL | D3DFVF_TEX1)};
 +
};
  
enum {FVF = (D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR |
 
D3DFVF_NORMAL | D3DFVF_TEX1)};
 
};
 
 
핵심은 매트릭스 팔레트를 float4x3 으로 하는게 핵심 이었다. 나머지는 그
 
동안 삽질한 코드와 동일 하다.
 
 
 
 +
* 셰이더 코드는 아래와 같다.
  
- 셰이더 코드는 아래와 같다.
+
// -------------------------------------------------------------
 
+
// 1패스:정점셰이더
 
+
// -------------------------------------------------------------
// -------------------------------------------------------------
+
VS_OUTPUT VS_pass0(
// 1패스:정점셰이더
+
float4 Pos : POSITION,          // 모델정점
// -------------------------------------------------------------
+
float3 Normal : NORMAL, // 법선벡터
VS_OUTPUT VS_pass0(
+
float2 Tex : TEXCOORD0, // 텍스쳐 좌표
float4 Pos : POSITION,          // 모델정점
+
float4 Weights : BLENDWEIGHT, // 버텍스 가중치
float3 Normal : NORMAL, // 법선벡터
+
float4 BoneIndices : BLENDINDICES// 본 인덱스 (4개 저장)
float2 Tex : TEXCOORD0, // 텍스쳐 좌표
+
)
float4 Weights : BLENDWEIGHT, // 버텍스 가중치
+
{
float4 BoneIndices : BLENDINDICES// 본 인덱스 (4개 저장)
+
VS_OUTPUT Out = (VS_OUTPUT)0; // 출력데이터
 
+
   
)
+
// 좌표변환
{
+
float4x4 mWVP = mul(mWorld, mVP);
VS_OUTPUT Out = (VS_OUTPUT)0; // 출력데이터
+
   
+
// BoneIndices 는 0~1 사이 값으로 스케일링된 상태이기 때문에  
// 좌표변환
+
// rgba *  255 를 해줘야 어플리케이션에서 저장한 BoneIndex를  
float4x4 mWVP = mul(mWorld, mVP);
+
// 얻어올 수 있다. D3DCOLORtoUBYTE4() 함수가 그 역할을 하게 된다.
 
+
//
// BoneIndices 는 0~1 사이 값으로 스케일링된 상태이기 때문에  
+
// ARGB 형태로 어플리케이션 단에서 저장 한 값이  
// rgba *  255 를 해줘야 어플리케이션에서 저장한 BoneIndex를  
+
// D3DCOLORtoUBYTE4() 함수를 거치면서 BGRA 형태로 바뀐다.
// 얻어올 수 있다. D3DCOLORtoUBYTE4() 함수가 그 역할을 하게 된다.
+
// 저장한 순서대로 Bone Index 를 접근하려면 wzyx 순으로 접근해야 한다.
//
+
int4 IndexVector = D3DCOLORtoUBYTE4(BoneIndices);
// ARGB 형태로 어플리케이션 단에서 저장 한 값이  
+
// D3DCOLORtoUBYTE4() 함수를 거치면서 BGRA 형태로 바뀐다.
+
float3 p = {0,0,0};
// 저장한 순서대로 Bone Index 를 접근하려면 wzyx 순으로 접근해야 한다.
+
float3 n = {0,0,0};
int4 IndexVector = D3DCOLORtoUBYTE4(BoneIndices);
+
 
+
p += mul(Pos, mPalette[ IndexVector.w]) * Weights.x;
float3 p = {0,0,0};
+
p += mul(Pos, mPalette[ IndexVector.z]) * Weights.y;
float3 n = {0,0,0};
+
p += mul(Pos, mPalette[ IndexVector.y]) * Weights.z;
 
+
p += mul(Pos, mPalette[ IndexVector.x]) * Weights.w;
p += mul(Pos, mPalette[ IndexVector.w]) * Weights.x;
+
p += mul(Pos, mPalette[ IndexVector.z]) * Weights.y;
+
n += mul(Normal, mPalette[ IndexVector.w]) * Weights.x;
p += mul(Pos, mPalette[ IndexVector.y]) * Weights.z;
+
n += mul(Normal, mPalette[ IndexVector.z]) * Weights.y;
p += mul(Pos, mPalette[ IndexVector.x]) * Weights.w;
+
n += mul(Normal, mPalette[ IndexVector.y]) * Weights.z;
 
+
n += mul(Normal, mPalette[ IndexVector.x]) * Weights.w;
n += mul(Normal, mPalette[ IndexVector.w]) * Weights.x;
+
n += mul(Normal, mPalette[ IndexVector.z]) * Weights.y;
+
Out.Pos = mul( float4(p,1), mWVP );
n += mul(Normal, mPalette[ IndexVector.y]) * Weights.z;
+
n = normalize(n);
n += mul(Normal, mPalette[ IndexVector.x]) * Weights.w;
+
 
+
// 법선 벡터 계산.
Out.Pos = mul( float4(p,1), mWVP );
+
float3 N = normalize( mul(n, (float3x3)mWIT) ); // 월드 좌표계에서의 법선.
n = normalize(n);
+
 
+
Out.N = N;
// 법선 벡터 계산.
+
Out.Eye = vEyePos - Pos.xyz;
float3 N = normalize( mul(n, (float3x3)mWIT) ); // 월드 좌표계에서의 법선.
+
Out.Tex = Tex;
+
   
Out.N = N;
+
    return Out;
Out.Eye = vEyePos - Pos.xyz;
+
}
Out.Tex = Tex;
+
   
+
    return Out;
+
}
+
  
  
- D3DCOLORtoUBYTE4() 함수 때문에 코드가 좀더 복잡해졌다. 때문에 속도도
+
* D3DCOLORtoUBYTE4() 함수 때문에 코드가 좀더 복잡해졌다. 때문에 속도도 텍스쳐좌표로 스키닝할 때보다 느리다.
  텍스쳐좌표로 스키닝할 때보다 느리다.
+

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



  • 셰이더 스키닝 하면서 삽질 한 부분.
    • 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() 함수 때문에 코드가 좀더 복잡해졌다. 때문에 속도도 텍스쳐좌표로 스키닝할 때보다 느리다.
개인 도구
이름공간

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