8.1 빛과 재질의 상호작용

조명을 사용할 때에는 정점 색상들을 직접 지정하지 않음. 표면의 재질들과 표면에 비출 빛들을 지정하고 조명 방정식을 적용해서 정점 색상이 결정되게 한다.

 

국소 모형 조명

ㄴ 대부분의 실시간 응용 프로그램이 사용하는 조형 모형으로 각 물체는 광원에서 직접 방출된 빛만 다룬다. (다른 물체에 의해 반사되어 들어오는 빛은 무시한다.)

전역 모형 조명

ㄴ 다른 물체에 의해 반사되어 들어오는 빛도 계산한다. 비용이 커서 실시간 게임에 사용하기에는 비용이 크다.

 

8.2 법선 벡터

정점 자료에 Normal 성분 값이 정점 법선 벡터 값인데 조명 계산에 쓰인다.

삼각형의 세 꼭짓점에서만 표면 법선을 계산해도 래스터화 과정에서 법선 성분 값이 보간되어 필요한 모든 표면 법선을 얻을 수 있다.

 

8.2.2 법선 벡터의 변환

법선 벡터를 비균등 비례변환이나 전단변환하게 되면 변환된 접선 벡터와 법선벡터는 서로 수직이 아니게 된다.

접선 벡터에 A 행렬로 변환 했다면 법선 벡터에는 A 역행렬의 전치행렬을 사용하여 변환하면 서로 수직이 된다.

 

8.3 조명의 주요 벡터

시점(E) : 눈의 위치

 

빛 벡터(L) : 표면의 점에서 광원을 가리키는 방향

반사 벡터(R) : 입사광이 표면 법선 n을 기준으로 반사된 방향

 

8.4 람베르트 코사인 법칙

복사 조도: 단위 면적당 복사 선속(빛 에너지)

비스듬히 비출수록 어두워짐

감소되는 빛의 비율는 L과 n의 내적으로 구할 수 있다. (L과 n이 수직이면 0)

8.5 분산 조명 (Diffuse)

분산 반사 (난반사): 모든 방향으로 고르게 반사되는 빛

ㄴ 색상과 분산 반사율의 내적으로 구해진다.

 

주변 조명

ㄴ 주변광(근사값)과 분산 반사율의 내적

 

8.7 반영 조명 (Specular)

프레넬 효과(Fresnel effect) : 두 매질 사이의 경계면에 빛이 도달하면 빛의 일부는 반사되고 나머지는 굴절되는 현상

 

ㄴ 매질에 따라 반사되는 빛의 양이 다르다.

ㄴ 법선벡터 n과 L 사이의 각도가 클수록 반사되는 빛의 양이 커진다.

 

표면 거칠기

ㄴ 완벽한 거울이 아닌 이상 반사된 빛은 거칠기의 정도에 따라 원뿔 모양으로 퍼진다.(반영 돌출부)

ㄴ 거칠기에 따라 정규분포 함수의 모양이 달라진다. 거칠기가 커지면 빛 에너지가 더 넓고 약하게 퍼지고

거칠기가 작으면 좁고 강하게 퍼진다.

8.8 조명 모형 정리

ㄴ 프레넬 값(매질의 속성), 분산 반사율, 거칠기 계수가 재질의 속성을 결정하는데 사용된다.

8.9 재질의 구현

정점에 색상을 지정하는 대신에 정점에 재질 값을 설정하고 텍스처 매핑을 사용한다.

 

물체 각각의 세계 행렬과 마찬가지로 각각의 재질을 담은 상수 버퍼를 업로드 힙에 올려서 관리한다.

여러 renderitem의 material 포인터가 같은 material 객체를 참조하면 여러 renderitem이 같은 재질을 사용할 수도 있다.

Material 객체에는 자기 자신의 상수 버퍼 index를 저장하고 있다.

 

8.10 평행광 (지향광)

빛의 색상과 빛의 벡터로 정의됨

8.11 점광

감쇠 계수를 구하기 위해 falloffstart와 falloffend라는 거리에 따라 빛이 감소하는 지점을 정의해아 한다.

감쇠 계수의 구간은 [0, 1]이며 광원에서 falloffstart 떨어진 점이 받는 계수는 1이고 falloffend가 받는 계수는 0이다.

이를 광원 값(색상)에 곱한다.

 

8.12 점적광

