728x90

※ 제 개인 공부이므로 풀 소스 코드는 작성하지 않습니다.

※ 생략 되어 있는 부분이 많습니다.

struct VtxD
 {
   D3DXVECTOR3 p;
   DWORD d;

   VtxD() : p(0, 0, 0), d(0xFFFFFFFF) {}
   VtxD(FLOAT X, FLOAT Y, FLOAT Z, DWORD D = 0XFFFFFFFF) : p(X, Y, Z), d(D) {}

   enum { FVF = (D3DFVF_XYZ | D3DFVF_DIFFUSE), };
 };


 LPDIRECT3DVERTEXSHADER9  m_pVs;    // Vertex Shader
 LPDIRECT3DVERTEXDECLARATION9  m_pFVF;    // Declarator
 LPD3DXCONSTANTTABLE  m_pTbl;

 

 D3DXMATRIX  m_mtWld;   // World Matrix

 

 INT   m_iNvx;    // Vertex Number
 VtxD*  m_pVtx;    // Vertex Buffer

 

정점들의 포지션 p와, 색상값 d로 구성된 정점 구조체, m_iNvx는 구를 형성하는 정점의 갯수이다.

 

*shader.fx*

 

float4x4 m_mtWorld; // World Matrix
float4x4 m_mtView; // View Matrix
float4x4 m_mtProj; // Projection Matrix

 

float4 m_FogColor; // Fog 색상
float m_FogEnd; // Fog 끝 값
float m_FogBgn; // Fog 시작 값

 

// For Vertex Processing Output
struct SvsIn
{
  float3 Pos : POSITION ; // dcl_position0
  float4 Dif : COLOR0  ; // dcl_color0
};

// For Vertex Processing Output
struct SvsOut
{
  float4 Pos : POSITION ; // oPos
  float4 Dif : COLOR0  ; // oD0
};


SvsOut VtxPrc( SvsIn In)
{
  float4 vcOut;
  float FogFactor;

  SvsOut Out = (SvsOut)0;    // Initialized to 0

 

  // 정점의 변환: 월드, 뷰
  vcOut = float4(In.Pos, 1);
  vcOut = mul(vcOut, m_mtWorld);
  vcOut = mul(vcOut, m_mtView);

 

  // 정점의 뷰 변환 과정의 z/(Fog 끝 값 - Fog 시작 값)을 Fog Factor로 저장
  FogFactor = vcOut.z/(m_FogEnd - m_FogBgn);

 

  // 정점의 정규 변환
  vcOut = mul(vcOut, m_mtProj);

 

  // 출력 Diffuse를 정점 Diffuse와 포그 색상과 혼합
  float4 Fog = m_FogColor * FogFactor + In.Dif * (1.0 - FogFactor);

 

  // 혼합 값을 출력 색상으로 지정
  Out.Dif = Fog;
  Out.Pos = vcOut;


  return Out;
}

안개 효과를 나타내는데 있어 여러 방법이 있는듯 하다 그중에서 대표적으로는,

선형 포그(Linear Fog), 지수 포그(Exponential Fog)로 분류 된다.

선형 포그는 전체적으로 선형적으로 변화하고, exp 포그는 급격히 변화하다가 천천히, exp2는 천천히 변화하다가 급격히 변화 하는 것을 볼수 있다.

 

선형 포그와, 지수 포그 계산법엔 각각의 공식이 있고, 필요한 값들 또한 조금씩은 다른것 같다.

 

선형 포그는 포그가 적용되는 시작거리(start), 종료되는 종료거리(end)가 필요하고,

지수 포그는 포그의 밀도를 나타내는 (Density (0 ~ 1.0)) 필요하다.

 

기본적으로 포그는 물체가 멀리 있으면 포그의 색상에 가까워야 하고, 가까울수록 물체의 색상에 가까워야 된다는 개념 하에 FogFactor 라고 하는 거리에 정도에 따라 계산되는 값인 포그 계수를 이용하여 계산 하는듯 하다.

 

현재 셰이더 파일에서 사용하고 있는 방법은 선형 포그이고 빨간색으로 된 부분이 선형 포그 계산 공식 부분이다.

 

지수 포그(exp, exp2) 공식은 다음과 같다.

 

Fog Factor EXP = 1/exp(뷰 변환 후 정점의 z  * Fog Density)

Fog Factor EXP2 = 1/exp( pow(뷰 변환 후 정점의 z  * Fog Density, 2)

 

이러한 과정을 통해 fog값을 구하게 되면 출력 Diffuse에 이 값을 설정해주어 안개 효과가 나타나도록 한다는 것이다.

 

Render()

 

HRESULT hr = 0;
 
m_pdev->SetRenderState(D3DRS_LIGHTING, FALSE);


D3DXMATRIX  mtViw;   // View Matrix
D3DXMATRIX  mtPrj;   // Projection Matrix

 

D3DXCOLOR FogColor(1.0F, 1.0F, 0.2F, 1); // Fog Color
FLOAT  FogEnd = 120.f; // Fog End
FLOAT  FogBgn = 0.f;  // Fog Begin

 

m_pdev->GetTransform(D3DTS_VIEW, &mtViw);
m_pdev->GetTransform(D3DTS_PROJECTION, &mtPrj);
 
// Render
m_pdev->SetVertexShader(m_pVs);
m_pdev->SetVertexDeclaration(m_pFVF);

 

hr = m_pTbl->SetMatrix(m_pdev, "m_mtWorld", &m_mtWld);
hr = m_pTbl->SetMatrix(m_pdev, "m_mtView", &mtViw);
hr = m_pTbl->SetMatrix(m_pdev, "m_mtProj", &mtPrj);
hr = m_pTbl->SetVector(m_pdev, "m_FogColor", (D3DXVECTOR4*)&FogColor);
hr = m_pTbl->SetFloat(m_pdev, "m_FogEnd", FogEnd);
hr = m_pTbl->SetFloat(m_pdev, "m_FogBgn", FogBgn);

 

m_pdev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, m_iNvx - 2, m_pVtx, sizeof(VtxD));

m_pdev->SetVertexShader(NULL);
m_pdev->SetVertexDeclaration(NULL);

 

지금 이 코드에서는 정점의 diffuse 값에 안개 효과를 적용하고 있기 때문에 나중에 텍스처가 적용되면 안개가 재대로 표현되지 못한다. 그래서 안개 표현은 픽셀 셰이더에서 처리하는 것이 좋다고 한다.


728x90
Posted by 정망스
,


맨 위로
홈으로 ▲위로 ▼아래로 ♥댓글쓰기 새로고침