Shader - 21.11.23

셰이더

고정기능 렌더링 파이프라인

우리가 찍은 정점들은 로컬상에 찍은 정점들이다.

장치객체에 월드, 뷰, 투영 행렬을 보관했다.

실제 정점의 로컬위치에 장치 스스로가 정해진 순서대로 월드,뷰,투영 행렬을 곱해서 화면에 그리는일을 하고있었다.

이래서 고정된 순서로 흘러가는 파이프라인이라고 한것이다.

이제부터 고정기능 렌더링 파이프라인을 사용하지 않는다.

SetTransForm 함수들을 지우고 직접 이 기능들을 작성한다.

직접 연산을 하게되면 여러가지 필요한 연산들을 중간중간 삽입해줄수 있다.

이를 사용자 정의 렌더링 파이프라인이라고 한다.

하지만 이기능은 C++로 작성되어있지않고 하이레벨쉐이더랭귀지로 작성해야한다.

기존의 CPP를 사용할수없는게 문제가된다.

HLSL로 확장자명인 파일로 한다.

이는 컴파일러는 인지못한다(2015부턴 한다)
개발자가 쉐이더를 위해 작성한 파일이구나 하고 인지하는 것 DX는 이파일을 직접 읽어들일수없다.마치 텍스트처럼 읽어서 수행하는 함수를 만들어줘야한다.
쉐이더는 파이프라인을 직접구현한 파일이다.
이를 DX가 텍스트처럼 읽어서 메모리화 할것이다.

ID3DXEffect : 컴파일러에서 메모리화한 쉐이더를 대표하는 구조체 (이를 통해 명령을 내릴수 있다.)

첫단계 . 셰이더 파일 제작.

마치 외부파일처럼 인터페이스를 읽고 메모리화 해야한다.
클라이언트의 97.ShaderFiles추가

클라이언트 -> bin -> ShadeFiles로 폴더생성
VS에서 만들어줄수도있고 탐색기 에서 만들어줘도된다. 확장자명을 hlsl로추가하면된다.

-속성을 잡아줘야한다.

hlsl파일을 솔루션에 추가하면

클라이언트-속성-HLSL 컴파일러가 생성된다.

이상태에서 실행하면 FXC::에러가 발생한다.

FXC는 쉐이더 파일을 의미한다. (확장자명을FX로 해도된다. 차이는 없다)

원래는 두개의 파일을 만들어야한다(vs,ps)버텍스 쉐이더와 픽셀 쉐이더를 따로 하는 게정석이지만
이를 하나의 파일안에 통합해서 작업한다.
이를 이펙트프레임워크FX라고도 부른다.

FXC -> FX를 컴파일해주는 프로그램이 VS에 포함되어있고 VS가 컴파일을 돌려봤더니 진입접 함수가 존재하지않아 에러를 내준것이다.

모든구성
HLSL컴파일러-일반-셰이더 형식-FX
셰이더 모델 - Shader Model2(셰이더 버전을 의미) 2로했지만 컴파일은 3로 한다.문제되지않는다.
(vs,ps 모두 사용해서 큰차이없음)

모델이 올라가면 지오메트리 쉐이더가 추가됨.

HLSL : c랑거의 비슷함 포인터,레퍼런스 없음
완벽한 절차지향, 구조체와 함수로 기능을 만들어나가면된다.

Shader_Rect.hlsl

VS_MAIN()과 PS_MAIN()을 만든다 각각 VS,PS의 진입접 함수를 의미한다.

버텍스셰이더 : 어떤 단계에서 이를 수행하는가를 잘 알고 있어야함. 내가 호출 X 자동으로 호출됨.
DRAW함수 이후에 호출.
어떤 버퍼를 그리기위해 렌더함수를 호출하고 Draw함수를 호출하고 이때부터 화면에 찍어주기위해 버텍스셰이더가 수행됨.

인자의 영향을 많이많는다.
m_ePrimitiveType : 트라이앵글 리스트를 넘겨줬다 버텍스 정점에서 정점 3개를 꺼내서 버텍스셰이더에 그 3개를 하나하나 버텍스셰이더를 수행하면서 인자값을 전달한다.
삼각형하나그릴떄 버텍스 셰이더 3번호출
->버텍스셰이더는 인자로 정점을 받아야한다.

셰이더에서 받아야하는 정점은 VI버퍼에서 만든 정점을 넘겨주면된다.

hlsl도 똑같이 구조체를 만들어줄수있다.

struct VS_IN(받아오기때문에 IN)
{
위치벡터와 UV좌표가 있다.

HLSL에서는 벡터를 float2..3...4로 제공해주고 있다. vector는 float을 4개가지고 있는 형식이다.

행렬타입 - float2x2,float3x3,float4x4,= matrix

}

VS_MAIN에 vTmp를 선언해주자.
대입이나 사칙연산은 기존과 같다.
다른건 xy를 통해 xy에 10을 집어넣는것도 가능하다.
vTmp.xy 는 float2 타입으로 인지가된다.