점적광 계수 : d와 -L의 각도 차이가 클수록 감소함, 지수 s를 조율하여 빛의 세기가 0으로 떨어지는 각도를 제어할 수 있음

빛의 색상에 감쇠계수와 점적광 계수를 모두 곱해야 해서 가장 연산비용이 비싸다.

 

8.13 조명 구현

셰이더 파일에 struct Light를 정의하고 패스 상수 버퍼에 사용하는 조명의 정보를 Light 배열로 넘긴다.

주변광 빛도 포함한다.

 

C++의 구조체 멤버와 hlsl의 구조체 채우기 방식을 동일하게 하여야 한다.

지향광, 점광, 점적광의 조명 계산 함수는 LightingUtil.hlsl이라는 셰이더 파일에 정의되어 있다.

 

픽셀 셰이더에서 한 표면의 점에 대해 모든 조명에 대한 계산을 하여 색상을 누적한 값이 최종 픽셀 색상이 된다.

 

연습문제

1.

B,G 값을 진동시키기 위해 전체 시간(초 단위)을 sin 함수에 넣음

4.

구 위치에 점광 10개를 만듬
Default.hlsl 파일에서 점광이 10개인 것을 기록

6.

툰 셰이딩 결과
거리에 따른 빛의 세기를 계산하는데 쓰이는 CalcAttenuation 함수를 변형하여 툰 셰이딩을 수행

연습문제 파일

https://github.com/lemonyun/Directx12_study/tree/main/8/Chapter%208%20Lighting

 

GitHub - lemonyun/Directx12_study: 2022/06/10

2022/06/10. Contribute to lemonyun/Directx12_study development by creating an account on GitHub.

github.com

 

'읽은 책 > DirectX 12를 이용한 3D 게임 프로그래밍 입문' 카테고리의 다른 글

10. 혼합  (0) 2022.06.22
9. 텍스처 적용  (0) 2022.06.21
7. Direct3D의 그리기 연산 제2부  (0) 2022.06.17
6. Direct3D의 그리기 연산  (0) 2022.06.16
5. 렌더링 파이프라인  (0) 2022.06.14

 

7.1 프레임 자원

매 프레임 CPU가 수정해야 하는 자원들을 순환 배열로 관리하여 CPU와 GPU가 놀지 않도록 하기

 

프레임 자원마다 명령 할당자가 필요하다. (GPU가 명령을 다 처리하지 않았어도 다음 프레임 자원을 수정해야 하기 때문에)

상수 버퍼를 매 프레임 수정한다면 프레임 자원마다 상수 버퍼가 필요하다.

