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;
LPDIRECT3DVERTEXDECLARATION9  m_pFVF;
LPD3DXCONSTANTTABLE  m_pTbl;

VtxD  m_pVtx[3];

 

이번엔 색상값이 들어가므로 DWORD d와, FVF에서 Diffuse가 추가 되었다.

 

*shader.fx*

 

// For Vertex Processing Input
struct SvtxIn
{
     float3 Pos : POSITION;
     float3 Nor : NORMAL;
     float4 Dif : COLOR;
     float2 Tex : TEXCOORD;
};

// For Vertex Processing Output
struct SvtxOut
{
     float4 Pos : POSITION;
     float4 Dif : COLOR;
     float2 Tex : TEXCOORD0;
     float4 Nor : TEXCOORD7; // 법선 벡터는 출력 레지스터가 없으므로 TEXCOORD 이용
};


SvtxOut VtxPrc(SvtxIn In)
{
     SvtxOut Out = (SvtxOut)0;  // Initialized to 0

     Out.Pos = float4(In.Pos, 1);
     Out.Dif = In.Dif;

     return Out;
}

 

이번 셰이더 파일은 구조체를 이용하여 정점의 입력,출력을 처리하고 있다.

VtxPrc 정점 셰이더 함수 안에서 입력받는 포지션과, diffuse 색상값을 출력 데이터로 설정해서 리턴해주고 있다.

 

m_pVtx[0] = VtxD(-1, -1, 0, D3DXCOLOR(1, 0, 0, 1)); //빨강
m_pVtx[1] = VtxD(0, 1, 0, D3DXCOLOR(0, 1, 0, 1)); //초록
m_pVtx[2] = VtxD(1, -1, 0, D3DXCOLOR(0, 0, 1, 1));  //파랑

 

이번엔 픽셀 셰이더에서의 시맨틱을 알아보자.

 

정점 셰이더 시맨틱과 동일하게 데이터의 출처에 대한 식별을 위해 사용한다.

시맨틱 위치는 구조체 멤버 뒤, 함수의 인수 뒤, 함수 뒤 등에 붙여서 사용한다.

 

1. 픽셀 셰이더 입력 시맨틱s

 

COLOR, COLOR[0, 1]: 정점 처리 과정에서 만들어진 Diffuse(0) Specular(1)

TEXCOORD, TEXCOORD[0~7]: 텍스처 좌표

2. 픽셀 셰이더 출력 시맨틱s

 

COLOR[n] 색상 → oC[n], COLOR =COLOR0

TEXCOORD[n]: → 텍스처 좌표

DEPTH[n]:  oDepth[n], DEPTH = DEPTH0

 

*shader.fx*

 

1.

float4x4 mtWorld : register(c0 ); // 전역 변수 mtWorld를 상수 레지스터 c0에 바인딩
float4   vcLight : register(c10); // 전역 변수 vcLight를 상수 레지스터 c10에 바인딩

 

2.
// Pixel Shader Main Function
//float4 PxlPrc(float2 vTex : TEXCOORD0) : COLOR0
//{
// return tex2D(DiffuseSampler, vTex);
//}

 

3.
// Vertex Shader Main Function
void VtxPrc( in float3 iPos : POSITION // dcl_position
   , in float4 iDif : COLOR0 // dcl_color0
   , out float4 oPos : POSITION // oPos
   , out float4 oDif : COLOR0 // oD0
)
{
 oPos = float4(iPos, 1);
 oDif = iDif;
}

 

1. 레지스터를 명시해서 바인딩하면 상수 테이블을 이용하지 않고 디바스의 SetVertexShaderConstantF() 함수를 이용해서 c0, c10 레지스터의 값을 변경할수 있으므로 결과적으로 mtWorld, vcLight를 수정한 것과 동일한 결과가 된다고 한다. (짤 사용하는것 같지는 않음..)

 

2. 사용자가 정의한 픽셀 셰이더 함수, tex2D 함수를 이용한 리턴 값의 타입이 COLOR0 이라고 보면 되는 사용자 정의 함수 사용법.

 

