픽셀 셰이더
픽셀 셰이더는 최종적으로 출력되는 픽셀의 색을 결정한다.
-TEXCOORD뒤의 넘버링
정점은 위치좌표는 하나를 가지지만
UV좌표는 8개까지 가져올수있기때문에
다수의 UV좌표를 사용할때 가져오기위한 넘버링이다.
쉐이더에서 받아오는 정점의 정보는 받아오는 버퍼의 정점 정보와 항상 같아야한다.
FVF의 D3DFVF_TEX는 몇개의 UV좌표를 쓰는가를 의미한다.
PS_OUT에서 정의한 COLOR값(렌더 타켓을 의미한다 장치에 연결되어있는 0번째 렌더타켓에 그린다.)은 밖으로 내보내는 값이다 엄밀히 말하면 외부랑 값을 맞춰봐야하는건 VS_IN밖에없다.
렌더타켓 : 그릴수 있는 텍스처, 장치가 생성될때 초기화되는 백버퍼(장치 초기화할때 TARGET으로 초기화함)
버텍스 셰이더의 기능
1. 정점의 변환
2. 정점의 멤버 구성을 추가 OR 삭제(좀 더 가벼운 픽셀을 만들어주기위해- 많이 만들어지니깐) : VS_IN와 VS_OUT이 같을 필요는 없다!
PS_IN의 위치는 뷰포트상의 위치를 의미한다
포지션시멘틱을 중복되게 할수없기때문에 아무런 연산도 하지않는 TEXCOORD1로 했다.(그냥 월드위치로 사용한다.)
어떻게하면 월드 위치를 부여할수있을까? VS_OUT에 월드위치를 부여해준다.
VS에서 Out.vWorldPos에 포지션에 월드 변환을 곱해서 넣어주자.
이제 모든 픽셀은 월드위치를 가지고있다.
하지만 PS에서는 되도록이면 연산을 줄이는게 좋다.
->VS에서 가능한지 생각해보자.
클라이언트랑 셰이더랑 VS_IN이 받아오는게 달라도 상관없다.
픽셀에 상관없는 데이터라면 VS_IN에서 안받아도되고 VS_OUT에 안넣어줘된다.
지금 구현하고있는 셰이더는 버퍼 렉트를 그리기위한 셰이더이다.
중요한건 픽셀에서 필요한 정보를 VS에서 만들어서 VS_OUT으로 뱉어주자는것이다.
셰이더 빌드
눈으로 보면서 확인을 해보자.
모든연산은 CPU가 아닌 GPU가 수행한다 쉐이더 안의 변수는 VRAM에 저장된다- > 하드웨어 렌더링
technique : 다수의 테크니션을 선언할수있다. 그래픽카드마다 지원할수있는 셰이더 버전이 다르다. 지원하는 버전마다 다른 테크니션을 선언해줄수 있다.
pass : 다수가 선언될수있다. 셰이더 기법의 캡슐화를 위해선언한다. 각 상태에따른 렌더링을 다르게하기위해 진입점 함수를 다르게 줄수있다.(상태에 따라 필요한 연산이 다르기 때문.
pass를 하나 통과해서 리소스를 화면에 그려짐
VS,PS를 지나가면 그림이 그려진것이다.
다중패스 렌더링은 사용하지않는것이 좋다.(어떤 리소스를 그릴때 여러 패스를 통과하는것 대표적으로 그림자)
HLSL은 디버깅이 불가하지만 어차피 코드가 길지않아 큰 문제가 되진않는다.
버퍼를 그릴때마다 몇번째 패스로 그릴게요를 선택해줄수있다 : ID3DXEffect객체에 BeginPass(몇번째 패스를 지날건지 숫자로 지정해준다.) , EndPass()를 호출해서 버퍼를 렌더링한다.
Pass안에서 렌더스테이츠를 정의할 수 있다.
D3DRS_() 이부분을 떼다가 대입으로 넣어주면된다.
(대소문자 상관없다)
technique DefaultTechnieuq
{
pass DefaultRendering
{
VertexShader = compile vs_3_0 VS_MAIN();
PixelShader = compile ps_3_0 PS_MAIN();
}
}
이제 셰이더를 빌드할 준비가 되었다.
셰이더 사용
엔진에 셰이더 컴포넌트를 추가하자.
CShader 클래스
Create에서 셰이더 파일의 경로를 받아오자.
복사생성자에서 이니셜라이저로 복사해주자.
네컨 프로토
D3DXCreateEffectFromFile로 이펙트를 만들어주자.
(장치,쉐이더파일 경로,널,널,D3DXSHADER_DEBUG//2015 이전버전에서는 디버그도안되고 에러도 출력해주지않아서 에러를 출력해주기위한 플래그를 넣어주었다,nullptr // 쉐이더에서 선언되고있는 변수들을 어떤 메모리 공간에서 관리할까? null일경우 VRAM에서,&m_pEffect,&pErrorBuffer//디버그 플래그를 준경우에 에러메세지를 어디에 보관해줄까?)
LPD3DXBUFFER : 메모리 덩어리 객체,GetBufferPointer 로 담겨있는 공간의 주소를 얻어온다. DX함수들이 메모리에 기록하고싶을때 인자로 넘겨주기위한 용도로 사용하는 객체이다.
컴포넌트매니저에 Shader추가해주자.
클라이언트측
MainApp에서 셰이더 컴포넌트 원형을 추가해주자.
백그라운드에 셰이더 컴포넌트를 추가해주자.
CBackGround::Render()를 수정해주자.
텍스처,월뷰투 행렬을 넘겨줄것이다.
클라이언트에서 쉐이더로 값을 던지는 작업
SetValue -> Bool변수와 텍스처 빼고는 다 던져줄수있다.
셰이더 컴포넌트에 SetUp_ConstantTable() 함수 추가해주자.
SetUp_ConstantTable()
D3DXHANDLE로 핸들을 인자로 받아와서 SetValue로 넘겨주자.
pData 주소에 들어있는 값을 어디까지 던져를 명시해줘야함(바이트 크기) iLengthByte를 인자로 받자.
HRESULT Begin_Shader(), End_Shader()
테크니크 하나밖에없으면 0번째를 이용한다 다수인경우 SetTechnique로 정해주자.
m_pEffect의 비긴을 호출해주자
(패스의 갯수 받아오고싶다면 INT 주소, 0)
BeginPass(iPassIndex)로 몇번째 패스로 그릴건지를 전달해주자.
End에선 EndPass()를 호출하고 End() 호출해주면된다.
BackGround::Render()
SetUp_ConstantTable 함수로 값을 넘겨주자.
클라로 돌아가서 비긴과 엔드 출력해주자.
Main에서 SetSamplerState지워주자.
조명끈다는 얘기했는데 이제 셰이더로 그려서 무조건 장치에 세팅해놓은것 무시된다.(SetRenderState는 무시안된다)
셰이더와 고정기능은 섞이면안된다.
length() : 벡터의 길이 구할수있다.