void ShapesApp::Update(const GameTimer& gt)
{
    OnKeyboardInput(gt);
	UpdateCamera(gt);

    // Cycle through the circular frame resource array.
    // Update 함수 호출 될때마다 다음 인덱스의 프레임 자원이 현재 프레임 자원이 됨
    mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources; 
    mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();

    // Has the GPU finished processing the commands of the current frame resource?
    // If not, wait until the GPU has completed commands up to this fence point.
    // CPU 처리속도가 GPU 처리속도보다 빨라서 한 바퀴를 돌았는데도 아직도 안 끝난 경우에는 기다림
    if(mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
    { 
        HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
        ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
        WaitForSingleObject(eventHandle, INFINITE);
        CloseHandle(eventHandle);
    }

	UpdateObjectCBs(gt);
	UpdateMainPassCB(gt);
}

void ShapesApp::Draw(const GameTimer& gt){
// 현재 프레임의 명령 목록들을 구축하고 제출
	mcurrFrameResource->Fence = ++mCurrentFence; // CPU는 현재 프레임 명령 제출을 끝냈음
    mCommandQueue->Signal(mFence.Get(), mCurrentFence); // GPU기준 마지막으로 끝낸 프레임 작업 번호가 무엇인지 설정

7.2 렌더 항목 (RenderItem 구조체)

하나의 물체를 그리는데 필요한 설정들을  모아놓은 구조체

 

1. 물체의 세계 행렬

2. numframesDirty // 물체의 자료가 변해서(위치가 이동했거나 한 경우) 상수 버퍼를 갱신해야 하는 경우 numframesdirty 값을 프레임 자원의 개수로 설정하면 된다.

update문에서 모든 renderitem들의 numframesdirty 값을 확인하는데 값이 0보다 크다면 해당 renderitem이 사용하는 상수 버퍼의 값을 갱신하고 numframesdirty 값을 -1 시킨다. CPU가 프레임 자원을 한바퀴 돌면 모든 프레임 자원의 상수 버퍼 값은 갱신된다.

3. 기하구조 (Mesh Geometry) (GPU와 CPU 메모리에 기하구조가 사용하는 정점 버퍼와 색인 버퍼 자원을 만들게 되는데

이 자원들을 가리키는 Com객체를 멤버로 가지고 있는 구조체)

4. 기본도형 위상구조

5. GPU상 해당 RenderItem이 사용하는 상수 버퍼의 index

 

7.3 물체별 상수 버퍼와 패스별 상수 버퍼

물체별 상수 버퍼는 물체의 world행렬만 가지고 있으면 된다.

패스별 상수 버퍼는 시점 위치, 시야 행렬, 투영 행렬, 화면 크기, 게임 시간 측정치 등 한 프레임에 한번만 수정되는 상수 자료를 가진다.

 

7.4 도형 기하구조

원기둥 메시

구 메시

측지구 메시

7.5 도형 예제

7.7 지형과 파도 예제

 

 

7.6 루트 서명 추가 설명

이전 장에서 다 설명함

서술자 테이블

루트 상수

루트 서술자 

ㄴ 서술자 테이블에서는 자원을 묶을 때 서술자 힙의 핸들을 묶어 줬지만 루트 서술자는 그냥 자원의 가상 주소를 묶으면 된다. (업로드 힙에 올린 상수 버퍼 자원의 서술자 힙을 만들지 않고도 가능한 방법이다.)

 

7.7.5 동적 정점 버퍼

파도 구현할때, 복잡한 물리계산과 충돌 검출을 수행해서 입자들의 새 위치를 구할때

 

상수 버퍼들의 배열을 업로드 힙에 올리는 방법과 유사하다. 이번에는 정점들의 배열을 업로드 버퍼에 담는다.

 

동적 버퍼를 사용하면 CPU에서 새 자료를 GPU 메모리에 전송하는 데 추가 부담이 발생하므로 정적 버퍼로 충분 할때에는 정적 버퍼를 사용하자

 

1. 간단한 애니메이션은 정점 셰이더에서 수행할 수 있다.

2. 텍스처로의 렌더링 기능이나 계산 셰이더 또는 정점 텍스처 조회 기능을 이용할 수 있다.

3. 기하 셰이더를 이용하면 GPU에서 기본도형의 생성 및 파괴 작업을 GPU에서 할 수 있다.

4. 테셀레이션 단계를 이용하면 GPU에서 세밀한 기하구조를 추가할 수 있다.

 

응용 프로그램에서 update뒤에 draw가 실행되므로

update에서 매 프레임 정점 버퍼를 업로드 힙에 갱신하고 draw하면 된다.

 

 

연습문제

1.

세부수준 0 1
세부수준 2 3

2.

셰이더 파일에서 상수 0번 레지스터가 받는 형식
정점 셰이더 부분
DrawRenderItems함수에서 각각의 renderitem의 world 행렬 갱신하는 부분
루트 서명 작성하는 부분

 

연습문제 파일

https://github.com/lemonyun/Directx12_study/tree/main/7/Chapter%207%20Drawing%20in%20Direct3D%20Part%20II/Shapes

 

GitHub - lemonyun/Directx12_study: 2022/06/10

2022/06/10. Contribute to lemonyun/Directx12_study development by creating an account on GitHub.

github.com

 

'읽은 책 > DirectX 12를 이용한 3D 게임 프로그래밍 입문' 카테고리의 다른 글

9. 텍스처 적용  (0) 2022.06.21
8. 조명  (0) 2022.06.20
6. Direct3D의 그리기 연산  (0) 2022.06.16
5. 렌더링 파이프라인  (0) 2022.06.14
4. Direct3D의 초기화(2)  (0) 2022.06.13

 

6.1 정점과 입력 배치

정점 구조체를 정의하고 D3D12_INPUT_DESC 배열또는 벡터를 정의한다.

정점 구조체의 멤버와 입력배치 서술배열의 각 원소의 오프셋이 일치해야 하고

입력 배치 서술 배열의 입력 서명과 정점 셰이더의 입력 서명이 일치해야한다.

 

6.2 정점 버퍼

자원의 종류는 텍스처와 버퍼 두가지로 나누어져 있는데, 버퍼는 밉맵과 달리 다차원이 아니며 밉맵이나 필터, 다중표본화 기능이 없어 단순한 자원이다. 정점 자료 원소의 배열을 CPU에 제공할 때에는 항상 버퍼를 사용한다.

 

범용 GPU 자원으로서의 버퍼에서 너비(width)는 가로 길이가 아니라 버퍼의 바이트 개수를 뜻한다.

 

정적 기하구조(프레임마다 변하지 않는 기하구조)를 그릴 때에는 최적의 성능을 위해 정점 버퍼들을 기본 힙(D3D12_HEAP_TYPE_DEFAULT)에 넣는다. 기본 힙은 GPU만 읽기 때문에 CPU가 기본 힙을 수정하지 못한다.

 

d3dUtil.cpp에 기본 힙의 자료를 초기화 하기 위한 CreateDefaultBuffer함수가 정의되어 있다.

1. 임시 업로드 힙에 버퍼를 만들고

2. D3D12_SUBRESOURCE_DATA 라는 임시 자료를 위한 구조체를 서술

3. 자원 장벽 명령으로 기본힙의 버퍼 상태를 COMMON에서 COPY_DEST로 변경

4. UpdateSubresources 함수는 CPU 메모리를 임시 업로드 힙에 복사하고 임시 업로드 힙의 자료를 

 

기본 힙의 버퍼와 업로드 힙의 버퍼는 이 함수 밖에서도 Comptr로 가리키고 있어야 한다. 실제로 명령 목록이 명령 대기열에 들어가 실행된 상태가 아니기 때문이다. 함수 내부에서 만들어진 기본 힙의 버퍼를 가리키는 Comptr를 이 함수가 반환하기 때문에 소유권을 넘길 수 있다. 아무튼 외부에 존재하는 두 버퍼에 대한 Comptr가 유지되어야 한다.

 

정점 자원을 서술하는 서술자는 서술자 힙이 필요없다.

D3D12_VERTEX_BUFFER_VIEW 구조체를 서술하고(버퍼 자원의 가상주소, 버퍼의 크기(vertex 구조체 크기 * 정점 개수), 정점 원소의 크기(vertex 구조체 크기)) 

 

cmdList->IASetVertexBuffers 함수의 매개변수로 위의 구조체로 만든 배열의 주소를 입력하면 각 정점 버퍼들이 슬롯에 차례대로 묶인다. 

cmdList->IASetPrimitiveTopology 함수로 기본도형 위상구조 상태를 set 시켜놔야 한다.

 

cmdList->DrawInstanced가 호출되어야지 그때 그려진다.

ㄴ 인덱스 없이 정점 버퍼에 있는 정점 순서대로 기본도형을 그린다.

6.3 색인 버퍼

만드는 방식은 정점 버퍼와 같은데 이름만 다르다

D3D12_INDEX_BUFFER_VIEW 구조체를 서술해야하고, 

cmdList->IASetIndexBuffer 함수를 사용한다.

 

색인들을 이용해 기본도형을 그리려면, DrawIndexedInstanced 함수를 사용해야 한다.

인덱스로 접근하기 때문에 다음의 3가지 정보를 사용한다.

1. 첫 정점의 위치

2. 첫 인덱스의 위치

3. 기하구조를 그리는데 사용하는 인덱스의 크기

여러 종류의 기하구조를 하나의 정점 버퍼와 색인 버퍼에 저장하더라도 기하구조를 그리는 첫 번째 정점의 위치와 인덱스 위치를 기록해놓으면 문제가 없다.

 

6.4 정점 셰이더

기본적인 정점 셰이더의 역할은 로컬 position을 동차좌표 position으로 변환하여 픽셀 셰이더에 전달하는 것이다.

셰이더 파일은 포인터나 참조가 없어서 out float oPosH와 같은 출력 매개변수를 사용한다.  

VertexOut VS(VertexIn vin)
{
VertexOut vout;

// Transform to homogeneous clip space.
vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj); 
// float3 형식의 로컬 position의 w값을 1로 하여 float4값을 생성하고 세계시야투영행렬을 곱한다.

// Just pass vertex color into the pixel shader.
    vout.Color = vin.Color;
    
    return vout;
}

 

 

정점 셰이더가 필요로 하는 입력서명을 입력 배치서술이 모두 제공하지 않으면 오류가 발생한다.

동차 절단 공간에서의 정점의 위치를 값는 출력 매개변수는 SV_POSITION 의미소를 부여해야 한다.

6.5 픽셀 셰이더

정점 셰이더에서 출력한 정점 특성들은 래스터화 단계에서 삼각형의 픽셀들을 따라 보간되어 보간된 결과가 픽셀셰이더의 입력으로 들어온다.

float4 PS(VertexOut pin) : SV_Target
{
    return pin.Color;
}

// SV_TARGET : 이 함수의 반환값의 형식이 렌더 대상의 형식과 일치해야 함을 뜻한다.(4차원의 색상 값)

6.6 상수 버퍼

셰이더 프로그램에서 참조하는 자료를 담는 GPU 자원

정점 버퍼와 색인 버퍼와 달리 상수 버퍼는 프레임당 한 번 갱신하는 것이 일반적임(기본 힙이 아니라 업로드 힙에 만들어야 CPU가 버퍼의 내용을 갱신할 수 있음)

하드웨어가 256 * n 바이트 오프셋에서 시작하는 256 * n 바이트 길이의 상수 자료만 볼 수 있기 때문에 상수 버퍼의 원소는 256바이트의 배수여야 한다.

cbuffer cbPerObject : register(b0)
{
	float4x4 gWorldViewProj; // 256바이트 경계에 맞게 바이트들이 암묵적으로 채워진다.
};

6.6.2 상수버퍼의 갱신

자원을 바이트 배열에 Map시킨 뒤

ThrowIfFailed(mUploadBuffer->Map(0, nullptr, reinterpret_cast<void**>(&mMappedData)));

바이트 배열의 특정 위치(256 * 오프셋) 상수 버퍼 구조체를 memcopy하여 복사하면 된다.

 

6.6.4 상수 버퍼 서술자

상수 버퍼 서술자는 DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV 형식의 서술자 힙에 담긴다.

DESCRIPTOR_HEAP_TYPE_DESC를 서술하여 서술자 힙을 만들 때

Type을 DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV로 해줘야 하고

Flags를 D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE로 해줘야 한다.(셰이더 프로그램에서 상수 버퍼에 접근해야 하기 때문에)

 

사실 서술자를 따로 만들지 않아도 된다. 자원의 GPU 가상주소를 루트 매개변수로 

 

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

루트 매개변수는 3가지로 정의될 수 있다.

1. 루트 상수

2. 루트 서술자

3. 서술자 테이블

루트 서명은 루트 매개변수의 배열이다.

루트 서명에는 최대 64개의 DWORD를 넣을 수 있는데

서술자 테이블: DWORD 하나

루트 서술자 : DWORD 두 개

루트 상수 : 32비트 상수당 DWORD 하나

CD3DX12_DESCRIPTOR_RANGE texTable;
	texTable.Init(
        D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 
        2,  // number of descriptors
        2); // register t2,t3

    // Root parameter can be a table, root descriptor or root constants.
    CD3DX12_ROOT_PARAMETER slotRootParameter[4];

	// Perfomance TIP: Order from most frequent to least frequent.
    slotRootParameter[0].InitAsDescriptorTable(1, &texTable, D3D12_SHADER_VISIBILITY_PIXEL);
    slotRootParameter[1].InitAsConstantBufferView(0); // register b0
    slotRootParameter[2].InitAsConstantBufferView(1); // register b1
    slotRootParameter[3].InitAsConstantBufferView(2); // register b2

위의 코드는 4개의 루트 파라미터중 1개는 서술자 테이블, 3개는 루트 서술자를 사용한 방법이다.

3가지 종류(srv, uav, cbv)의 서술자를 하나의 테이블에 저장하여 사용하고 싶다면 CD3DX12_DESCRIPTOR_RANGE table[3]의 형태로 선언해야 한다. srv는 t레지스터에 cbv는 b레지스터에 묶인다.

테이블은 서술자는 루트 파라미터 한 개를 사용해서 여러개의 서술자를 여러개의 레지스터와 묶어준다. 

 

루트 서명은 어떤 레지스터에 어떤 루트 매개변수가 연관되는지(루트 서술자인지, 서술자 테이블인지, 루트 상수인지)를 정의 하는 역할이고 실제로 자원을 묶으려면 cmdlist->SetGraphicsRoot****을 호출해서 묶는다.

 

 

6.7 셰이더의 컴파일

셰이더 파일(.hlsl)은 이식성 있는 바이트 코드로 컴파일된 후에 그래픽 드라이버는 그 바이트 코드를 시스템의 GPU에 맞게 최적의 네이티브 명령들로 컴파일한다.

 

오프라인 컴파일 : 셰이더를 실행 시점에서 컴파일하지 않고 오프라인에서 개별적인 단계로 컴파일

ㄴ 복잡한 셰이더의 경우 컴파일에 시간이 오래 걸리는데, 오프라인에서 컴파일하면 게임의 로딩 시간이 빨라진다.

컴파일된 셰이더 파일(.cso)

진입점이 VS인 파일과 PS인 파일로 나누어 컴파일 될 수 있다. (.cso파일이 두 개)

 

오프라인 컴파일 방법이던 아니던 컴파일된 셰이더 목적 바이트코드는 ID3DBlob라는 범용 메모리 버퍼에 저장되고 파이프라인 상태객체를 서술할때 사용된다.

 

6.8 래스터화기 상태

D3D12_RASTERIZER_DESC 구조체를 서술하여 파이프라인 상태 객체 만들때 설정한다.

6.9 파이프라인 상태 객체

루트서명

셰이더 바이트 코드(정점, 영역, 덮개, 기하, 픽셀)

혼합 방식

다중표본화 samplemask (최대 32개의 표본의 비활성화 여부)

래스터화기 상태

깊이 스텐실 판정 방법 지정

입력 배치 서술 구조체

기본도형 위상구조 종류

동시에 사용하는 렌더 대상 개수

렌더 대상 format

깊이 스텐실 버퍼 format

다중표본화 표본개수와 품질 수준

 

연습문제

1.

mInputLayout =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_PER_VERTEX_DATA, 0 },
        { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_PER_VERTEX_DATA, 0 }
        { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 24, D3D12_INPUT_PER_VERTEX_DATA, 0 }
        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 36, D3D12_INPUT_PER_VERTEX_DATA, 0 }
        { "TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 44, D3D12_INPUT_PER_VERTEX_DATA, 0 }
        { "COLOR", 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0, 52, D3D12_INPUT_PER_VERTEX_DATA, 0 } // XMCOLOR는 32비트 자료형
    };