3. 사용자가 정의한 정점 셰이더 함수, 이번엔 함수가 void 형이다 void 형일 경우엔 인수 앞에 in/out 키워드를 넣어서 입 출력을 지정할수 있는 함수 사용법.

(함수의 인수 값을 내부에서 변경 못하게 하려면 uniform 키워드 사용)

 

728x90
Posted by 정망스
,
728x90

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

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

 

 

삼각형을 그리기 위한 셋팅들은 전 글인

 

2. 노란 삼각형을 그려보자..(외부 fx파일, 전역, 지역 변수 핸들 개념 등등..) 와 모두 같다.

 

*shader.fx*

 

// External Variable Semantic
float4x4 m_mtWldViw : WORLDVIEW;
float4 pos: POSITION;


// Struct
struct T
{
    float3 pos : POSITION;
    float3 normal;
};


// User Defined Function Semantic
float4 MyFunc( float3 pos: POSITION) : POSITION
{
     return float4(pos, 1);
}


void VtxPrc( in float3 iPos : POSITION, out float4 oPos : POSITION, out float4 oD0 : COLOR)
{
     float4 posLocal: POSITION; // 지역 변수는 Semantic을 붙일 수 없다.

 

     // 구조체 초기화
     struct T v={ {1,2,3}, {4,5,6}};

 

     // vector 형 초기화
     vector<float, 4> Dif  = float4(1,1,0,1);

 

     // vector 형 갱신
     Dif = vector(1, 0, 1, 1);

 

     // boo형 변수
     bool t=true;

 

     // 사용자 정의 함수 call
     oPos = MyFunc(iPos);
     oD0  = Dif;
}

 

Semantic이라고 하는 것은 변수의 입력과 출력을 확인 또는 지정하거나 데이터의 출처와 역할에 의미를 부여하기 위해 함수나, 변수, 인수 뒤에 선택적으로 붙여서 서술하는 것이라고 한다.

 

방법은 간단하다 변수,인수,함수 끝에 콜론( : )을 붙이고 명시할 시맨틱 이름을 붙이면 된다.

 

위 셰이더 코드에서 빨간색으로 되어있는 posLocal 변수는 지역변수인데 지역 변수에는 시맨틱을 붙일 수 없다고 한다.

 

위 코드 대로 셰이더를 컴파일하게 되면 에러가 난다. 시맨틱을 없애거나 변수를 없애면 정상적으로 보라색 삼각형이 나온다. 

 

1.입력에 사용되는 시맨틱s

 

POSITION[n]: 정점의 위치. POSITION, POSITION0, POSITION1, ….

BLENDWEIGHT[n]: 정점 블렌딩 비중 값

BLENDINDICES[n]: 정점 블렌딩 인덱스 값

NORMAL[n]: 정점 법선 벡터

PSIZE[n]: Point Size

COLOR[n]: 정점 Diffuse(COLOR, COLOR0), Specular(COLOR1)

TEXCOORD[n]: 텍스처 좌표

TANGENT[n]: 정점 접선 벡터

BINORMAL[n]: 정점 종법선 벡터

TESSFACTOR[n]: tessellation factor

2.출력에 사용되는 시맨틱s

 

POSITION: 정점의 출력 위치

PSIZE: Point Size

FOG: 정점 포그 값

COLOR[0,1]: Diffuse, Specular

TEXCOORD[0~7]: 텍스처 좌표

 

D3D에서 사용자가 만든 데이터는 출력 레지스터가 없기 때문에 이 데이터를 픽셀 쉐이더로 전달하기 위한 경우 TEXCOORD 출력 시멘틱을 가장 많이 사용하며 TEXCOORD0, TEXCOORD1은 대부분 사용하기 때문에 보통TEXCOORD7부터 TEXCOORD6, TEXCOORD5, … 등을 이용한다고 한다.

728x90
Posted by 정망스
,
728x90

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

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

 

 

