전체글 48

6.7 셰이더의 컴파일

D3D에서 셰이더 프로그램은 먼저 이식성이 있는 바이트 코드로 컴파일되어야 한다. 그래야 그래픽 드라이버는 그 바이트 코드를 다시 시스템의 GPU에 맞게 최적의 네이티브 명령들로 컴파일한다. 1. 런타임 컴파일 실행 시점에서 D3DCompilerFromFile() 함수를 이용해 셰이더를 컴파일할 수 있다. https://docs.microsoft.com/en-us/windows/win32/api/d3dcompiler/nf-d3dcompiler-d3dcompilefromfile D3DCompileFromFile function (d3dcompiler.h) - Win32 apps Compiles Microsoft High Level Shader Language (HLSL) code into bytecode ..

DirectX 2021.12.31

6.6 루트 서명과 서술자 테이블

셰이더 프로그램들은 특정 종류의 자원들이 렌더링 파이프라인에 묶인 상태에서 그리기 호출이 실행되었다고 기대한다. 자원들은 특정 레지스터 슬롯에 묶이며, 셰이더 프로그램들은 그 슬롯들을 통해서 자원에 접근한다. 루트서명(root signature)은 그리기 호출 전에 응용 프로그램이 반드시 렌더링 파이프라인에 묶어야 하는 자원들이 무엇이고 그 자원들이 셰이더 입력 레지스터들에 어떻게 대응되는지를 정의한다. 루트 서명은 반드시 그리기 호출에 쓰이는 셰이더들과 호환되어야 한다. 루트 서명의 유효성은 파이프라인 상태 객체(PSO, Pipeline State Object 나중에 나옴)를 생성할 때 검증된다. 루트 서명은 ID3D12RootSignature 인터페이스를 사용한다. 루트 서명은 자원들을 서술하는 매개..

DirectX 2021.12.31

6.5 상수 버퍼(Constant buffer)

상수 버퍼는 셰이더 프로그램에서 참조하는 자료를 담은 GPU 자원(ID3D12Resource)의 예이다. Vertex Shader 코드 중 이런 구문이 있다. cbuffer cbPerObject : register(b0) { float4x4 gWorldViewProj; }; 여기서 cbPerObject 라는 cbuffer 객체(상수 버퍼)를 참조한다. 여기서 상수 버퍼는 gWorldViewProj라는 4 x 4 행렬 하나만 저장한다. 정점, 색인 버퍼와는 달리 상수 버퍼는 프레임마다 갱신해주는 것이 일반적이다. 카메라가 매 프레임 이동할 때 마다 상수 버퍼를 새 시야 행렬로 갱신해야 할 것이다. 따라서 상수 버퍼는 디폴트 힙이 아닌 업로드 힙에 만든다. 또한, 상수 버퍼에는 특별한 하드웨어 조건이 따른다..

DirectX 2021.12.26

6.4 픽셀 셰이더(Pixel Shader)

정점 셰이더처럼 픽셀 셰이더도 본질적으로는 하나의 함수지만, 정점 셰이더와는 달리 픽셀 단편마다 실행된다. https://gamedev.stackexchange.com/questions/8977/what-is-a-fragment-in-3d-graphics-programming What is a fragment in 3D graphics programming? What is a fragment in a fragment shader? Wikipedia says that: In general, a fragment can be thought of as the data needed to shade the pixel, plus the data needed to test whether the fragment su....

DirectX 2021.12.26

6.3 정점 셰이더(Vertex Shader)

셰이더는 HLSL라는 언어로 작성한다. https://dandydot.tistory.com/category/HLSL 'HLSL' 카테고리의 글 목록 dandydot.tistory.com 본질적으로 정점 셰이더는 하나의 함수이다. 아래 예제를 보면 정점 셰이더(VS)의 첫째, 둘째는 입력(in) 매개변수고, 나머지 두개는 출력(out) 매개변수다. HLSL는 참조나 포인터가 없으므로 이렇게 in(생략가능), out이 지정된 매개변수를 사용해야 한다. HLSL에서 함수는 항상 인라인화 된다. cbuffer cbPerObject : register(b0) { float4x4 gWorldViewProj; }; void VS(float3 iPosL : Position, float4 iColor : Color, o..

DirectX 2021.12.26

4. 함수

1. 사용자 정의 함수 HLSL 함수의 특징이다. 1. 익숙한 C++의 함수 구문을 사용한다. 2. 매개변수는 항상 값으로 전달된다. 3. 재귀를 지원하지 않는다. 4. 항상 인라인화된다. // in: 입력용 변수 out: 출력용 변수 inout: 입출력용 변수 bool foo(in const bool b, out int r1, inout float r2) { if(b) { r1 = 5; // r1을 통해 하나의 값을 출력한다. } else { r1 = 1; // r1을 통해 하나의 값을 출력한다. } // r2는 inout이므로 입력 값이 될 수도 출력 값이 될 수도 있다. r2 = r2 * r2 * r2; return true; } 2. 내장 함수 https://docs.microsoft.com/ko..

HLSL 2021.12.24

2. 키워드와 연산자

1. 키워드 다음은 HLSL이 정의하는 모든 키워드의 목록이다. asm bool compile const decl do double else extern false float for half if in inline inout int matrix out pass pixelshader return sampler shared static string struct technique texture true tyepdef uniform vector vertexshader void volatile while 그리고 예약되어 있지만 실제로 쓰이지 않는 키워드들이다. auto break case catch char class const_cast continue default delete dynamic_cast enum ..

HLSL 2021.12.24

1. 변수 형식

1. 스칼라 형식 2. 벡터 형식 int2, half3 bool4 등 가능 벡터를 초기화 방법 float3 v = {1.0f, 2.0f, 3.0f}; float2 w = float2(x, y); float4 u = float4(w, 3.0f, 4.0f); // u = (w.x, w.y, 3.0f, 4.0f) vec.x = vec.r = 1.0f; vec.y = vec.g = 2.0f; vec.z = vec.b = 3.0f; vec.w = vec.a = 4.0f; 벡터 u = (ux, uy, uz, uw)의 성분들을 벡터 v에 복사하되, v = (uw, uy, uy, ux)가 되도록 성분을 뒤섞어서 복사하고 싶다고 하자. 가장 직접적인 방법은 u의 각 성분을 하나하나 복사해주는 것이다. 그러나 HLSL은 ..

HLSL 2021.12.24

6.2 색인(index)

정점과 마찬가지로 색인들을 ID3D12Resource에 넣어두어야 한다. 생성 방법도 정점 버퍼와 동일하게 임시 업로드 힙을 생성해 초기화 해주고 디폴트 힙에 복사해주면 된다. 차이점은 색인들을 이용해 그리기는 ID3D12GraphicsCommandList::DrawIndexedInstanced()를 사용한다는 점이다. 여러 물체로 이루어진 장면을 그린다고 하자 여러 색인 버퍼를 연결해서 하나의 큰 색인 버퍼를 만들게 된다. 그러면 상자의 실제 색인은 이렇게 된다. firstBoxVertexPos, firstBoxVertexPos+1, · · ·, firstBoxVertexPos + numBoxVertices - 1 따라서 색인 버퍼의 색인들을 갱신하려면 모든 상자 색인에 firstBoxVertexPos..

DirectX 2021.12.24