이 멤버변수는 마치 공용체와같다 rgba로도 접근할수있다.
방향벡터와 위치벡터를 표현하면서 색깔도 표현하기 때문.

vTmp.g == vTmp.y 같은값이다.

버텍스 셰이더의 받아오기 위한 정점을 구성해보자.

struct VS_IN
{
float3 vPosition;
float3 vTexUV;
}

왜 버텍스 텍스가 넘어온다?
백그라운드의 객체를 그릴때 Render()에서 Shader_Rect로 그린다는 코드를 넣어줄것이다.

클라이언트에서 선언한 정점이랑 HLSL에서 선언한 정점이 달라도 받아온다.

이 멤버가 정확히 어떤 의미를 가지는지 명시해줘야한다. 시맨틱

float3 vPosition : POSITION 위치임을 명시
float3 vTexUV : TEXCOORD0 첫번째 UV다.

시멘틱 정보 확인 D3DDECLUSAGE(정점안에 선언될 수 있는 멤버들의 용도를 열거체로 지정)
로 확인할수있다.
뒤에것만 가져오면된다. 뒤에 문자들이 시맨틱.
시맨틱을 보고 가져온다(FVF를 보고)

셰이더 -> 정점버퍼에서 정점을 건져서 그대로 전달해준다. 정점의 포지션은 로컬스페이스에 있다고 할수있다.

각각의 정점을 던져주기때문에 락언락을 해줄필요가없다.

받아온 정점을 변환하고(월뷰투는 무조건해야함) 반환한다.

struct VS_OUT
{
위치의 자료형을 float3에서 4로 변경해야한 다. w값에 뷰스페이스 상의 z값을 보관해야하기때문에 반드시 float4
}

VS_MAIN
{
월드변환,뷰변환,투영행렬곱
실제 투영행렬은 w나누기를했을때
UV좌표는 크게 변환할게 없다.

투영행렬을 곱하고난후 w에 뷰스페이스상의 z값을 저장해둔다. 더미값이 아닌 매우 중요한값.

인덱스버퍼에서 3개를 가져온다.

}

POSITIOIN 시멘틱 데이터에 대해서만 아래의 작업을 수행한다.

우리눈에 보이지 않지만 w값으로 xyzw 모드를 나누는 연산을 수행한다.

뷰포트 변환. (윈도우 좌표로 변환한다.

래스터 라이즈.(픽셀을 생선한다)

struct PS_IN
{
VS_OUT과 동일하다.
래스터라이즈는 정점정보를 기반으로해서 픽셀을 만드는 과정이기 때문에.
}

래스터 라이즈로 생성한 픽셀을 하나하나 픽셀셰이더에 넘겨준다.

800X600이라면 48만번 한다.
때문에 픽셀셰이더에선 루프돌릴 생각은 안하는게 좋다.

/ 최종적으로 화면에 그려야할 픽셀의 색을 결정한다. /

struct PS_OUT
{
float vColor : COLOR0;
}

PS_OUT PS_MAIN(PS_IN in)
{

 PS_OUT Out;
 
 Out.vColor = ;
 
 return Out;

}

버텍스 셰이더 전역변수

월뷰투 행렬을 곱해주기위해선 각 행렬을 받아야하고 이를 전역변수로 선언한다.

각 전역변수를 상수테이블이라고 한다.(하나의 여러개의 데이터를 가지고있는 메모리영역을 테이블이라고 한다.)

셰이더안에 선언한 모든 전역변수는 상수다.
->변경할수 없다.
하지만 이값을 이용해서 다른연산을 하는건 전혀상관없다.

어떻게 값을 정의해주는가?
1.초기화
2.클라이언트의 각 행렬을 받아오고싶다. 언급한 ID3DXEffect를 이용하자 이 구조체에 셰이더에있는 행렬의 값을 저장하는 각종 함수가 있다.
클라이언트에서 Set함수로 어떤 전역변수에 던질지를 명시해서 변수를 넘겨서 클라이언트의 값을 가져올수있다.

딱히 값을 안던지면 초기호된 값으로 사용된다.

로컬페이스의 위치에다가 월뷰투를 곱해주자.

한번에 곱해주기위해 미리 매트릭스를 선언해두자.

matrix matWV,matWVP;

mul함수는 모든 곱하기가 가능한 경우의 곱을 수행해준다.

matWV = mul(g_WorldMatrix,g_ViewMatrix);
matWVP = mul(matWV, g_ProjMatrix);

1X3이랑 4x4를 곱해줄순없다.

float4(In.vPosition, 1.f)로 1x4로 만들어준다

위치벡터니깐 w를 1로 넣어주자.

버텍스 셰이더 끝.(물론 기초적인 기능만)

실행시 에러난다. 아직 이펙트 셰이더를 완성하지않았다.

좋은 웹페이지 즐겨찾기