삼각형을 그리기 위한 셋팅들은 전 글인

 

2. 노란 삼각형을 그려보자..(외부 fx파일, 전역, 지역 변수 핸들 개념 등등..) 와 모두 같다.

 

이번엔 uniform이라는 키워드를 알아보기 위한 조금 달라진 shader.fx 파일을 본다.

 

*shader.fx*

 

void VtxPrc( in  float3 iPos: POSITION, out float4 oPos: POSITION, out float4 oD0 : COLOR,

float4 Dif)

{
     Dif = float4(0,1,1,1); //청록색
     oPos = float4(iPos, 1);
     oD0  = Dif;
}

 

Vtxprc 인수중 빨간색으로 되어있는 float4 Dif 부분으로 인해 이 셰이더파일을 컴파일할 때 에러가 발생한다. Vtxprc 함수가 void형 이기 때문에 인자들 앞에 입/출력을 명시적으로 지정해줘야하는데 Dif는 그렇게 작정 되지 않았기 때문이다.

 

uniform float4 Dif 와 같이 앞에 uniform이라는 키워드를 붙여주면 컴파일러가 Dif라는 변수를 상수 레지스터에 저장된 데이터라 여기게 되고 컴파일이 성공하게 된다.

 

uniform 키워드는 지역 변수에는 사용 불가 하고 전역, 함수의 인자에 사용이 가능하다.

 

uniform 키워드는 주로 전역 변수등에 선언하고, varing라는 키워드가 있는데 이 키워드는 위치, 색상, 법선 등의 입력 값에 주로 사용한다고 한다.

 

(예전엔 그런거 같은데 지금 이 글을 쓰는 시점에서는 잘 쓰지 않는 키워드들인듯 하다.)

728x90
Posted by 정망스
,
728x90

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

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

 

 

struct Vtx
 {
      D3DXVECTOR3 p;

      Vtx() : p(0, 0, 0) {}
      Vtx(FLOAT X, FLOAT Y, FLOAT Z) : p(X, Y, Z) {}

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

 

LPDIRECT3DVERTEXSHADER9  m_pVs;

LPDIRECT3DVERTEXDECLARATION9  m_pFVF;

LPD3DXCONSTANTTABLE  m_pTbl; 

D3DXHANDLE  m_hDif;

Vtx   m_pVtx[3];

 

정점 구조체 선언하고, 필요한 객체들 (정점 셰이더, 정점 선언자, 상수 테이블, 핸들) 선언해주고,

삼각형을 그리기위한 정점 3개 선언해준다. 

 

** shader.fx **

 

// 전역 변수
float4 Dif  = float4(0,1,1,1); //파랑색 계열

void VtxPrc( in float3 iPos : POSITION, out float4 oPos: POSITION, out float4 oD0 : COLOR)
{
     // 지역 변수
     float4 Dif  = float4(1,1,0,1); //노랑색 계열

     oPos = float4(iPos, 1);
     oD0  = Dif;
}

shader.fx라고 하는 셰이더 파일을 외부로부터 작성한다. 정점들의 포지션값을 입력받고 새로 포지션 값과, 색상을 지정하여 리턴해준다.

 

HRESULT hr = D3DXCompileShaderFromFile("data/shader.fx", NULL, NULL, "VtxPrc", "vs_1_1", dwFlags, &pShd, &pErr, &m_pTbl );

 

//m_hDif = m_pTbl->GetConstantByName(NULL, "Dif");

 

m_pVtx[0] = Vtx(-1, -1, 0);
m_pVtx[1] = Vtx(0, 1, 0);
m_pVtx[2] = Vtx(1, -1, 0);

 

D3DXCompileShaderFromFile을 이용하여 외부에서 셰이더파일을 불러와 컴파일을 해준다.

상수 테이블(m_pTbl)로부터 GetConstantByName을 이용하여 셰이더 파일 안에있는 Dif의 핸들을 얻어온다.

 

m_pdev->SetRenderState(D3DRS_LIGHTING, FALSE);


m_pdev->SetVertexShader(m_pVs);
m_pdev->SetVertexDeclaration(m_pFVF);


D3DXCOLOR color(1, 0, 1, 1); //보라색 계열


 

// 이름에 의한 상수 레지스터 설정
m_pTbl->SetVector(m_pdev, "Dif", (D3DXVECTOR4*)&color);

 

// 핸들에 의한 상수 레지스터 설정
m_pTbl->SetVector(m_pdev, m_hDif, (D3DXVECTOR4*)&color);

 

m_pdev->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 1, m_pVtx, sizeof(Vtx));

 

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

 

