GameChoi
Choi Programming
GameChoi
전체 방문자
오늘
어제
  • 분류 전체보기 (468)
    • C++ Algorithm & Study (184)
      • C++ & Algorithm Strategies (45)
      • Game Math & DirectX 11 (72)
      • Server + UE5 (29)
      • Lyra Clone Coding (37)
    • Create Game (284)
      • [Window API] Game Client & .. (55)
      • [DirectX] DirectX 2D & 3D (155)
      • [UE5] BLUEPRINT & C++ (74)
    • odds and ends (0)
      • English (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • Direct11
  • Player State
  • c++
  • Network Worker
  • core
  • Game Room
  • GAME Client
  • UE5
  • protobuf
  • server
  • RPG Game
  • Player Move Packet
  • Game Server
  • Other Character
  • Algorithm Strategies
  • Direct3D
  • session
  • client
  • Destination Move Packet
  • job queue

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
GameChoi

Choi Programming

[Direct11] 38. 3D Direct Application - Displacement Mapping
C++ Algorithm & Study/Game Math & DirectX 11

[Direct11] 38. 3D Direct Application - Displacement Mapping

2023. 6. 30. 17:27

1. 3D Direct Application

1.1 Displacement Mapping System

1.1.1 Displacement Mapping

1.1.1.1 Displacement Mapping

 - 테셀레이션과 함께 사용하여 렌더링 품질을 더욱 높일 수 있는 변워 매핑 사용

   - 법선 매핑이 단지 조명의 세부도만 개선할 뿐 실제 기하구조의 세부도는 개선X

 - 표면의 굴곡과 균열을 묘사하는 높이 맵이라고 부르는 또 다른 맵을 이용하여 기하구조를 변형

   - 법선 맵이 각 픽셀마다 세 색상 성분에 하나의 법선 벡터를 저장

   - 높이 맵은 각 픽셀마다 하나의 색상 성분에 높이 값을 저장

 - 테셀레이션으로 메시를 더 잘게 쪼개고 영역 셰이더에서 정점을 법선 벡터 방향으로 이동시킬 때의 이동량으로 쓰임

   - 테셀레이션으로 기하구조에 삼각형을 추가하는 것 자체로 메시에 세부사항이 추가되지는 않음

     - 한 삼각형을 여러 번 세분한다해도 원래 삼각형 평면에 더 많은 삼각형이 생기는 것

       - 요철이나 균열 같은 세부사항을 추가하려면 테셀레이션된 정점들의 위치를 적절하게 변경

 - 높이맵은 테셀레이션된 정점의 변위에 사용할 수 있는 입력 원본의 하나, 벡터 위치를 변위 시킬 때 공식 사용

   - 정점을 표면의 바깥쪽을 향한 표면 법선 벡터가 가리키는 방향으로 일정 거리만큼 이동

1.1.1.2 Shader Code

 - 변위 매핑을 렌더링 코드와 통합하려면 렌더링 코드가 테셀레이션을 지원

   - 메시 기하구조의 해상도를 변위 매핑의 해상도에 걸맞은 수준으로 높일 수 있기 때문

     - 기본 도형 위상구조를 밑의 코드로 설정

       - 메시의 한 삼각형의 정점 세 개가 한 삼각형 패치의 제어점 세 개로 해석, 메시의 각 삼각형을 세분할 수 있게 됨

D3D11_PRIMITIVE_T0P0L0GY_3_C0NTR0L_P0INT_PATCHLIST

 - 테셀레이션을 사용할 때 각 삼각형을 얼마나 세분할 것인지 결정

   - 삼각형이 시점에 가까울수록 테셀레이션을 더 많이 수행하는 방식

     - 정점 셰이더에서는 정점별로 거리에 따른 테셀레이션 계수를 계산해서 덮개 셰이더로 넘김

 - 상수 버퍼에 거리 계산에 관여하는 최종적인 테셀레이션 계수들에 영향을 주는 변수 추가

   - 구체적인 값은 렌더링할 장면에 따라 달라짐

cbuffer cbPerFrame /* 필요한 것만 작성 */
{ float gMaxTessDistance; float gMinTessDistance; float gMinTessFactor; float gMaxTessFactor; };

1.1.1.3 Vertex Shader

 - 정점 셰이더에서 d의 거리에 따라 정규화된 테셀레이션 계수를 이용하여 결정

float d = distance(vout.PosW, gEyePosW);
float tess = saturate((gMinTessDistance - d) / (gMinTessDistance - gMaxTessDistance));
vout.TessFactor = gMinTessFactor + tess * (gMaxTessFactor - gMinTessFactor);

1.1.1.4 Hull Shader

 - 상수 덮개 셰이더는 패치별로 평가, 메시의 소위 테셀레이션 계수들을 출력

   - 테셀레이션 계수는 테셀레이터 단계가 패치를 얼마나, 어떻게 세분할 것인지 결정

     - 테셀레이션 계수를 계산하는 작업은 정점 셰이더에서 결정

       - 정점별 테셀레이션 계수들의 평균으로 변 테셀레이션 계수들을 계산

struct PatchTess { float EdgeTess[3] : SV_TessFactor; float InsideTess : SV_InsideTessFactor; };

 - 정점 테셀레이션 계수들을 변을 따라 평균, 테셀레이션 계수들을 변의 속성에 근거해서 계산하는 것이 중요

   - 여러 삼각형이 공유하는 변의 테셀레이션 계수가 그러한 모든 삼각형에서 동일, 그렇지 않으면 메시의 틈이 생김

pt.EdgeTess[0] = 0.5f * (patch[1].TessFactor + patch[2].TessFactor);
pt.EdgeTess[1] = 0.5f * (patch[2].TessFactor + patch[0].TessFactor);
pt.EdgeTess[2] = 0.5f * (patch[0].TessFactor + patch[1].TessFactor);
pt.InsideTess = pt.EdgeTess[0];

 - 제어점 덮개 셰이더는 일단의 제어점들을 받아 일단의 제어점들을 출력

   - 출력할 제어점마다 한 번씩 호출, 이번에 사용할 제어점 덮개 셰이더는 그대로 통과함

hout.PosW = p[i].PosW; hout.NormalW = p[i].NormalW; hout.TangentW = p[i].TangentW; hout.Tex = p[i].Tex;

1.1.1.5 Domain Shader

[domain("tri")]
DomainOut DS(PatchTess patchTess, float3 bary : SV_DomainLocation, const OutputPatch<HullOut, 3> tri)

 - 테셀레이션 단계가 생성한 각 정점마다 실행, 테셀레이션된 패체에 대한 정점 셰이더

   - 실질적인 변위 매핑이 일어나는 곳이 영역 셰이더

     - 즉 높이맵에서 높이 값을 추출하여 정점 위치를 공식에 따라 법선 방향으로 이동시키는 작업

 - 패치 특성들을 생성된 정점들에 대해 보간

   - 보간 때문에 법선이 더 이상 단위 벡터가 아닐 수 있으므로 다시 정규화 진행

DomainOut dout;
dout.PosW = bary.x * tri[0].PosW + bary.y * tri[1].PosW + bary.z * tri[2].PosW;
dout.NormalW = bary.x * tri[0].NormalW + bary.y * tri[1].NormalW + bary.z * tri[2].NormalW;
dout.TangentW = bary.x * tri[0].TangentW + bary.y * tri[1].TangentW + bary.z * tri[2].TangentW;
dout.Tex = bary.x * tri[0].Tex + bary.y * tri[1].Tex + bary.z * tri[2].Tex;

dout.NormalW = normalize(dout.NormalW);

 - 시점과의 거리에 근거해서 밉맵 수준을 선택

   - 매 Mip Interval 단위마다 다음 번 밉맵 수준을 선택하고 [0, 6] 구간으로 한정

const float MipInterval = 20.0f;
float mipLevel = clamp((distance(dout.PosW, gEyePosW) - MipInterval) / MipInterval, 0.0f, 6.0f);

 - 높이맵의 표본을 추출하여 정점 위치를 법선 방향으로 이동하고 동차 절단 공간으로 투영

float h = gNormalMap.SampleLevel(samLinear, dout.Tex, mipLevel).a;
dout.PosW += (gHeightScale * (h - 1.0)) * dout.NormalW;
dout.PosH = mul(float4(dout.PosW, 1.0f), gViewProj);
저작자표시 (새창열림)

'C++ Algorithm & Study > Game Math & DirectX 11' 카테고리의 다른 글

[Direct11] 40. 3D Direct Application - Terrian Rendering #2  (0) 2023.06.30
[Direct11] 39. 3D Direct Application - Terrian Rendering #1  (0) 2023.06.30
[Direct11] 37. 3D Direct Application - Normal Mapping  (0) 2023.06.30
[Direct11] 36. 3D Direct Application - Dynamic Cube Mapping System  (0) 2023.06.27
[Direct11] 35. 3D Direct Application - Cube Mapping System  (0) 2023.06.27
    'C++ Algorithm & Study/Game Math & DirectX 11' 카테고리의 다른 글
    • [Direct11] 40. 3D Direct Application - Terrian Rendering #2
    • [Direct11] 39. 3D Direct Application - Terrian Rendering #1
    • [Direct11] 37. 3D Direct Application - Normal Mapping
    • [Direct11] 36. 3D Direct Application - Dynamic Cube Mapping System
    GameChoi
    GameChoi

    티스토리툴바