4. 

 

5. 

삼각형의 면 픽셀 색상이 빨간색과 초록색의 그라데이션 효과처럼 보이는 이유는 
래스터화기 상태에서 정점 특성의 보간이 일어나기 때문이다.

 

7.

CBV_SRV_UAV 서술자 힙을 만들때 서술자 크기를 2로 하고
서술자 힙의 핸들을 이동시켜가며 상수 버퍼 서술자를 두 개 채운다.

update()에서 업로드 힙에 있는 상수 버퍼에 변환 행렬 값을 갱신한다.
두개의 버퍼에 각각 다른 변환 행렬값을 갱신한다. (이동변환 적용된 것과 아닌 것)

SetGraphicsRootDescriptorTable(0,  서술자 힙 handle(맨 앞))
그리기 // 첫 번째 서술자 그려짐
handle.Offset(1, mCbvSrvUavDescriptorSize) // 핸들 한칸 움직이고
SetGraphicsRootDescriptorTable(0, 서술자 힙 handle)
그리기 // 두 번째 서술자로 그려짐

11. 

1. 입력 배치 서술들의 순서는 정점 구조체 성분들의 순서와 일치하지 않아도 된다.
alignedByteOffset으로 구조체의 어떤 멤버인지 알 수 있기 때문에

2. 정점 셰이더 구조체의 성분 순서가 C++ 정점 구조체 성분 순서와 일치하지 않아도 된다.
의미소로 이어져 있기 때문에

 

15. 

R픽셀 색상 값이 0.5 이하인 픽셀 단편이 제거된다.

 

연습문제 파일

https://github.com/lemonyun/Directx12_study/tree/main/6/Chapter%206%20Drawing%20in%20Direct3D/Box

 

GitHub - lemonyun/Directx12_study: 2022/06/10

2022/06/10. Contribute to lemonyun/Directx12_study development by creating an account on GitHub.

github.com

 

+ Recent posts