SetVertexShader을 이용하여 셰이더를 사용한다 알리므로 shader.fx 파일안에 있는 VtxPrc 함수안의 지역변수 Dif값으로 인해 삼각형이 노랑색으로 나오게 된다. 만약 지역변수 Dif값을 삭제하면,

 

D3DXCOLOR color(1, 0, 1, 1); 이 부분으로 인해 전역변수 Dif값이 보라색으로 바뀌게 되고 삼각형이 보라색으로 나오게 된다.

 

셰이더안의 값을 변경하는 방법으로는 

1.

m_pTbl->SetVector(m_pdev, "Dif", (D3DXVECTOR4*)&color);

 

와 같이 "Dif"처럼 직접 이름을 지정해주는 방법.

 

2.

m_hDif = m_pTbl->GetConstantByName(NULL, "Dif");

m_pTbl->SetVector(m_pdev, m_hDif, (D3DXVECTOR4*)&color);

 

와 같이 GetConstantByName을 이용하여 상수 테이블로부터 핸들을 얻어오는 방법이 있다.

 

상수 테이블에는 셰이더파일 안에 들어있는 변수들의 정보가 들어있다.

728x90
Posted by 정망스
,
728x90

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

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

 

 

struct Vtx
 {
      D3DXVECTOR3 p;

      Vtx() : p(0, 0, 0) {}
      Vtx(FLOAT X, FLOAT Y, FLOAT Z) : p(X, Y, Z) {}

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

 

LPDIRECT3DVERTEXSHADER9  m_pVs;
LPDIRECT3DVERTEXDECLARATION9  m_pFVF;

Vtx   m_pVtx[3];

 

정점 구조체 선언해주고.. 필요한것들 정점쉐이더 객체와, 정점 선언자 객체, 그리고 삼각형 그릴꺼니까 정점 3개 만들어 준다.

 

const char sHlsl[] =
  "float4 VtxPrc(float3 Pos : POSITION) : POSITION  \n"
  "{                                                               \n"
  "    return float4(Pos, 1);                                  \n"
  "}                                                               \n"
  "                                                                \n"
  ;

 

HRESULT hr = D3DXCompileShader(sHlsl, iLen, NULL, NULL , "VtxPrc" , "vs_1_1"  , dwFlags, &pShd , &pErr, NULL);

 

m_pVtx[0] = Vtx(-1, -1, 0);
m_pVtx[1] = Vtx(0, 1, 0);
m_pVtx[2] = Vtx(1, -1, 0);

 

Create() 함수 안에서,

 

sHlsl 이라고 하는 우리가 적용할 셰이더를 작성해준다. 여기선 포지션 값만을 설정한다.

D3DXCompileShader을 이용해서 셰이더 컴파일을 해주고, 정점 좌표 3개 작성해준다.

 

m_pdev->SetRenderState(D3DRS_LIGHTING, FALSE);


m_pdev->SetVertexShader(m_pVs);
m_pdev->SetVertexDeclaration(m_pFVF);


m_pdev->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 1, m_pVtx, sizeof(Vtx));

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

 

Render() 함수 안에서,

 

랜더링상태 설정, 셰이더를 사용하겟다라고 설정과, 정점선언자 설정을해주고 그린다.

다 그리고 나면 null로 해제 시켜주고 고정 파이프라인으로 돌아오게 한다.

728x90
Posted by 정망스
,


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