<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>DVelog</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sun, 09 Jun 2024 19:08:59 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>DVelog</title>
            <url>https://velog.velcdn.com/images/howru_dv/profile/a33e77e5-88f8-4032-a255-69df4929bc41/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. DVelog. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/howru_dv" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[12. RayCasting & Intersection]]></title>
            <link>https://velog.io/@howru_dv/12.RaycastingIntersection</link>
            <guid>https://velog.io/@howru_dv/12.RaycastingIntersection</guid>
            <pubDate>Sun, 09 Jun 2024 19:08:59 GMT</pubDate>
            <description><![CDATA[<h1 id="📒raycasting-raytracing">📒RayCasting, RayTracing</h1>
<hr>
<h3 id="📌raycasting">📌RayCasting</h3>
<p>광선 <em>Ray</em>
: 어떠한 원점과 방향을 갖는 것</p>
<p>광선 투사법 <em>RayCasting</em>
: 광선을 정해진 방향으로 쏘아 어떤 물체와 충돌하게 만드는 것</p>
<ul>
<li>두 점 사이: 광선 투사법으로 두 점 사이에 무언가가 가로막고 있는지 확인 가능</li>
<li>두 면 사이: 광선 투사법으로 두 면 사이에 무언가가 가로막고 있는지 확인 가능<ul>
<li>Ex) A에서부터 빛이 나간다고 할 때, 중간에 무언가가 막고 있어 B 표면에 그림자가 졌는지, 아니면 제대로 빛이 전달되는지 여부 등 확인</li>
</ul>
</li>
</ul>
<h3 id="📌raytracing">📌RayTracing</h3>
<p>: RayCasting을 사용해서 이미지 생성하는 렌더링 방식
<img src="https://velog.velcdn.com/images/howru_dv/post/d5719761-1d33-4cd9-a7f2-3ae20640a561/image.png" alt=""></p>
<ul>
<li>카메라 앞에 모니터를 두고, 카메라에서 모니터의 각 픽셀마다 광선을 쏜다고 가정</li>
<li>광선이 3D 공간에서 어떤 한 물체와 충돌했을 때,</li>
<li>충돌 지점에서 또다른 광선을 투사시켜 그림자 유무를 확인하는 방식으로 색을 계산</li>
</ul>
<h3 id="📌raycasting-vs-raytracing">📌RayCasting vs RayTracing</h3>
<p>: 광선 투사법과 광선 추적법은 다름</p>
<p><strong>[RayCasting]</strong>
View point로부터 나와 Scene 내의 Object에 도달하는 광선을 추적</p>
<ul>
<li>semi-3D 기술: 2차원 맵에서 3차원의 원근감을 만드는 렌더링 기술</li>
<li>빠른 속도: 스크린의 모든 수직선에 대해 계산만 하면 됨<ul>
<li>과거 컴퓨터의 퍼포먼스 문제로 3D 엔진을 실시간으로 실행할 수 없던 시절 사용</li>
</ul>
</li>
</ul>
<p><strong>[RayTracing]</strong>
Object에서 나오는 빛의 광선을 추적해 렌더링</p>
<ul>
<li>3D 장면의 반사, 그림자를 지원하는 현실감있는 렌더링 기술</li>
<li>높은 해상도와 복잡한 장면 실시간 처리</li>
</ul>
<h1 id="📒ray-triangle-intersection">📒Ray-Triangle Intersection</h1>
<hr>
<p>: 광선 충돌 판단을 위해선 장면 내의 모든 물체의, 각 삼각메쉬마다, 광선과 충돌했는지 판단해야 함</p>
<ul>
<li>Moller-Trumbore 알고리즘 등을 통해 검출 가능</li>
</ul>
<h3 id="📌1-평면과-광선의-교차점-찾기">📌1. 평면과 광선의 교차점 찾기</h3>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/96e590e3-38fc-4186-aa91-8eca83f7ca94/image.png" alt=""></p>
<h3 id="📌2-삼각형-안의-점인지-판단하기">📌2. 삼각형 안의 점인지 판단하기</h3>
<ul>
<li>외적<ul>
<li>들어오는 벡터의 방향에 따라 외적의 위치가 바뀜</li>
<li>이를 이용해 내외부 판별</li>
<li>삼각형의 한 점 v0에서 다른 점 v1을 향하는 벡터 (변 표현)와, 
v0에서 교차점 p를 향하는 벡터를 외적</li>
<li>외적의 결과를 Normal 벡터와 내적시켜 방향 판단</li>
</ul>
</li>
<li>내적<ul>
<li>대상 벡터가 90도를 넘을 때 내적의 값이 음수가 됨</li>
<li>내적을 이용하면 간단하게 내외부 판별</li>
</ul>
</li>
<li>삼각형의 모든 점에 대해 내부로 판별된다면 삼각형 안의 점임</li>
</ul>
<h1 id="📒mouse-picking">📒Mouse Picking</h1>
<hr>
<p>: 카메라가 보는 화면 상에서 마우스를 클릭했을 때, 해당 픽셀의 3D World 좌표 구하기</p>
<h3 id="📌ray-setting">📌Ray Setting</h3>
<p>카메라에서 마우스의 위치로 향하는 Ray</p>
<ul>
<li>Start Point: Camera Pos</li>
<li>Dir: Mouse의 Screen 좌표(ScreenSpace)를 World 좌표로 이동<ol>
<li>NDC 좌표계 변환 (ScreenSpace: uv좌표계 --&gt; NDC좌표계)</li>
<li>ViewSpace에서 광선의 방향정보 구해줌</li>
<li>ViewSpace ➡️ WorldSpace 전환 (View inv matrix) </li>
</ol>
</li>
</ul>
<h3 id="📌raycasting-1">📌RayCasting</h3>
<p>카메라에서 마우스의 위치로 향하는 World Ray를 마우스 피킹할 오브젝트의 로컬로 보냄</p>
<ul>
<li>오브젝트와 광선의 교차점 구함</li>
<li>충돌 검사: 마우스 피킹할 오브젝트를 대상으로, 메쉬의 모든 면마다 Ray와 충돌했는지 검사</li>
</ul>
<p><strong>References</strong>
[1] RayTracing: <a href="https://github.com/Alegruz/alegruz.github.io/blob/main/Notes/2022/03/Korean/RayTracingEssentials.md">🔗github</a>
[2] RayCasting: <a href="https://github.com/365kim/raycasting_tutorial?tab=readme-ov-file">🔗github</a>
[3] Ray-Triangle Intersection: <a href="https://www.slideshare.net/wraithkim/1-249173329">https://www.slideshare.net/wraithkim/1-249173329</a>
[4] 삼각형 내부판단 : <a href="https://hwanggoon.tistory.com/114">https://hwanggoon.tistory.com/114</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[11. LOD & LandScape]]></title>
            <link>https://velog.io/@howru_dv/11.-LandScape</link>
            <guid>https://velog.io/@howru_dv/11.-LandScape</guid>
            <pubDate>Wed, 05 Jun 2024 08:16:25 GMT</pubDate>
            <description><![CDATA[<h1 id="📒level-of-detail-lod">📒Level Of Detail (LOD)</h1>
<hr>
<h3 id="📌what-is-level-of-detail">📌What is Level Of Detail?</h3>
<p>: 메시 모델링 데이터의 정밀도를 단계별로 조정하는 기술</p>
<ul>
<li>가까우면 메시를 세밀하게, 멀면 단순하게 표현</li>
<li>렌더링 속도(Speed)와 질(Quality)의 밸런싱<ul>
<li>실시간 렌더링 기술은 어느정도 퀄리티를 타협하더라도 빠른 렌더링이 중요함</li>
<li>가능한 좋은 퀄리티로(즉 타협을 덜 하면서) 빠르게 렌더링하기 위함</li>
</ul>
</li>
</ul>
<p><strong>[LOD 타입]</strong></p>
<ul>
<li>Static LOD</li>
<li>Dynamic LOD<ul>
<li>메시 분할</li>
<li>메시 간략화</li>
</ul>
</li>
</ul>
<h3 id="📌static-lod">📌Static LOD</h3>
<p>: 여러개의 메시를 준비해 사용<img src="https://velog.velcdn.com/images/howru_dv/post/9e5e5ff8-d5ca-4a5f-a599-4b95c70ffec2/image.png" alt=""></p>
<ul>
<li>카메라와 물체 간 거리를 측정해서 카메라와 가까운 거리에 있는 물체는 정밀한메시를 사용하고, 거리가 멀어질수록 낮은 단계의 메시를 사용</li>
<li>처음부터 메시의 정밀도가 정해져 있고, 이를 카메라와의 거리에 따라서 단계별로 바꿔가며 사용하는 것</li>
<li>장단<ul>
<li>장: 간단하므로 속도가 빠름</li>
<li>단: 메모리 낭비, 거리에 따라서 메시가 급격히 변할 때 튀는 현상(popping) 발생</li>
</ul>
</li>
</ul>
<h3 id="📌dynamic-lod">📌Dynamic LOD</h3>
<p>: 카메라와 물체의 거리에 따라서 실시간으로 메시의 정밀도를 변화시킴<img src="https://velog.velcdn.com/images/howru_dv/post/6b779e96-3abf-4f90-b07a-126fc671588a/image.jpg" alt=""></p>
<ul>
<li>메시 분할과 메시 간략화 두 타입으로 나뉨</li>
<li>장단<ul>
<li>장: 거리에 따라 LOD가 이루어지므로 튀는 현상(popping) 적음, 메모리 낭비 없음</li>
<li>단:<ul>
<li>느린 속도: 메시 분할, 간략화 등에 추가 연산이 필요</li>
<li>잦은 Lock-Unlock: 레벨이 바뀌거나 정점데이터를 갱신할 때 정점 계산을 동적으로 수행</li>
</ul>
</li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>DirectX11과 Tesellation</strong>
DirectX 11 버전부터는 GPU가 LOD를 처리해줘서, 따로 구현하지 않아도 된다.</p>
</blockquote>
<h1 id="📒dynamic-lod">📒Dynamic LOD</h1>
<hr>
<h3 id="📌lod-계산">📌LOD 계산</h3>
<p><strong>(1) 거리기반 LOD</strong>
: 시점 위치와 오브젝트의 거리를 이용해 단계 값을 구하는 방법</p>
<ul>
<li>구현이 간단하고 부하가 적음</li>
<li>필요없는 부분이 세밀하게 보이거나 세밀하게 보여야 하는 부분이 단순하게 보일 수 있음</li>
</ul>
<p>*<em>(2) 면적기반 LOD *</em>
: 오브젝트의 투영 면적에 따른 단계값을 구하는 방법</p>
<ul>
<li>자연스럽게 표현됨</li>
<li>많은 CPU 연산량: 투영 면적이 달라질 때마다 다시 계산</li>
</ul>
<h3 id="📌방법1-메시-간략화">📌(방법1) 메시 간략화</h3>
<p>: 폴리곤의 수를 줄이는 방법</p>
<ul>
<li>간략화할 기준을 세우고 모양을 최대한 유지한 상태에서 폴리곤의 수 제거</li>
<li>간략화 기준: 어느 폴리곤의 어느 꼭지점을 먼저 제거할 것인가 등</li>
<li>간략화 방법:<ul>
<li>점 제거(Vertex Decimation)</li>
<li>점 합치기(Vertex Clustering)</li>
<li>면 줄이기(Edege Colapse)</li>
</ul>
</li>
</ul>
<h3 id="📌방법2-메시-분할">📌(방법2) 메시 분할</h3>
<p>: 하나 폴리곤을 여러 개의 폴리곤으로 분할하는 방법</p>
<h3 id="📌균열-현상-crack">📌균열 현상 (Crack)</h3>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/0f64fdd7-f183-4dca-be12-91d293417f30/image.png" alt="">
하나의 단일 메시 속에 여러 단계의 패치가 존재할 때, 인접한 패치 간 분할 단계의 차이가 존재하는 경우 발생</p>
<ul>
<li>패치 단위로 분할 level을 잡는다면 level이 변하는 경계면에선 틈이 생김 (들림)</li>
</ul>
<p><strong>[Crack이 생기지 않게 하기]</strong></p>
<ul>
<li>방법1: 인접한 두 패치 가 서로 level이 다르더라도, 더 낮은 level의 패치쪽에선 맞닿는 면의 레벨을 높여줘야(맞춰줘야) 함</li>
<li>방법2: 패치 단위가 아닌, 거리에 따라 분할 level을 잡으면 자연스럽게 mapping 가능</li>
</ul>
<p><strong>[발생한 Crack을 매꾸기]</strong>
: 추가 삼각형을 발생한 Crack에 끼워넣기</p>
<ul>
<li>뗌질 삼각형을 LOD단계가 달라지는 모든 노드에 해서 상하좌우 네 가지 방향으로 만들어줌<img src="https://velog.velcdn.com/images/howru_dv/post/a96d70c3-1775-4754-ad34-1b41b0c7644a/image.jpg" alt=""><img src="https://velog.velcdn.com/images/howru_dv/post/1a643dcb-f3db-4254-9fe1-c2d91eae4f81/image.jpg" alt=""></li>
</ul>
<h3 id="📌poppiong-현상">📌poppiong 현상</h3>
<p>: 거리에 따라 폴리곤 수가 갑작스럽게 줄어들거나 늘어나면 그래픽이 튀어보이는 현상</p>
<ul>
<li>정적LOD사용시 급격한 레벨의 차이로 모양이 바뀌어 튀어보이는 현상</li>
<li>해결: 보간<ul>
<li>낮은 레벨에서 높은 레벨로 갈 때 사라지는 정점의 위치값을 level 간 차이에 대한 보간값 t를 구해 보간</li>
<li>정적LOD에서의 해결 : 실시간으로 데이터를 계산할때 t값을 구하고, 그에 따라 보간</li>
<li>동적LOD에서의 해결 : 두 level에서의 버텍스 버퍼를 모두 stream source로 보내고, t값을 세팅하여 버텍스 셰이더에서 두 버텍스를 보간</li>
</ul>
</li>
</ul>
<p><strong>[보간 예시]</strong>
<img src="https://velog.velcdn.com/images/howru_dv/post/9ef0cde6-963b-4ba9-ad47-76e7d317f834/image.jpg" alt="">
: level0 (0, 0), (10, 15), (20, 5)과 level1(0, 0), (20, 5)으로 구성된 직선이 있을 때
level1에서 존재하지 않는 점 (10, 15)를 level1에서의 가상의점 (10, 2.5)와 보간해야 함</p>
<p>현재 level이 0이고 보간값 t가 0.5라면
중간점은  0.5 * (10, 15) + 0.5 * (10, 2.5) = (10, 8.75)</p>
<h1 id="📒tesellation과-height-map">📒Tesellation과 Height map</h1>
<hr>
<p>: Height map을 참고해서 추가적으로 만든 정점들의 높이를 변경</p>
<ul>
<li>ex 지형텍스처가 표현하려고 했던 고해상도 지형 적용</li>
</ul>
<h3 id="📌displacement-mapping">📌Displacement Mapping</h3>
<ul>
<li>nomal mapping: 근본적으로 geometry를 조작하지 못함</li>
<li>tesellation: surfaces를 쪼개 만든 정점의 위치를 조작할 수 있음</li>
</ul>
<h3 id="📌setting">📌Setting</h3>
<p><strong>[Mesh]</strong>
: Tesellation level의 차이를 주려면 patch를 필요한 값으로 세팅해줘야 함
즉, mesh를 새로 만들어 써야 함</p>
<ul>
<li><p>Face: 기본적으로 mesh를 쪼개는(patch) 줄 수</p>
</li>
<li><p>UV</p>
<ul>
<li>Mesh의 사각형 하나(patch 2개) 당 0~1</li>
<li>전체를 0~1로 보지 않음 주의</li>
<li>즉 왼쪽 위가 0,0, 오른쪽 아래가 Face,Face
<img src="https://velog.velcdn.com/images/howru_dv/post/a8d738a0-6a86-404e-bcae-8a89a4af70ff/image.png" alt=""></li>
</ul>
</li>
<li><p>렌더링 시점: deferred rendering</p>
</li>
</ul>
<p><strong>[height map]</strong></p>
<ul>
<li>픽셀 포맷: R32<ul>
<li>r: height</li>
<li>흑백으로만 표현됨</li>
</ul>
</li>
<li>shader<ul>
<li>UV: 전체 기준</li>
<li>normal: shader에서 재계산 필요</li>
</ul>
</li>
</ul>
<h3 id="📌normal-재계산">📌normal 재계산</h3>
<p>: height map을 그대로 적용시키면 height는 적용되지만,
모든 vertex의 normal은 여전히 같은 방향이므로 명암의 차이가 존재하지 않음</p>
<p><strong>[Normal 구하기]</strong></p>
<ul>
<li>바로 주변 정점의 높이를 통해 현재 접하는 면의 Tangent와 Binormal을 도출 가능</li>
<li>이를 통해 Normal 구함</li>
</ul>
<p><strong>[변화량 도출]</strong></p>
<ul>
<li>정점 간 간격 변화량<ul>
<li>Inside Level로 정점 간 이동 간격 추측</li>
<li><code>정점 간 간격 변화량 = 1 / pathLevel.Inside</code></li>
</ul>
</li>
<li>정점 간 UV 변화량<ul>
<li><code>UV 간 변화량 = 1 / FaceXY * 정점 간 간격</code></li>
</ul>
</li>
<li>계산 좌표계<ul>
<li>world에서 scale이 적용되면 높이가 변하므로, world 좌표계에서 계산해야 함</li>
<li>(주의) 계산 후 WV matrix 곱하는 것과 결과 다름!!<img src="https://velog.velcdn.com/images/howru_dv/post/b2bee5ed-1955-4ce5-b11d-5671d51a7840/image.png" alt=""></li>
</ul>
</li>
</ul>
<h3 id="📌landscape">📌LandScape</h3>
<p>: height map으로 적용시킬 texture를 실시간으로 수정해서, 지형을 만드는 것</p>
<ul>
<li>height tex 수정</li>
<li>albedo tex 수정</li>
</ul>
<p><strong>References</strong>
[1] LOD: <a href="https://blog.naver.com/ssod015/220272372528">https://blog.naver.com/ssod015/220272372528</a>
[2] Height Map: <a href="https://victorbush.com/2015/01/tessellated-terrain/">https://victorbush.com/2015/01/tessellated-terrain/</a>
[3] LandScape: <a href="https://victorbush.com/2015/01/tessellated-terrain/">https://victorbush.com/2015/01/tessellated-terrain/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[10. Frustum Culling]]></title>
            <link>https://velog.io/@howru_dv/10.FrustomCulling</link>
            <guid>https://velog.io/@howru_dv/10.FrustomCulling</guid>
            <pubDate>Sun, 19 May 2024 20:31:25 GMT</pubDate>
            <description><![CDATA[<p>: 모든 정보를 GPU로 보내는 대신 보이는 요소와 보이지 않는 요소를 정렬하고,
보이는 요소만 렌더링하는 최적화 기법</p>
<ul>
<li>평면의 방정식 기법 사용</li>
</ul>
<h1 id="📒평면의-방정식">📒평면의 방정식</h1>
<hr>
<p><strong>1. 어떤 벡터와 평면의 노말벡터의 내적이 0이라면 두 벡터는 수직임</strong>
<img src="https://velog.velcdn.com/images/howru_dv/post/7b7d0996-b31f-4a10-a1a0-02b1af3117ee/image.png" alt=""></p>
<ul>
<li>수직하는 두 벡터 간의 내적값은 0<blockquote>
<p><strong>(복습) 내적 Inner Product</strong>
: 투영</p>
<ul>
<li>각 성분의 합</li>
</ul>
</blockquote>
</li>
<li>평면 위의 벡터와 평면의 노말벡터는 수직임<ul>
<li>평면 위의 벡터: 평면 위의 두 점 사이에 존재하는 방향벡터</li>
</ul>
</li>
<li>평면 위의 아무 점들 간 방향벡터와 평면의 노말벡터는 수직임<ul>
<li>즉 평면의 방향벡터와 노말벡터의 내적값은 항상 0으로 같음</li>
<li>즉 어떤 벡터와 평면의 노말벡터의 내적이 0이라면 두 벡터는 수직임</li>
</ul>
</li>
</ul>
<p><strong>2. 원점이 아닌 곳에 존재하는 평면</strong>
<img src="https://velog.velcdn.com/images/howru_dv/post/31d9126d-0373-4833-950a-f3c8b22ab17d/image.png" alt=""></p>
<ul>
<li>Normal 판단<ul>
<li>평면 위의 방향벡터 V1과, V1의 Tangent vector인 V2까지 두 벡터가 필요함</li>
<li>즉 평면 위의 점 3개가 필요함</li>
</ul>
</li>
<li>원점 O로부터 떨어진 거리 D<ul>
<li>평면 위의 점을 노멀벡터로 내적하면(투영하면) D의 길이를 구할 수 있음</li>
</ul>
</li>
<li>평면의 위치 판단<ul>
<li><code>D = 0</code>: 평면이 원점에 위치함</li>
<li><code>D &gt; 0</code> or <code>D &lt; 0</code>: 평면이 원점에 위치하지 않음</li>
</ul>
</li>
<li>평면의 방정식: <code>Ax + By + Cz + D</code></li>
</ul>
<p><strong>3. 임의의 정점과 평면</strong>
<img src="https://velog.velcdn.com/images/howru_dv/post/6ed3750c-c6f9-4c63-b717-6b72db59e34c/image.png" alt=""></p>
<ul>
<li>임의의 점과 원점 사이의 거리<ul>
<li>임의의 점과 평면의 노말벡터를 내적한 값 (자료상 SD)</li>
</ul>
</li>
<li>원점으로부터 거리 비교<ul>
<li>평면: D</li>
<li>임의의 점: SD</li>
<li>즉, D와 SD를 비교하면 임의의 점이 평면으로부터 떨어진 방향을 구할 수 있음</li>
</ul>
</li>
<li>점과 평면의 관계<ul>
<li><code>SD &gt; D</code> : 평면 밖</li>
<li><code>SD = D</code> : 평면 위</li>
<li><code>SD &lt; D</code> : 평면 안</li>
</ul>
</li>
<li>점과 평면의 방정식<ul>
<li>즉, 평면의 방정식을 알고 있다면 대입해서 쉽게 연산 가능<ul>
<li>평면의 방정식의 계수를 알고 있다면 내적해서 값 얻을 수 있음</li>
<li>내적: 각 성분의 곱</li>
</ul>
</li>
<li><code>대입값(내적 + D) &gt; 0</code> : 평면 밖</li>
<li><code>대입값(내적 + D) = 0</code> : 평면 위</li>
<li><code>대입값(내적 + D) &lt; 0</code> : 평면 안</li>
</ul>
</li>
</ul>
<h1 id="📒frustum-culling">📒Frustum Culling</h1>
<hr>
<p>: 카메라 시야 범위 즉, 절두체 안에 들어오지 않으면 rendering을 걸지 않는 최적화 방식</p>
<ul>
<li>CPU 차원에서 검사</li>
</ul>
<h3 id="📌절두체-검사">📌절두체 검사</h3>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/1f58dee1-c2ed-4693-ace1-26ba8a866d52/image.png" alt="">
: 절두체의 각 면마다 평면의 방적식 안밖검사, 총 6번 (6면) 검사</p>
<ul>
<li>한 면이라도 통과하지 못하는 경우 카메라에 들어오지 않음<ul>
<li>즉 렌더링 않음</li>
</ul>
</li>
</ul>
<h3 id="📌평면의-방정식-판단">📌평면의 방정식 판단</h3>
<p>: 평면과 현재 좌표(점)의 관계 연산</p>
<ul>
<li>D &gt; P·N : 원점과 평면 사이에 있음</li>
<li>D = P·N : 평면에 있음</li>
<li>D &lt; P·N : 원점과 평면 외부에 있음</li>
</ul>
<h3 id="📌bounding-box">📌Bounding Box</h3>
<p>: 시야각에서 중심은 벗어났지만, 부피가 커서 시야 안에 들어오는 경우</p>
<ul>
<li>문제: 오브젝트의 중심좌표만 체크하는 경우</li>
<li>해결: 물체마다 제일 큰 동작 기반으로 벗어남 인정해주는 값 지정</li>
</ul>
<p><strong>References.</strong>
[1] 평면의 방정식: <a href="https://m.blog.naver.com/ldj1725/220062476672">https://m.blog.naver.com/ldj1725/220062476672</a>
[2] Frustum Culling: <a href="https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling">https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling</a>
[3] Frustum Culling: <a href="https://sanghoon23.tistory.com/86">https://sanghoon23.tistory.com/86</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[09. Tesellation]]></title>
            <link>https://velog.io/@howru_dv/09.Tesellation</link>
            <guid>https://velog.io/@howru_dv/09.Tesellation</guid>
            <pubDate>Sun, 19 May 2024 19:29:26 GMT</pubDate>
            <description><![CDATA[<h1 id="📒tesellation">📒Tesellation</h1>
<hr>
<p>: Hull &amp; Domain Shader</p>
<ul>
<li>DX11부터 추가된 pipeline 단계</li>
<li>정점을 추가해 폴리곤을 세분화하고 쪼갬
<img src="https://velog.velcdn.com/images/howru_dv/post/f3d448f3-c82d-479d-b727-d23e955a8cb8/image.webp" alt=""></li>
</ul>
<h3 id="📌setting">📌Setting</h3>
<ul>
<li>Topology<ul>
<li>Vtx를 분석하는 위상</li>
<li>Tesselation 전용 Topology 사용</li>
<li><code>D3D11_PRIMITIVE_TOPOLOGY_N_CONTROL_POINT_PATCHLISHT</code><ul>
<li>ex, N==3 이라면 제어점 3개짜리 patch list</li>
</ul>
</li>
</ul>
</li>
<li>edge<ul>
<li>edge idx: idxed Vtx가 마주보는 변</li>
</ul>
</li>
<li>mesh: 대칭구조 필요</li>
</ul>
<h3 id="📌control-point--patch">📌Control Point &amp; Patch</h3>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/1110c27c-927c-4640-8126-b9d436b446e4/image.png" alt=""></p>
<p><strong>[Control Point]</strong>
: 삼각형을 넘겨준다고 가정할 때, 각 정점에 해당하는 점</p>
<ul>
<li>내부를 제어하는 점</li>
<li>제어점은 중간의 다른 정점을 생성하기 위한 기준점임</li>
</ul>
<p><strong>[Patch]</strong>
: 삼각형을 넘겨준다고 가정할 때, Control Point 세 개가 모인 set 자체</p>
<ul>
<li>control point의 그룹</li>
</ul>
<h1 id="📒pipeline">📒PipeLine</h1>
<hr>
<h3 id="📌tesellation-pipeline">📌Tesellation Pipeline</h3>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/d58aeb3f-2c33-40e2-a693-5cb30753bb1d/image.png" alt=""></p>
<p><strong>[Vertex Shader]</strong>
: 원본 Vertex의 input - output</p>
<ul>
<li>Tesellation에서는 Domain Shader가 진짜 vertex 처리<ul>
<li>즉 VS는 딱히 하는 일 없음</li>
</ul>
</li>
<li>ex, 사각형 그리기위해 2개 삼각형 구성하는 상황) : 6개 output</li>
</ul>
<p><strong>[Hull Shader]</strong>
: 원본 Vertex를 n개씩 묶어 patch라는 하나의 조각으로 묶음</p>
<ul>
<li>n: 사용자가 설정, 대체로 3(삼각형) 사용</li>
<li>ex, 사각형 그리기위해 2개 삼각형 구성하는 상황) : 2개 output</li>
</ul>
<p><strong>[Tesellation Stage]</strong>
: 추가적인 정점 생성함</p>
<ul>
<li>DX 내부적으로 수행, 직접 건드릴 수 없음</li>
<li>patch constant function만 정의 가능</li>
<li>patch constant function:<ul>
<li>패치당 한 번씩 호출되는 함수</li>
<li>원하는 정점 개수 세팅</li>
</ul>
</li>
</ul>
<p><strong>[Domian Shader]</strong>
: 새로 생긴 Vtx까지 포함해서, 모든 Vtx에 대해 호출 후 전처리</p>
<ul>
<li>원래 VS에서 하던 일 담당</li>
</ul>
<h3 id="📌tesellation-vs-geometry">📌Tesellation vs Geometry</h3>
<blockquote>
<p><strong>[(복습) Geometry Shader]</strong>
: 추가적인 분할 진행</p>
</blockquote>
<p>: Tesellation과 Geometry 모두 정점을 분할하는 기능을 가지므로, 보통 함께 사용하진 않음</p>
<ul>
<li>정점 대량 생산의 경우: Tesellation 활용<ul>
<li>ex, 지형생성</li>
</ul>
</li>
<li>정점 소량 생산의 경우: Geometry Shader 활용<ul>
<li>ex, billboard 효과</li>
</ul>
</li>
</ul>
<h1 id="📒hull-shader-state">📒Hull Shader State</h1>
<hr>
<p>: 각 입력 패치(사각형, 삼각형 또는 선)에 해당하는 기하 도형 패치(및 패치 상수)를 생성하는 단계</p>
<ul>
<li>각 패치(SV_PrimitiveID)에 대해 출력 제어점(SV_OutputControlPointID) 당 한 번 호출</li>
</ul>
<h3 id="📌hullshader-실행단계">📌HullShader 실행단계</h3>
<p>: 크게 두 단계로 나뉨</p>
<ul>
<li>제어점 단계<ul>
<li>각 제어점에 대해 한 번 작동</li>
<li>패치를 위한 제어점을 읽고, 하나의 출력 제어점 생성<ul>
<li>출력 제어점은 ControlPointID로 식별됨</li>
</ul>
</li>
</ul>
</li>
<li>패치 상수 단계<ul>
<li>패치당 한 번씩 작동</li>
<li>가장자리 공간 분할 요인 및 기타 패치별 상수 생성</li>
</ul>
</li>
</ul>
<h3 id="📌hullshader-func-define">📌HullShader Func Define</h3>
<p><strong>[description]</strong>
: 컴파일에 필요한 description 필요</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/windows/win32/direct3d11/direct3d-11-advanced-stages-hull-shader-design">https://learn.microsoft.com/en-us/windows/win32/direct3d11/direct3d-11-advanced-stages-hull-shader-design</a></li>
<li>대표적인 description<ul>
<li>patch constant func: 컴파일할 함수</li>
<li>outputtopology</li>
<li>outputcontrolpoints</li>
<li>domain</li>
<li>partioning: 분할 자료형<ul>
<li>float형을 쓰면 더 세밀한 분할 가능</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>[paramater]</strong>
: 같이 소속된 patch의 정점들이 함께 들어옴</p>
<ul>
<li>InputPatch: patch의 원본 정점들 (VS return type)</li>
<li>SV_OutputControlPointID: patch 내 호출된 idx</li>
</ul>
<blockquote>
<p><strong>[TIP] Sementics</strong>
 SV_Position은 rasterizer에서 사용하는 sementic이기 때문에, HS에선 사용 불가능함</p>
</blockquote>
<h3 id="📌patch-constant-function">📌patch constant function</h3>
<p>: 어떻게 분할할지 설정하는 함수</p>
<ul>
<li>실행: Tesselation Stage<ul>
<li>Hull Shader &gt; Tesselation Stage &gt; Domain Shader</li>
</ul>
</li>
<li>패치 당 한 번씩 호출<ul>
<li>즉 Vtx의 idx가 필요하지 않음</li>
</ul>
</li>
</ul>
<p><strong>[paramater]</strong></p>
<ul>
<li>InputPatch: patch의 원본 정점들 (VS return type)</li>
<li>SV_PrimitiveID: patch의 ID</li>
</ul>
<p><strong>[retun type]</strong>
: patch의 분할 레벨</p>
<ul>
<li>SV_TessFactor: edge당 control 갯수</li>
<li>SV_InsideTessFactor: 내부 control 갯수</li>
</ul>
<h1 id="📒tesselation-state">📒Tesselation State</h1>
<hr>
<p>: 더 세밀한 표현을 위해 공간 분할 요소를 사용하여 각 패치를 세분화하는 단계</p>
<ul>
<li>패치당 한 번 작동</li>
<li>프로그래밍 불가</li>
</ul>
<h1 id="📒domain-shader">📒Domain Shader</h1>
<hr>
<p>: 원본 정점 포함 모든 정점에 대해 호출해 세분화된 위치 계산하는 단계</p>
<ul>
<li>출력 지점당 한 번 실행</li>
</ul>
<h3 id="📌보간">📌보간</h3>
<p>: 보간된 값이 들어오지 않고, 대신 가중치값이 들어오므로 직접 보간해서 값 구해야 함
<img src="https://velog.velcdn.com/images/howru_dv/post/55c9a189-af7c-451e-8ed3-f278af2b4b15/image.png" alt=""></p>
<ul>
<li>원본 정점: 패치의 원본 정점 먼저 들어옴</li>
<li>가중치: 보간된 값이 아닌, 원본 정점에 대한 가중치 값이 들어옴<ul>
<li>가중치를 사용해서 정점 계산해야 함</li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>(복습) Pixel Shader</strong>
: 호출된 픽셀의 값이 알아서 보간되어 들어왔음</p>
</blockquote>
<h3 id="📌domainshader-func-define">📌DomainShader Func Define</h3>
<p><strong>[description]</strong>
: 컴파일에 필요한 description 필요</p>
<ul>
<li>domain : 들어오는 단위<ul>
<li>ex, 3개 정점을 가진 삼각형을 단위로 들어옴 명시</li>
</ul>
</li>
</ul>
<p><strong>[paramater]</strong></p>
<ul>
<li>patch Level: HullShader에서 설계한 각 패치의 분할 레벨</li>
<li>OutputPach : 원본 정점들</li>
<li>SV_DomainLocation : 해당 Vtx에서 사용할 가중치</li>
</ul>
<h1 id="📒tesellation의-이점">📒Tesellation의 이점</h1>
<hr>
<p>📌성능 개선</p>
<ul>
<li>GPU를 통해 low-detail subdivision surface를 high-detail subdivision surface로 변환</li>
<li>CPU에서 high-resolution 모델을 올리는 방식: 엄청난 부하 발생</li>
</ul>
<p>📌Displacement Mapping</p>
<ul>
<li>nomal mapping: 근본적으로 geometry를 조작하지 못함</li>
<li>tesellation: surfaces를 쪼개 만든 정점의 위치를 조작할 수 있음
<img src="https://velog.velcdn.com/images/howru_dv/post/207411cd-a960-4238-966f-15cdd8364fff/image.png" alt=""></li>
</ul>
<p><strong>References</strong>
[1] Hull Shader MS Doc: <a href="https://learn.microsoft.com/en-us/windows/uwp/graphics-concepts/hull-shader-stage--hs-">https://learn.microsoft.com/en-us/windows/uwp/graphics-concepts/hull-shader-stage--hs-</a>
[2] Domain Shader MS Doc: <a href="https://learn.microsoft.com/en-us/windows/uwp/graphics-concepts/domain-shader-stage--ds-">https://learn.microsoft.com/en-us/windows/uwp/graphics-concepts/domain-shader-stage--ds-</a>
[3] Tessellation: <a href="https://develop-4-art.tistory.com/11">https://develop-4-art.tistory.com/11</a>
[4] Tessellation: <a href="https://song-ift.tistory.com/450">https://song-ift.tistory.com/450</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[08. Shadow]]></title>
            <link>https://velog.io/@howru_dv/08.3DShadow</link>
            <guid>https://velog.io/@howru_dv/08.3DShadow</guid>
            <pubDate>Sun, 19 May 2024 17:27:09 GMT</pubDate>
            <description><![CDATA[<h1 id="📒shadow">📒Shadow</h1>
<hr>
<h3 id="📌개념적-흐름">📌개념적 흐름</h3>
<ol>
<li>Depth Map 생성<ul>
<li>광원 기준 샷 따로 찍음 : 깊이 저장</li>
</ul>
</li>
<li>Depth Map 투영<ul>
<li>메인카메라가 보는 월드를 다시 전역광원 깊이샷에 투영시켜봄</li>
<li>광원에서 볼 수 있는지, 즉 그림자지는 부분인지 아닌지 판단
<img src="https://velog.velcdn.com/images/howru_dv/post/70135546-9544-4357-8d37-778e41c23821/image.png" alt=""></li>
</ul>
</li>
</ol>
<blockquote>
<p><strong>(복습) scene 찍기</strong></p>
</blockquote>
<ul>
<li><code>tick:</code> shader domain의 obj들을 따로 모아둠</li>
<li><code>render:</code> 모은 그룹의 각 obj마다 render 호출</li>
<li><code>shader:</code><ul>
<li>세팅한 RT &amp; DST에다가,</li>
<li>각 VS에서 들어온 Vtx의 local 값을 ➡️ WVP 행렬 연산해 Screen 좌표로 보내 얻은</li>
<li>본인의 위치에 값 연산해 그림</li>
<li>그룹의 모든 obj마다 반복</li>
</ul>
</li>
<li>해당 shader domain 그룹의 texture 완성!<ul>
<li>모든 그룹마다 위 과정 수행<blockquote>
<p>: 즉, 그림자를 생성하는 obj를 모아 shader depth map을 그리는 render 호출하면, 각 obj마다 shadow depth shader를 통해 light에서 바라보는 모습을 그려, shadow depth texture를 완성함</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<h3 id="📌setting">📌Setting</h3>
<p><strong>[ShadowDepth MRT]</strong></p>
<ul>
<li>ShadowDepth Tex (RT)<ul>
<li>Texture 해상도:<ul>
<li>화면에 그리는 용도가 아닌 Shader용으로 제작하기 때문에 화면크기와 달라도 됨<ul>
<li>Texture의 최대크기: 8192</li>
</ul>
</li>
<li>Directinal Light: 월드 전체를 그려야 하므로 해상도가 커야 함</li>
<li>Point Light: 정해진 range 안의 물체만 그리므로 작아도 괜찮음(512~1024)</li>
</ul>
</li>
</ul>
</li>
<li>DepthStencil Tex<ul>
<li>RT와 같은 해상도의 DS용 Tex 따로 생성</li>
</ul>
</li>
</ul>
<h3 id="📌shadow-drawing">📌Shadow Drawing</h3>
<ol>
<li><p>Viewport 설정</p>
<ul>
<li><p>Viewport 크기와 Render Target 크기: </p>
<ul>
<li>처음부터 RT 크기가 아닌 Viewport 설정(크기)에 맞춰서 그려짐</li>
<li>즉, Viewport와 Render Target의 크기가 다를 때 늘어나거나 줄어드는 개념이 아니라</li>
<li>RenderTarget에서 Viewport만큼의 크기에 렌더링되는 것</li>
</ul>
</li>
<li><p>Viewport 설정 단계: Rasterizer 이전</p>
<ul>
<li>Viewport는 Rasterizer 단계에 영향을 줌</li>
<li>MRT가 Viewport Size를 들고 있어야 함</li>
</ul>
</li>
<li><p>Viewport의 크기가 제대로 세팅되지 않는다면</p>
<ul>
<li>Rasterizer: Viewport만큼의 크기에 호출시켜줌</li>
<li>RT Copy: 전체 Render Target 영역을 대상으로 호출됨
<img src="https://velog.velcdn.com/images/howru_dv/post/e3b28083-24ea-4dc8-a31d-65661fe5a62d/image.png" alt=""></li>
</ul>
</li>
</ul>
</li>
<li><p>ShadowDepth rendering
: 광원 시점에서 물체의 깊이 그림</p>
<ul>
<li><p>광원 시점 View &amp; Proj 행렬을 통해 물체의 깊이 그림</p>
<ul>
<li>카메라 컴포넌트에서 구현해뒀으므로</li>
<li>Light3D에서 CamObj를 들고 행렬 계산용으로만 사용하도록 설계</li>
</ul>
</li>
<li><p>Proj Type</p>
<ul>
<li>Directional Light: 직교투영<ul>
<li>DirLight는 태양광이므로 모두 같은 방향을 가져야 함</li>
<li>태양은 멀리 떨어져 있으므로 월드값 즉, _근소한 값의 차이_에 차이 발생 않음</li>
</ul>
</li>
<li>Point Light: 원근투영</li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>Shadow depth texture의 각 Pixel</strong></p>
</blockquote>
<ul>
<li>position : Light가 바라보는 관점 기준</li>
<li>기록정보 :<ul>
<li><code>r</code> : depth, Light로부터 떨어진 정도 기록</li>
</ul>
</li>
</ul>
</li>
<li><p>Shadow Shading</p>
<ul>
<li>Light가 추가적으로 필요한 정보 (바인딩)<ul>
<li>Shadow Depth Tex</li>
<li>Light ViewProj mat</li>
</ul>
</li>
<li>그림자 지는 부분 확인
: Pixel Shader에서 현재 픽셀의 위치를 Shadow Depth Tex로 투영해 그림자 지는 부분인지 판단<ul>
<li>변환행렬: <code>pixel 위치</code> * <code>View Inv mat</code> * <code>Light ViewProj mat</code></li>
</ul>
</li>
<li>판단<ul>
<li>Shadow Depth Tex로 투영해 추출한 값(Depth)이 예상한 값보다 더 앞이라면, 즉 추출값이 계산값보다 더 작다면</li>
<li>앞에 빛을 가리는 물체가 있었음</li>
<li>즉 그림자지는 부분</li>
<li>보정값(Magic Number): 실수계산이라 작은 오차가 존재할 수 있으므로 값 보정해서 인정</li>
</ul>
</li>
</ul>
</li>
</ol>
<h3 id="📌alising">📌Alising</h3>
<p>  : Directional Light의 경우 깨짐현상 발생</p>
<ul>
<li>이유<ul>
<li>이유1: Directional Light가 멀리서 찍기 때문에, 확대했을 때 깨짐</li>
<li>이유2: deferred라서 Anti-Alising 처리가 안됨</li>
</ul>
</li>
<li>해결: 별도의 단계<ul>
<li>그림자만 처리하는 단계 분리해야 함</li>
<li>이후 blur 등으로 직접 처리</li>
</ul>
</li>
</ul>
<h3 id="📌광원의-범위를-벗어나는-경우">📌광원의 범위를 벗어나는 경우</h3>
<p>: 광원의 범위를 벗어나서 그림자가 갑자기 사라지면 어색해 보임</p>
<ul>
<li>방법1: 그림자 그리지 않기</li>
<li>방법2: follow (dynamic의 경우)<ul>
<li>dynamic light는 main cam을 따라다님</li>
</ul>
</li>
<li>방법3: 광원 반복배치 (static의 경우)<ul>
<li>광원을 반복적으로 배치해서 연속적으로 그림자 그려줌</li>
</ul>
</li>
</ul>
<h3 id="📌애니메이션-그림자">📌애니메이션 그림자</h3>
<ul>
<li>광원은 TPose를 받지만 애니메이션을 플레이하는 경우</li>
<li>그림자를 찍을 때 Skinning작업을 해줘야 함</li>
</ul>
<h1 id="📒-point-light-shadow">📒 Point Light Shadow</h1>
<hr>
<p>: Dir Light와는 달리 그림자가 육면체형태로 6번 판정 및 렌더링 돌아야 함</p>
<ul>
<li>최적화: Geometry 셰이더<ul>
<li>하나의 시점에서 여러방향 뽑을 수 있음</li>
</ul>
</li>
</ul>
<h1 id="📒-최적화">📒 최적화</h1>
<hr>
<h3 id="📌static-object-vs-dynamic-object">📌Static Object vs Dynamic Object</h3>
<p>[Object Type]</p>
<ul>
<li>static: 처음 1회 그림자 그려 사용</li>
<li>dynamic: 매 틱 그림자 그려 사용</li>
</ul>
<p>[Object Shadow Option]</p>
<ul>
<li>enable: 그림자 생기는 오브젝트</li>
<li>disable: 그림자 생기지 않는 오브젝트</li>
</ul>
<p>[Light Shadow Option]</p>
<ul>
<li>enable: 그림자 만드는 빛</li>
<li>disable: 그림자 만들지 않는 빛</li>
</ul>
<h3 id="📌최적화">📌최적화</h3>
<p>: 그림자를 그리기 위해선 결국 렌더링 횟수가 증가하니 프레임드랍 발생함</p>
<ul>
<li>움직이지 않는 것, static한 물체들은 미리 (한 번) 그려놓고 다시 그리지 않음</li>
<li>변형이 있는 물체, dynamic한 물체들만 계속 다시 그림</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[07. Decal Rendering]]></title>
            <link>https://velog.io/@howru_dv/07.DecalRendering</link>
            <guid>https://velog.io/@howru_dv/07.DecalRendering</guid>
            <pubDate>Sun, 12 May 2024 20:48:33 GMT</pubDate>
            <description><![CDATA[<h1 id="📒decal-projection">📒Decal (Projection)</h1>
<hr>
<p>: VolumeMesh가 교차하는 다른 Object에 Texture 투영</p>
<ul>
<li>Deffered Rendering 사용</li>
<li>ex) 발자국 자국, 총알 자국, 문신
<img src="https://velog.velcdn.com/images/howru_dv/post/ed4676ee-8642-43b6-bcc4-deedb40465a3/image.png" alt=""></li>
</ul>
<h3 id="📌setting">📌Setting</h3>
<ul>
<li>Shader domain : Decal domain 추가<ul>
<li>렌더링 시점: Deffered 이후, Lighting 이전</li>
</ul>
</li>
<li>Render Target (MRT): Decal MRT 생성</li>
<li>DepthStencil State: NoTest NoWrite</li>
<li>culling: CULL-FRONT<ul>
<li>VolumeMesh 안으로 카메라가 들어갔을 때도 렌더링되어야 함</li>
<li>Lighting을 CULL-FRONT한 것과 같은 이유</li>
</ul>
</li>
</ul>
<h3 id="📌shading">📌Shading</h3>
<p>: VolumeMesh와 교차하는 면의 PixelShader만 호출되어야 함</p>
<ul>
<li>PointLight의 Shading 접근법과 유사</li>
<li>VolumeMesh의 내부 판단<ol>
<li>Texture Sampling 값 보정<ul>
<li><code>-0.5</code> ~ <code>+0.5</code> ➡️ ~ <code>-1.0</code> ~ <code>+1.0</code></li>
</ul>
</li>
<li>보정한 값으로 UV sampling<ul>
<li>표면의 normal이 Y축을 향하도록 바닥에 깔려있으므로 XZ축 사용</li>
</ul>
</li>
</ol>
</li>
</ul>
<h1 id="📒additional-decal-mrt-op">📒Additional Decal MRT Op</h1>
<hr>
<h3 id="📌emissive-texture">📌Emissive Texture</h3>
<p>: 자체적으로 발광하는 텍스처</p>
<ul>
<li>Blend State<ul>
<li>상황:<ul>
<li>Color는 AlphaBlend 필요</li>
<li>Light(Emissive Tex)는 OneOneBlend 필요</li>
</ul>
</li>
<li>Decal 전용 Blend State 생성<ul>
<li>BLEND_DESC.IndependentBlend = Enable</li>
<li>Render Target마다 독립적으로 Blend State 설정하는 플래그</li>
</ul>
</li>
</ul>
</li>
<li>Emissive Tex 처리: Merge</li>
</ul>
<h3 id="📌normal-map">📌Normal Map</h3>
<p>: Normal Map 등을 사용해서 표면 거칠기 덮어씌우기 가능</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[06. Deferred Rendering]]></title>
            <link>https://velog.io/@howru_dv/06.DefferedRendering</link>
            <guid>https://velog.io/@howru_dv/06.DefferedRendering</guid>
            <pubDate>Sun, 12 May 2024 20:14:19 GMT</pubDate>
            <description><![CDATA[<h1 id="📒deferred-rendering">📒Deferred Rendering</h1>
<hr>
<p>: 지연 렌더링</p>
<ul>
<li>Deferred: 연기된, 지연된</li>
</ul>
<h3 id="📌foward-rendering">📌Foward Rendering</h3>
<p>Straight Forward Shading. 
렌더링 파이프라인을 1번만 거쳐서 GPU Back Buffer(GBuffer)에 바로 렌더링</p>
<ul>
<li>Mesh 하나를 그릴 때마다 모든 계산을 시행</li>
<li>라이팅 계산: Mesh의 수에 비례<ul>
<li>불필요한 연산 발생: 빛의 영향을 받지 않은 Mesh에 대해서도 연산</li>
</ul>
</li>
</ul>
<h3 id="📌deferred-rendering">📌Deferred Rendering</h3>
<p>: 렌더링 파이프라인을 크게 2번 거쳐 렌더링 (Two Pass Algorithm)</p>
<ul>
<li><p>Foward Rendering의 단점을 보완한 렌더링 기법으로, 멀티 렌더 타겟 사용</p>
</li>
<li><p>Two Pass</p>
<ul>
<li><strong>First Pass</strong>
: Gbuffer라고 칭하는 여러개의 버퍼에 오브젝트 정보 렌더링<ul>
<li>Diffuse, Screen Space Normal, Specular, Smoothness, Screen Space Depth등의 정보를 기록해 사용함</li>
</ul>
</li>
<li><strong>Second Pass</strong>
: 기록된 정보들을 토대로 셰이딩 연산 (라이팅 연산)<ul>
<li>모든 오브젝트들의 GBuffer을 렌더링한 후(Deffered) 라이팅 계산함</li>
<li>즉, 한 번에 렌더링이 완료되지 않고</li>
<li>기록된 오브젝트의 정보들을 사용해 렌더링 완료함</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>[장점]</strong></p>
<ul>
<li>특정 정보만 따로 분리해 다룰 수 있으므로</li>
<li>특정 영역에 관한 추가적인 연산, 효과 적용 가능</li>
<li>광원을 많이 사용하는 경우 Forward보다 빠를 수 있음<ul>
<li>겹친 픽셀을 포함해 모든 픽셀마다 Light 연산을 하는 대신 Light마다 한 번의 연산만 진행</li>
</ul>
</li>
</ul>
<p><strong>[단점]</strong></p>
<ul>
<li>광원을 적게 사용하는 경우 Forward보다 느림<ul>
<li>더 많은 렌더링 횟수</li>
<li>더 많은 메모리 사용 (Texture)</li>
</ul>
</li>
<li>반투명한 물체 처리가 어려움<ul>
<li>PASS1에서 한 오브젝트의 값으로 모든 데이터를 결정하므로 겹쳐있는 오브젝트 처리가 어려움</li>
</ul>
</li>
<li>Anti-Aliasing 성능 하락<ul>
<li>MSAA같은 anti-aliasing은 하드웨어 Rasterization 단계에서 수행됨</li>
<li>Deferred Shading에서는 Frist Pass에서만 Rasterization 수행</li>
<li>Second Pass는 GBuffer결과물을 사용하기만 하므로 Rasterization 수행되지 않으므로 AA 적용 불가능</li>
<li>이러한 이유로 Deferred Shading은 Light계산이 이루어지기 전에 AA을 적용하므로 최종 결과물이 예상한 값과 다르게 나올 수 있음</li>
</ul>
</li>
</ul>
<h1 id="📒deferred에서의-lighting">📒Deferred에서의 Lighting</h1>
<hr>
<p>: Deferred rendering을 적용하면 광원에 대한 연산만을 따로 다룰 수 있음</p>
<ul>
<li>라이트가 미치는 영향을 따로 기록</li>
<li>빛 번짐, Bloom 등과 같은 기능을 사용하기 쉬워짐</li>
</ul>
<h3 id="📌forward-lighting과의-연산흐름-차이">📌Forward Lighting과의 연산흐름 차이</h3>
<p>: (Deferred) 화면 결정 후 -&gt; 라이팅 연산</p>
<ul>
<li>Forward Shading:
한 pixel위치에 존재하는 여러개의 pixel값들에 모두 Lighting 연산 후 depth값 비교해 하나의 pixel만 그림</li>
</ul>
<ul>
<li>Deferred Shading:
First Pass를 통해 한 pixel 위치에서 &#39;Light 계산하게될 pixel값&#39;을 선정, Second Pass에서 해당 pixel값만 Light연산 후 그림<ul>
<li>즉, 한 픽셀에 여러개의 Object가 겹쳐있을수록 Deferred Shading의 성능이득 증가</li>
</ul>
</li>
</ul>
<h3 id="📌light-mrt">📌Light MRT</h3>
<p>: 전용 Texture에 빛의 영향 기록</p>
<ul>
<li><p>연산시점: Deferred 물체가 그려진 이후</p>
<ul>
<li>Deferred: Lighting 연산 받음</li>
<li>Forward: (따로 처리 않는 이상) Lighting 처리 않음</li>
</ul>
</li>
<li><p>렌더링 요청 주체: Light</p>
<ul>
<li>Forward: 모든 Mesh마다 Lighting 연산 적용</li>
<li>Deferred: 각 Light Object가 렌더링 요청</li>
</ul>
</li>
<li><p>빛의 영향 범위 판단: Position 정보를 기록해둔 Texture 사용</p>
<ul>
<li>예를 들어, Position Texture에 기록이 없다면 물체가 존재하지 않는 부분 ➡️ 빛 기록 안함</li>
<li>예를 들어, (Point Light rendering 시) Position Texture에 기록이 있다면 Point Light의 범위 안으로 들어오는지 판단</li>
</ul>
</li>
</ul>
<h3 id="📌setting">📌Setting</h3>
<p><strong>[Texture]</strong>
: 2개의 CBuffer 사용</p>
<ul>
<li>Diffuse: 세기</li>
<li>Specular: 반사광</li>
</ul>
<p><strong>[Setting]</strong></p>
<ul>
<li>DepthStencil Type: NO_TEST_NO_WRITE</li>
<li>Blend State Type: ONE_ONE<ul>
<li>기존1 : 신규1 비율로 믹스</li>
</ul>
</li>
<li>Culling: CULL-FRONT<ul>
<li>CULL-NONE: Light rendering이 두 번 호출됨</li>
<li>CULL-BACK: Light 범위 안으로 카메라가 들어가면 Light 연산하지 않음</li>
</ul>
</li>
</ul>
<h3 id="📌volume-mesh-check">📌Volume Mesh Check</h3>
<p>: Directional Lihgt가 아닌 경우 빛이 영향을 주는 범위를 알기 위해 Volume Mesh check가 필요함</p>
<ul>
<li>VolumeMesh: 광원이 영향을 주는 범위<ul>
<li>VolumeMesh만큼 호출된 전체 픽셀에 빛을 적용시키면 안 됨</li>
<li>VolumeMesh만큼 호출된 곳에서도 빛이 영향을 주는 부분만 적용시켜야 함</li>
</ul>
</li>
</ul>
<h1 id="📒volume-mesh-check">📒Volume Mesh Check</h1>
<hr>
<p>[빛의 영향 범위를 확인하는 여러 방법들]</p>
<ul>
<li>방법1: Position Texture 사용</li>
<li>방법2: Stencil 사용</li>
</ul>
<h3 id="📌방법1-position-texture-사용">📌방법1: Position Texture 사용</h3>
<p>: Position Texture를 사용해 Pixel shader에서 한 번에 빛의 영향 범위 판단</p>
<ul>
<li>VolumeMesh 안에 들어오는지 판단<ol>
<li>호출된 픽셀 위치를 UV로 환산</li>
<li>추출한 UV로 Position Texture 샘플링</li>
<li>얻은 좌표정보로 VolumeMesh와의 거리 측정<ul>
<li>역으로 연산 (Screen➡️World➡️LocalSpace of VolumeMesh)</li>
<li>좌표계 역연산: 변환행렬(View Inv * World Inv)을 바인딩해 사용</li>
</ul>
</li>
<li>거리 측정 결과로 내외부 판단</li>
</ol>
</li>
<li>장단<ul>
<li>장: 빠름 (PS에서 바로 연산 가능)</li>
<li>단: VolumeMesh의 기하학적인 특징이 있어야 함 - 내외부 판단 위해</li>
</ul>
</li>
</ul>
<h3 id="📌방법2-stencil-사용">📌방법2: Stencil 사용</h3>
<p>: VolumeMesh의 BackFace, FrontFace, Stencil에 대해 총 3번 렌더링 결과로 빛의 영향 범위 판단</p>
<ul>
<li><p>VolumeMesh 안에 들어오는지 판단</p>
<ol>
<li><p>Volume Mesh용 DepthStencil State 제작</p>
<ul>
<li>BACKFACE용</li>
<li>FRONTFACE용</li>
<li>STENCIL용</li>
</ul>
</li>
<li><p>BACKFACE 렌더링
: Light의 뒷부분 관점에서 VolumeMesh의 내부판단</p>
<ul>
<li>DepthFunc: BackFaceCheck</li>
<li>DepthStencilType: Greater<ul>
<li>더 뒤에 있으면 통과</li>
<li>먼저 그려진 물체들이(Deffered) VolumeMesh의 뒷면보다 앞에 존재한다면</li>
<li>즉, light의 영향 범위 안쪽이라면</li>
</ul>
</li>
</ul>
</li>
<li><p>FRONTFACE 렌더링
: Light의 앞부분 관점에서 VolumeMesh의 내부판단</p>
<ul>
<li>DepthFunc: FrontFaceCheck</li>
<li>DepthStencilType: Less<ul>
<li>더 뒤에 있으면 통과</li>
</ul>
</li>
<li>FrontFace.StencilFailOp: DECR<ul>
<li>두 번 증가하는 현상 방지</li>
</ul>
</li>
</ul>
</li>
<li><p>STENCILCHECK
: 예상하는 Stencil 값인지 확인</p>
<ul>
<li>DepthFunc: NEVER</li>
<li>DepthStencilType: Equal<ul>
<li>같으면 통과</li>
</ul>
</li>
<li>OMSetDepthStencilState: 2번째(idx 1) pram으로 예상하는 Stencil 값 전달</li>
<li>StencilEnable = true<ul>
<li>RenderTarget없이 DepthStencil Texture만 세팅</li>
<li>즉, RenderTarget에 색을 내보내는 Pixel Shader 단계 수행 X</li>
</ul>
</li>
<li>StencilPassOp: INCR</li>
</ul>
</li>
</ol>
</li>
<li><p>장단</p>
<ul>
<li>장: VolumeMesh의 기하학적인 특징이 없어도 가능 - 내외부 판단 위해</li>
<li>단: 느림 (렌더링이 3번 발생)</li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>[Stencil 단계 3~4를 한 단계로 합치기]</strong>
: 2~3 단계는 한 단계로 수행할 수 있음</p>
</blockquote>
<ul>
<li>DepthStencilType: CULL_NONE</li>
<li>각 구조체마다 세팅</li>
</ul>
<h1 id="📒stencil-buffer">📒Stencil Buffer</h1>
<hr>
<p>: 렌더링해야 할 곳에 특정 값을 설정해, back buffer의 일정 부분만 rendering되도록 함</p>
<ul>
<li>off-screen buffer</li>
<li>해상도: Backbuffer, depth buffer와 동일함</li>
<li>ex) 거울, 그림자, 아웃라인
<img src="https://velog.velcdn.com/images/howru_dv/post/77c06aa9-c277-437d-acfd-026d03555664/image.png" alt=""></li>
</ul>
<p><strong>References</strong>
[1] Deffered Rendering: <a href="https://learnopengl.com/Advanced-Lighting/Deferred-Shading">https://learnopengl.com/Advanced-Lighting/Deferred-Shading</a>
[2] Stencil Buffer: <a href="https://dis.dankook.ac.kr/lectures/game09/wp-content/uploads/sites/16/1/1171436988.pdf">https://dis.dankook.ac.kr/lectures/game09/wp-content/uploads/sites/16/1/1171436988.pdf</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[5. Multi Render Target]]></title>
            <link>https://velog.io/@howru_dv/5.MultiRenderTarget</link>
            <guid>https://velog.io/@howru_dv/5.MultiRenderTarget</guid>
            <pubDate>Fri, 10 May 2024 11:21:54 GMT</pubDate>
            <description><![CDATA[<h1 id="📒render-target">📒Render Target</h1>
<hr>
<h3 id="📌om-set">📌OM Set</h3>
<p><code>DX11 기준</code>
: Render Target과 Depth Stencil Texture를 같이 묶어서 세팅해줌</p>
<ul>
<li>Render Target: 최대 8장 지정 가능</li>
<li>Depth Stencil Texture: 1장만 지정 가능</li>
</ul>
<h1 id="📒multi-render-targetmrt-class-설계">📒Multi Render Target(MRT) Class 설계</h1>
<hr>
<h3 id="📌mrt-class">📌MRT Class</h3>
<p>: RenderTarget arr와 DS를 모아 관리</p>
<ul>
<li>더이상 Device가 직접 RenderTarget을 관리할 필요 없음</li>
</ul>
<p><strong>[Code Flow]</strong></p>
<ul>
<li>MRT Create &amp; Clear: RenderMgr<ul>
<li>RenderMgr에서 MRT 생성 후 들고 있는 구조</li>
<li>즉, 모든 MRT는 RenderMgr에서 들고 있음</li>
</ul>
</li>
<li>OM Set: render 시<ul>
<li>사용하는 셰이더에 따라 적절한(정해진) MRT로 OMSet 해줌</li>
</ul>
</li>
</ul>
<h3 id="📌mrt-type">📌MRT Type</h3>
<ul>
<li>MRT는 여러 타입이 있을 수 있음</li>
<li>용도에 따라 MRT를 바꿔가며 렌더 찍어 사용</li>
</ul>
<blockquote>
<p><strong>[Texture Format]</strong>
: MRT에서 Position 등의 정보를 Texture로 저장해 전달하기도 함</p>
</blockquote>
<ul>
<li>Position 등은 큰 숫자를 저장할 수 있어야 함</li>
<li><code>R8G8B8</code> : 부동소수점을 저장하기에 8bit는 너무 작음</li>
<li><code>R32G32B32</code> : 큰 데이터를 저장하기 위해선 32bit Format으로 설정해야 함</li>
</ul>
<h3 id="📌대략적인-rendering-순서">📌대략적인 Rendering 순서</h3>
<ol>
<li><p>Deffered
: 정보를 남겨두고 취합하는 렌더링</p>
<ul>
<li>다른 연산에서 사용하기 위한 정보를 연산하는 렌더링</li>
<li>한 번의 연산으로 완성되지 않음, 다른 곳에서 가져다 사용하는 용</li>
<li>ex) DEFFERED, DECAL, LIGHTING ...</li>
</ul>
</li>
<li><p>Merge
: Deferred에 기록된 정보를 메인렌더에 병합시켜야 함</p>
</li>
<li><p>Forward
: 한 번의 연산으로 완성되는 렌더링</p>
<ul>
<li>Forward를 통해 AlphaBlend를 처리할 수 있음</li>
</ul>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[4. SkyBox]]></title>
            <link>https://velog.io/@howru_dv/4.SkyBox</link>
            <guid>https://velog.io/@howru_dv/4.SkyBox</guid>
            <pubDate>Fri, 10 May 2024 05:22:53 GMT</pubDate>
            <description><![CDATA[<h1 id="📒skybox">📒SkyBox</h1>
<hr>
<h3 id="📌skybox란">📌SkyBox란</h3>
<p>: 가상의 배경을 만들 때 사용되는 wrapper
<img src="https://velog.velcdn.com/images/howru_dv/post/250a37d2-acde-4132-9099-8f4e3d110c6c/image.jpg" alt=""></p>
<ul>
<li>전체 씬을 둘러싸며 지오메트리 너머의 월드의 이미지를 보여줌</li>
<li>카메라가 움직이는 동안 고정된 배경 제공</li>
</ul>
<p><strong>[Skybox 타입]</strong></p>
<ul>
<li>Sphere</li>
<li>Cube</li>
</ul>
<h3 id="📌mesh--material">📌Mesh &amp; Material</h3>
<ul>
<li>Mesh: Cube, Sphere</li>
<li>Shader: 전용 Shader 제작<ul>
<li>Rasterizer Type: CULL_FRONT<ul>
<li>SkyBox는 내부에서만 볼 것</li>
</ul>
</li>
<li>DepthStencil Type: LESS_EQUAL<ul>
<li>skybox는 제일 멀리 있으므로 depth가 1이어야 함 (depth: 0~1)</li>
<li>depth texture는 초기화 시 1로 세팅되므로 LESS가 아닌 LESS_EQUAL</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="📌skybox-배치">📌SkyBox 배치</h3>
<p><strong>[SkyBox를 배치하는 방법]</strong></p>
<ol>
<li>실제 SkyBox의 위치 조작</li>
<li>Shader로 렌더 시 합성</li>
</ol>
<p><strong>[(방법1) 실제 SkyBox 위치 조작]</strong></p>
<ul>
<li>Main Camera의 위치로 SkyBox 위치를 계속 업데이트</li>
<li>Cam이 어디에 있든 SkyBox가 보임</li>
</ul>
<p><strong>[(방법2) Shader로 SkyBox 강제 렌더]</strong>
: VS에서 Position과 Depth를 Viewspace에 맞춰 세팅해줌</p>
<ol>
<li><p>SkyBox가 ViewSpace 상에서 원점에 있다고 가정</p>
<ul>
<li>즉 카메라에 배치되어 있다고 가정</li>
<li>VS로 들어온 Skybox Vtx의 Local 좌표를 ViewSpace 상 좌표라고 봄</li>
</ul>
</li>
<li><p>Camera의 회전정보 적용</p>
</li>
<li><p>Depth를 최대값으로 밈</p>
<ul>
<li>depth: 0~1의 값</li>
<li>즉 z를 1로 설정해야 함</li>
<li>Rasterizer State를 고려해서 투영행렬 결과의 z 자리에 w값을 넣어줌</li>
</ul>
</li>
</ol>
<blockquote>
<p><strong>Rasterizer State</strong>
: 투영행렬 곱한 결과는 최종좌표가 아님</p>
</blockquote>
<ul>
<li>뷰행렬 결과: <code>vX</code>, <code>vY</code>, <code>vZ</code>, <code>vW</code></li>
<li>투영행렬 결과: <code>pX * vZ</code>, <code>pY * vZ</code>, <code>pZ * vZ</code>, <code>vZ</code></li>
<li>Rasterizer State: 투영행렬 결과의 w(vZ)로 나눠줌</li>
</ul>
<h1 id="📒cubetex">📒CubeTex</h1>
<hr>
<p>: DX에서 자체적으로 큐브텍스처 샘플링을 진행함</p>
<ul>
<li>텍스처가 큐브로 배치되어 있는 것처럼 봄</li>
<li>UV 대신 방향벡터 사용</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[3. 3D Collision]]></title>
            <link>https://velog.io/@howru_dv/3.3DCollision</link>
            <guid>https://velog.io/@howru_dv/3.3DCollision</guid>
            <pubDate>Wed, 08 May 2024 16:03:11 GMT</pubDate>
            <description><![CDATA[<h1 id="📒3d-collision">📒3D Collision</h1>
<hr>
<h3 id="📌obb-충돌">📌OBB 충돌</h3>
<p>: 비용이 너무 커짐 (축 15?개)</p>
<ul>
<li>온라인의 경우 서버 부담 증가로 거의 사용하지 않음</li>
<li>대체:<ul>
<li>거리계산 (radius check)</li>
<li>시야계산 (부채꼴)</li>
<li>타게팅 (mouse position)</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2. Texture Roughness]]></title>
            <link>https://velog.io/@howru_dv/2.-Texture-Roughness</link>
            <guid>https://velog.io/@howru_dv/2.-Texture-Roughness</guid>
            <pubDate>Wed, 08 May 2024 12:59:55 GMT</pubDate>
            <description><![CDATA[<h1 id="📒표면의-거칠기를-표현하는-다양한-방법">📒표면의 거칠기를 표현하는 다양한 방법</h1>
<hr>
<p>[표면의 거칠기를 표현하는 다양한 방법]
<img src="https://velog.velcdn.com/images/howru_dv/post/77ec6b1d-2e80-452f-b93a-fbb4ede4595b/image.jpeg" alt=""></p>
<ul>
<li>고퀄리티 모델링</li>
<li>Normal Mapping (Bump Mapping)</li>
<li>Tesselation (Displacement Mapping)</li>
<li>Nanite Virtualized Geometry (Mesh shader) ???</li>
</ul>
<h3 id="📌normal-mapping">📌Normal Mapping</h3>
<p>: Normal에 값을 매핑시켜서, 마치 다른 면인 것처럼 연산함</p>
<ul>
<li><code>Texture Type</code></li>
<li>Vtx의 수를 유지하면서 퀄리티 높게 묘사 가능<ul>
<li>실루엣: Vtx 수는 그대로 유지하되 가상의 표면 방향을 사용하는 눈속임 기법이므로, 실루엣은 변하지 않음</li>
<li>즉 큐브를 구처럼 만들거나, 튀어나온 무언가를 표현하기에는 한계가 있음</li>
</ul>
</li>
<li>Normal Texture: 색상 텍스처 (RGB)<ul>
<li>RGB를 XYZ로 매핑 (Bump Mapping의 상위호환)
<img src="https://velog.velcdn.com/images/howru_dv/post/f01f8ecb-2e1a-4970-99c0-346af4bf3f21/image.png" alt=""></li>
</ul>
</li>
</ul>
<blockquote>
<p>[Bump Mapping]</p>
</blockquote>
<ul>
<li><code>Texture Type</code></li>
<li>사용: 스크래치, 모공 등 작은 디테일</li>
<li>Bump Texture: Grayscale<ul>
<li>색상값을 Height로 매핑
<img src="https://velog.velcdn.com/images/howru_dv/post/840f040d-9690-4905-8a9f-e919c280d121/image.png" alt=""></li>
</ul>
</li>
</ul>
<h3 id="📌tesselation">📌Tesselation</h3>
<p>: 그래픽스 셰이더에서 정점 수 늘리기 (쪼개기)</p>
<ul>
<li><code>Shader Technique</code></li>
<li>Hull Shader + Domain Shader</li>
<li>정점 쪼개기: 임의의 메쉬를 입력받아 동적으로 여러 기본 요소로 세분화함<ul>
<li>실루엣: 실루엣의 변화가 표현됨</li>
</ul>
</li>
<li>동적 세분화: 현재 시점을 기준으로 메쉬의 어느 부분을 더 세분화해야 하는지 동적으로 결정한다는 뜻<ul>
<li>메시의 일부는 높은 해상도와 디테일을 가짐</li>
<li>다른 부분은 매우 낮은 해상도를 가짐</li>
<li>ex, 메시의 쿼드가 카메라에서 얼마나 멀리 떨어져 있는지, 현재 카메라가 볼 수 있는지 등을 판단해 쿼드를 완전히 폐기하고 단지 2개의 삼각형으로 처리하거나, 수천개의 삼각형으로 처리하거나 선택</li>
</ul>
</li>
<li>장점: 렌더링 속도가 매우 빠름 (Displacement Mapping의 상위호환)</li>
</ul>
<blockquote>
<p>[Displacement Mapping (&amp; Bump Mapping)]
: 정점 수 늘리기 (쪼개기)</p>
</blockquote>
<ul>
<li>Displacement Mapping은 텍스처를 기반으로 메시 정점을 실제로 변환함 (static)</li>
<li>static한 변환으로 높은 비용 소모</li>
</ul>
<h3 id="📌nanite">📌Nanite</h3>
<p>: 픽셀 스케일의 디테일 및 다수의 오브젝트를 렌더링하는 가상화 지오메트리 시스템</p>
<ul>
<li><code>Geometry System</code></li>
<li>tesellation으로 생성된 Vtx를 포함해, 렌더링되는 Vtx를 결정해 성능을 향상시킴</li>
<li>클러스터 컬링과 자동 LOD(Level of detail)를 통해 고품질 모델을 빠르게 렌더링</li>
</ul>
<p>[Nanite]</p>
<ul>
<li><p><code>UE5에 새롭게 적용된 핵심 기술</code></p>
<ul>
<li>amd에서는 primitive shader라는 이름으로 지원</li>
<li>nvidia에서는 mesh shader라는 이름으로 지원
<img src="https://velog.velcdn.com/images/howru_dv/post/da92e971-f32f-41b2-ac03-55768ff337a8/image.png" alt=""></li>
</ul>
</li>
<li><p>기술목표</p>
<ul>
<li>버추얼 텍스처링처럼 지오메트리 버전</li>
<li>뷰에 따라 필요한 디테일 수준의 지오메트리 데이터만 가상화</li>
<li>폴리곤 수나 드로 콜의 제약 없이 하이폴리곤 메시를 바로 사용</li>
<li>로우폴리곤 + 노멀 맵 대신 하이폴리곤 모델을 바로 사용 가능</li>
</ul>
</li>
<li><p>작동방식</p>
<ul>
<li>로드 시: 메시를 <strong>hierachy cluster</strong>라는 단위로 묶어줌
<img src="https://velog.velcdn.com/images/howru_dv/post/6af7c104-63f2-4177-99c6-a0fc937d9a3f/image.png" alt=""></li>
<li>렌더링 시<ul>
<li>카메라 뷰를 바탕으로 클러스트의 LOD가 자동 결정됨</li>
<li>클러스터는 동일한 오브젝트 내에서 인접한 클러스트와 또다시 묶어 부모 클러스터로 만들어줌
<img src="https://velog.velcdn.com/images/howru_dv/post/85ed5383-52c6-448c-88d8-1ecbc10a4d12/image.png" alt=""></li>
</ul>
</li>
</ul>
</li>
<li><p>장점</p>
<ul>
<li>수동으로 노멀맵을 굽거나 LOD를 적용할 필요가 없기 때문에 최적화 시간을 줄일 수 있음</li>
<li>카메라에 보이는 클러스터만 렌더링하므로 성능이 좋음<ul>
<li>Oclusion Curing <code>비교군, 모든 폴리곤을 렌더링하므로 성능이 나쁨</code>
<img src="https://velog.velcdn.com/images/howru_dv/post/6402ab2c-5bd9-4da3-9f8b-a991b9129e5f/image.png" alt=""></li>
<li>Clustur Curing
<img src="https://velog.velcdn.com/images/howru_dv/post/3cf66547-db8c-43c1-aba0-654d566aa6b0/image.png" alt=""></li>
</ul>
</li>
</ul>
</li>
</ul>
<h1 id="📒normal-mapping">📒Normal Mapping</h1>
<hr>
<h3 id="📌normal-texture-좌표계">📌Normal Texture 좌표계</h3>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/b840d6da-c96a-46de-8af4-b9ee97453127/image.png" alt=""></p>
<ul>
<li>(주의) DX식이 아님!</li>
<li>Unreal식임</li>
</ul>
<h3 id="📌normal-texture-type">📌Normal Texture Type</h3>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/146c9c92-0751-43cb-89fa-d4cb481b08e8/image.png" alt=""></p>
<ul>
<li>Tangent Space: Local 방식</li>
<li>Object Space: World 방식</li>
</ul>
<p><strong>[Object Space]</strong>
: World 좌표 기준으로 표현된 값 (절대값)</p>
<ul>
<li>rgb를 world normal의 xyz로 매핑 (Normal Texture 좌표계 기준)</li>
<li>장: 연산이 간단함</li>
<li>단:<ul>
<li>Vtx의 변화에 대응하지 못함<ul>
<li>ex, 3D Animation 등</li>
<li>local space 내에서 Vtx가 움직일 수 있음</li>
<li>그런 경우 Normal의 방향이 틀어짐</li>
</ul>
</li>
<li>대상 모델에만 적용 가능<ul>
<li>다른 모델에 적용하면 normal이 틀어져 어색함</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>[Tangent Space]</strong>
: local 기준으로 표현된 값</p>
<ul>
<li>rgb를 local normal의 xyz로 매핑 (Normal Texture 좌표계 기준)<ul>
<li>Normal의 좌표계 = local 좌표계 = 평면좌표계 = Tangent space</li>
</ul>
</li>
<li>local -&gt; world space로의 연산 필요</li>
</ul>
<h3 id="📌tangent-space-연산">📌Tangent Space 연산</h3>
<p><strong>[좌표계 변환에 필요한 정보]</strong>
: Vtx가 향하는 방향, 즉 Normal 방향을 가상으로 바꿔줌</p>
<ul>
<li>Normal, Tangent, Binormal 의 방향 조작 (매핑)</li>
</ul>
<p><strong>[Normal Texture 읽기]</strong></p>
<ol>
<li><p>회전행렬 계산</p>
<ul>
<li>Normal Texture 좌표계는 rgb &quot;B&quot;가 &quot;Z&quot;축이며 Normal Vector임</li>
<li>회전행렬
<code>Normal Texture 좌표계를 고려했을 때</code><ul>
<li>X 축: tangent vector</li>
<li>Y 축: binormal vector</li>
<li>Z 축: normal vector
<img src="https://velog.velcdn.com/images/howru_dv/post/b840d6da-c96a-46de-8af4-b9ee97453127/image.png" alt=""></li>
</ul>
</li>
</ul>
</li>
<li><p>값 매핑</p>
<ul>
<li>픽셀의 색상정보(RGB)를 벡터 표현 위한 자료형으로 사용</li>
<li>RGB는 각각 0<del>255 저장하며, 셰이더에선 정규화해 0</del>1로 표현</li>
<li>음수 표현: 표현 범위를 쪼개 음수와 양수 표현<ul>
<li>0 ~ 0.5    : 음수</li>
<li>0.5        : 0</li>
<li>0.5 ~ 1    : 양수</li>
</ul>
</li>
<li>치환식: 샘플값 * 2 - 1<ul>
<li>연산결과 -1~1로 표현 가능</li>
</ul>
</li>
</ul>
</li>
<li><p>(OpenGL 용 텍스처인 경우) 좌표계 매핑</p>
<ul>
<li>OpenGL은 y축의 방향이 반대임
<img src="https://velog.velcdn.com/images/howru_dv/post/b840d6da-c96a-46de-8af4-b9ee97453127/image.png" alt=""></li>
<li>해결:<ul>
<li>Normal Texture 좌표계 기준 Y축, 즉 Binormal 부호를 반전시키거나</li>
<li>텍스처를 DX용으로 바꾸기</li>
</ul>
</li>
</ul>
</li>
</ol>
<p><strong>References.</strong>
[1] 3D Simulation: <a href="https://sketchfab.com/3d-models/bump-vs-normal-map-vs-displacement-map-748c49515a1b4e198c9ace516355a156">Bump Mapping vs Normal Mapping vs Displacement Mapping</a>
[2] About Mapping: <a href="https://www.pluralsight.com/blog/film-games/bump-normal-and-displacement-maps">https://www.pluralsight.com/blog/film-games</a>
[3] Nanite Unreal Doc: <a href="https://dev.epicgames.com/documentation/ko-kr/unreal-engine/nanite-virtualized-geometry-in-unreal-engine?application_version=5.1">언리얼 엔진의 나나이트 가상화 지오메트리 | 언리얼 엔진 5.1 문서</a>
[4] Nanite Introduction: <a href="https://devjino.tistory.com/219">https://devjino.tistory.com/219</a>
[5] Mesh Shader Nvida Doc: <a href="https://developer.nvidia.com/blog/introduction-turing-mesh-shaders/">Mesh Sahder | Nvida Devloper</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[1. 3D Lighting]]></title>
            <link>https://velog.io/@howru_dv/1.3DLighting</link>
            <guid>https://velog.io/@howru_dv/1.3DLighting</guid>
            <pubDate>Wed, 08 May 2024 07:03:04 GMT</pubDate>
            <description><![CDATA[<h1 id="📒다양한-라이팅-연산-방법">📒다양한 라이팅 연산 방법</h1>
<hr>
<p>[다양한 라이팅 연산 방법]
<img src="https://velog.velcdn.com/images/howru_dv/post/e48b557c-aa63-499e-8bff-65e2bbfef879/image.png" alt=""></p>
<ul>
<li>Gouraud shading: 정점에서 라이팅 연산하는 방법</li>
<li>Pong shading: 픽셀단위로 라이팅 연산하는 방법</li>
</ul>
<h3 id="📌gouraud-shading">📌Gouraud shading</h3>
<p>: Vtx에서 광원 연산 후 PS에서 보간값 사용</p>
<ul>
<li>장: 연산량 적음<ul>
<li>초창기 그래픽스에서 사용하던 방식</li>
<li>그러나 현재 컴퓨터에선 이정도 연산량 큰 차이 없음</li>
</ul>
</li>
<li>단: 어색함<ul>
<li>버텍스의 연산 결과를 보간한 값이므로,</li>
<li>이를 평면에 발라 구체를 만들면 어색함</li>
</ul>
</li>
</ul>
<h3 id="📌pong-shading">📌Pong shading</h3>
<p>: 각 픽셀의 Normal을 보간해 픽셀마다 광원 연산</p>
<ul>
<li>보간된 Normal로 각 픽셀마다 적절한 Lighting 연산 가능<ul>
<li>평면이지만 곡면처럼 처리 가능</li>
</ul>
</li>
</ul>
<h1 id="📒light-reflection">📒Light Reflection</h1>
<hr>
<p>: 반사된 빛이 카메라를 향하면 더 밝아 보임</p>
<h3 id="📌반사벡터-유도">📌반사벡터 유도</h3>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/4cf051de-3799-4a62-b09e-1a34f778b65d/image.png" alt=""></p>
<p><code>R = P + 2N(-P·N)</code>
<code>반사벡터 = 입사벡터 + 2표면벡터(-입사벡터·표면벡터)</code></p>
<h3 id="📌좌표계">📌좌표계</h3>
<p>: View space 사용</p>
<ul>
<li>반사광 연산은 카메라 정보를 얻어 사용해야 함</li>
<li>카메라 정보 :<ul>
<li>view matrix에서 얻어 사용 가능</li>
<li>좌표계를 view space로 둔다면 카메라와 관련한 연산 용이</li>
</ul>
</li>
</ul>
<h3 id="📌반사광-연산">📌반사광 연산</h3>
<ul>
<li><p>반사된 빛의 크기</p>
<ul>
<li>Reflection Vector와 Camera의 Eye vector 간 각도 연산</li>
<li>내적:<ul>
<li>두 벡터가 반대방향으로 교차할 때 반사된 값이 최대</li>
<li>(라이팅 연산처럼) cos 사용하기 위해 내적</li>
<li>반대방향 교차이므로 한 벡터는 뒤집어줘야 함</li>
</ul>
</li>
</ul>
</li>
<li><p>그래프 보정</p>
<ul>
<li>cos의 문제: 그래프가 완만함 (로그그래프처럼 급격히 꺾여야 함)</li>
<li>내적 결과값을 pow해서 그래프 곡선 조절</li>
<li>cos 그래프 <img src="https://velog.velcdn.com/images/howru_dv/post/cab9cbeb-ae56-4a0b-a89d-708427b7f761/image.png" alt=""></li>
<li>로그그래프 <img src="https://velog.velcdn.com/images/howru_dv/post/f5093028-ca40-4506-889b-0eceb322af74/image.png" alt=""></li>
</ul>
</li>
<li><p>연산 결과 빛처리</p>
<ul>
<li>결과값 * reflection scale(설정한 반사값)</li>
<li>오브젝트 값이 아닌 라이트값만 영향을 받아야 함</li>
</ul>
</li>
</ul>
<p><strong>References.</strong>
[1] Reflection Vector derivation: <a href="https://novemberfirst.tistory.com/112">https://novemberfirst.tistory.com/112</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[0. 3D Vtx & 3D Mesh]]></title>
            <link>https://velog.io/@howru_dv/0.3DVtx3DMesh</link>
            <guid>https://velog.io/@howru_dv/0.3DVtx3DMesh</guid>
            <pubDate>Wed, 08 May 2024 04:49:49 GMT</pubDate>
            <description><![CDATA[<h1 id="📒3d-vtx">📒3D Vtx</h1>
<hr>
<h3 id="📌복습-vb--ib">📌복습: VB &amp; IB</h3>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/cf812f11-343d-4c79-9bf0-1fd43aa106c8/image.jpeg" alt=""></p>
<ul>
<li>다각형을 그리기 위해서는 중첩된 정점이 발생함</li>
<li>Index Buffer: 정점을 재활용하므로 같은 정점을 두 번 만들지 않음<ul>
<li>메모리적 이점</li>
</ul>
</li>
</ul>
<h3 id="📌normal-vector--tangent-vectors">📌Normal Vector &amp; Tangent Vectors</h3>
<p>3D Vertex에는 정점의 방향 정보가 추가됨
<img src="https://velog.velcdn.com/images/howru_dv/post/b37074fb-71a0-4305-8dce-771f19f1c509/image.png" alt="">
<img src="https://velog.velcdn.com/images/howru_dv/post/be35cb49-a7f7-468a-b4e6-11c1631a2cdf/image.png" alt=""></p>
<ul>
<li>Normal: (정점 표면 방향 벡터) 표면의 수직 방향으로 향함</li>
<li>Tangent: (접선 벡터) Normal Vector에 수직이며 UV의 U축으로 향하는 벡터<ul>
<li>DX에서 UV의 U축은 왼손좌표계 기준 우측으로 향하는 벡터임</li>
</ul>
</li>
<li>Binormal: (종법선 벡터) Normal Vector에 수직이며 UV의 V축으로 향하는 벡터<ul>
<li>Normal과 Tangent 벡터에 모두 수직한 벡터</li>
</ul>
</li>
</ul>
<blockquote>
<p>[복습] Vertex Struct 변경 시</p>
</blockquote>
<ul>
<li>Input Layout 변경</li>
</ul>
<h3 id="📌추가된-벡터방향정보의-사용">📌추가된 벡터(방향정보)의 사용</h3>
<p>: 3D Lighting</p>
<ul>
<li><p>표면의 normal 벡터와 빛의 진입각을 내적해서 빛을 받는 양 계산</p>
<ul>
<li>내적하는 이유: cos 그래프 사용하려고</li>
<li>빛이 0도로 진입했을땐 1(최대), 90도로 진입했을땐 0(최소)
<img src="https://velog.velcdn.com/images/howru_dv/post/480d77b9-9c84-4417-ad93-45b9e7d9ecbb/image.jpeg" alt=""></li>
</ul>
</li>
<li><p>연산 시 사용하는 Light 방향:</p>
<ul>
<li>90도를 기준으로 연산해야하므로,</li>
<li>광원에서 나온 Light의 반대 방향을 사용해야 함</li>
<li>(~표면으로 들어온 Light의 방향)</li>
</ul>
</li>
</ul>
<h1 id="📒3d-shader">📒3D Shader</h1>
<hr>
<h3 id="📌vertex-shader">📌Vertex Shader</h3>
<p>: Vtx의 방향 계산</p>
<ul>
<li>단위벡터<ol>
<li>확장: 좌표가 아닌 단위벡터이므로 0으로 확장</li>
<li>Rotate에만 영향받아야 함: World Matrix는 Scaling이 이미 적용되어 있으므로 Normalize 필요</li>
</ol>
</li>
<li>좌표계: Local -&gt; World 변환<ul>
<li>Vtx의 정보는 Local 좌표계 기준으로 들어오지만,</li>
<li>Light의 World 방향과 연산 등</li>
<li>World상에서의 normal 방향을 표기해 사용해야 하므로</li>
<li>World좌표계로 옮겨줘야 함</li>
</ul>
</li>
</ul>
<h3 id="📌pixel-shader">📌Pixel Shader</h3>
<p>: 최종 출력 색상 결정</p>
<ul>
<li>Obj color * Light color * Light Pow</li>
<li>+ Obj color * Light Amb color</li>
</ul>
<h3 id="📌light-pow의-범위">📌Light Pow의 범위</h3>
<p>: 0~1</p>
<ul>
<li>음수일 수 없음</li>
<li>Ambient color 등 빛의 개념을 의도대로 적용하기 위해선 0~1에서 잘라줘야 함</li>
</ul>
<h1 id="📒3d-debug-shading">📒3D Debug Shading</h1>
<hr>
<h3 id="📌inner-glow">📌Inner Glow</h3>
<ul>
<li>Sphere의 중앙일수록 Normal이 카메라를 보고</li>
<li>Sphere의 가쪽일수록 Normal이 카메라와 직교함</li>
<li>카메라의 시선벡터 (부호반대)와 내적해서 유사도 계산</li>
<li>alpha = ~유사도</li>
</ul>
<h1 id="📒3d-mesh">📒3D Mesh</h1>
<hr>
<h3 id="📌normal-평면과-곡면">📌Normal, 평면과 곡면</h3>
<p>[평면]
: 극단적으로 표면의 각이 변화하는 경우</p>
<ul>
<li>ex Cube Mesh</li>
<li>Normal 공유할 수 없음</li>
<li>4*6 개의 Vtx 필요</li>
</ul>
<p>[곡면]
: 표면의 각이 부드럽게 변화하는 경우</p>
<ul>
<li>ex Sphere</li>
<li>Normal 중간값으로 둬서 공유해도 됨</li>
</ul>
<h3 id="📌culling">📌Culling</h3>
<p>: Cull-Back</p>
<ul>
<li><p>3D Light 연산</p>
<ul>
<li>CW를 가정한 Vtx 세팅의 연산결과이므로</li>
<li>뒷면(CCW)에서 보더라도 CW의 연산결과를 보게됨</li>
<li>➡️ 그냥 뒷면을 그리지 않게 Cull back 사용</li>
</ul>
</li>
<li><p>뒷면을 그리려면</p>
<ul>
<li>두 면(앞면 + 뒷면)을 합쳐야 함</li>
</ul>
</li>
</ul>
<h3 id="📌곡면예시-sphere-mesh-만들기">📌(곡면예시) Sphere Mesh 만들기</h3>
<ul>
<li>Vtx: 가로/세로 분할해 접근</li>
<li>Normal: 본인의 좌표가 Normal임<ul>
<li>중점에서 바라보는 방향이 표면의 방향이 되므로</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[0. VS연결]]></title>
            <link>https://velog.io/@howru_dv/0.-VS%EC%97%B0%EA%B2%B0</link>
            <guid>https://velog.io/@howru_dv/0.-VS%EC%97%B0%EA%B2%B0</guid>
            <pubDate>Sat, 13 Jan 2024 13:06:40 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>언리얼 공식 가이드 QuickStart를 따라하는 중 생긴 오류 해결
<a href="https://docs.unrealengine.com/5.2/ko/unreal-engine-cpp-quick-start/">https://docs.unrealengine.com/5.2/ko/unreal-engine-cpp-quick-start/</a></p>
</blockquote>
<h2 id="1-unreal세팅">1. Unreal세팅</h2>
<p><a href="https://dev.epicgames.com/community/learning/tutorials/XjvJ/unreal-engine-ue-5-1-visual-studio-2022-installation-guide?locale=ko-kr">https://dev.epicgames.com/community/learning/tutorials/XjvJ/unreal-engine-ue-5-1-visual-studio-2022-installation-guide?locale=ko-kr</a></p>
<h2 id="2-vs-환경-세팅">2. VS 환경 세팅</h2>
<blockquote>
<p>만약 설치했는데 구성설정에서 인식을 제대로 하지 못한다면, 최신 업데이트를 진행해준다</p>
</blockquote>
<h4 id="1-vs-세팅">1. VS 세팅</h4>
<p><a href="https://docs.unrealengine.com/5.1/ko/setting-up-visual-studio-development-environment-for-cplusplus-projects-in-unreal-engine/">https://docs.unrealengine.com/5.1/ko/setting-up-visual-studio-development-environment-for-cplusplus-projects-in-unreal-engine/</a></p>
<h4 id="2-unrealvs-설치">2. UnrealVS 설치</h4>
<ul>
<li>언리얼 설치경로의 UnrealVS를 찾는다 (\Epic Games\UE_5.2\Engine\Extras\UnrealVS\)</li>
<li>사용 버전의 VS 폴더로 들어간다</li>
<li>UnrealVS.vsix를 설치한다
<img src="https://velog.velcdn.com/images/howru_dv/post/c221239c-9148-4d9a-9f39-4b3b7bb9bdf5/image.png" alt=""></li>
</ul>
<h2 id="3-vs-구성설정">3. VS 구성설정</h2>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/5f6cdd18-7b09-4a0e-8c3a-b17ad86310d0/image.png" alt=""></p>
<h4 id="구성상태-불량">구성상태 불량</h4>
<p><a href="https://raw.githubusercontent.com/microsoft/vc-ue-extensions/main/Source/.editorconfig">https://raw.githubusercontent.com/microsoft/vc-ue-extensions/main/Source/.editorconfig</a></p>
<ul>
<li>명명 규칙 검사기 설정</li>
<li>HLSL 설정</li>
</ul>
<h4 id="오류-목록">오류 목록</h4>
<p>무시한다. 공식문서에서 VS 에러는 무시하고 Unreal의 콘솔창으로 에러를 확인하라는게 이런 말인 듯?
몰?루</p>
<h2 id="4-vs-연결-확인">4. VS 연결 확인</h2>
<p><a href="https://makerejoicegames.tistory.com/297">https://makerejoicegames.tistory.com/297</a></p>
<h2 id="5-vs로-빌드하기">5. VS로 빌드하기</h2>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/8b165fe4-dbca-401c-bd61-2fa085cb46bc/image.png" alt="">
VS에서 빌드하면 오류가 발생한다</p>
<h4 id="방법1-vs에서-말고-unreal에서-build한다">방법1. VS에서 말고 Unreal에서 build한다</h4>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/922d327d-0de5-47ec-81c4-0f11da76c3bf/image.png" alt="">
<img src="https://velog.velcdn.com/images/howru_dv/post/8fe154a8-d1f8-4256-8dcc-34d44db9fe0b/image.png" alt=""></p>
<h4 id="방법2-unreal에서-live-coding을-끄고-vs에서-build한다">방법2. Unreal에서 live coding을 끄고, VS에서 build한다</h4>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/475cff53-f658-41ee-b182-de651e40d01e/image.png" alt="">
<img src="https://velog.velcdn.com/images/howru_dv/post/7ced31c6-a289-4471-9814-f65f3c036a30/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[내적]]></title>
            <link>https://velog.io/@howru_dv/InnerProduct</link>
            <guid>https://velog.io/@howru_dv/InnerProduct</guid>
            <pubDate>Wed, 10 Jan 2024 18:30:55 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/howru_dv/post/e9b92272-3ca5-468e-abe6-f2d18e513399/image.png" alt=""></p>
<h2 id="dot-product-inner-product-내적">Dot Product, Inner Product <em>(내적)</em></h2>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/53d9ec84-3b39-45d9-a5eb-3f046f5b9732/image.jpg" alt="">
내적이란 두 벡터의 같은 성분끼리의 곱의 합으로, 두 벡터의 곱과 유사하다. 
예를 들어 vecotr A(x1, y1)와, vector B(x2, y2)가 있을 때,
두 벡터의 내적인 A · B 는 (x1*x2) + (y1*y2)가 된다.</p>
<p>즉 벡터의 내적은 스칼라값이다.
이 값은, 한 벡터의 방향으로 다른 벡터를 projection_투영_ 시킨 후 곱한 값이다.</p>
<hr>
<h2 id="내적의-정리1">내적의 정리1</h2>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/b3f2c968-2627-43f1-8790-c4724c72d244/image.jpg" alt="">
두 벡터의 내적 값은, 두 벡터의 크기와 두 벡터 사이의 각을 곱한 값과 같다.
|a| 는 vector A의 크기이고 θ는 두 벡터가 이루는 각이다.</p>
<h4 id="따름정리">따름정리</h4>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/af06d8c9-b3a3-485d-a3c8-e1d134449692/image.jpg" alt="">
따라서 두 벡터 사이의 cosθ는 위와 같은 정리를 만족한다.</p>
<h4 id="응용-두-벡터-사이의-각도-구하기-0--180도">응용: 두 벡터 사이의 각도 구하기 (0 ~ 180도)</h4>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/d1e79b41-4071-49dc-a8a3-9759a2b7e2a5/image.png" alt="">
따라서 벡터의 내적을 활용해 두 벡터가 이루는 각을 구할 수 있다.</p>
<ul>
<li>두 벡터의 내적으로 cosθ 값을 구할 수 있다.</li>
<li>arccos(cosθ)를 한다면, θ 값을 도출할 수 있다.</li>
<li>이 때 normalized된 단위벡터를 활용한다면 arccos에 넣을 값이 간결해지므로 용이하다</li>
</ul>
<blockquote>
<p>❕두 벡터 사이의 값이 180도가 넘눈다면, 외적 등을 활용해 추가적인 연산을 해야함</p>
</blockquote>
<blockquote>
<p>❕두 벡터 사이의 값은 arctan으로도 구할 수 있음</p>
</blockquote>
<blockquote>
<p>❕ 응용문제: <a href="https://rangsub.tistory.com/15">https://rangsub.tistory.com/15</a></p>
</blockquote>
<hr>
<h2 id="내적의-정리2">내적의 정리2</h2>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/d9835c74-2f7c-4381-a42c-93e4753ca50b/image.jpg" alt="">
<img src="https://velog.velcdn.com/images/howru_dv/post/554bac18-8888-4ec2-9aa9-c277a1c45b6e/image.png" alt="">
두 벡터의 내적 값으로 두 벡터의 유사도(진행방향 사이의 관계)를 판단할 수 있다.
cos의 그래프를 떠올리면 쉽게 연상 가능하다.</p>
<ul>
<li>내적 값이 0이라면, 두 벡터는 수직이다</li>
<li>내적 값이 양수라면, 두 벡터 사이의 각은 90도보다 작다</li>
<li>내적 값이 음수라면, 두 벡터 사이의 값은 90도보다 크다</li>
</ul>
<hr>
<h2 id="projection">Projection</h2>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/7ba67eff-d2fc-48ed-9b79-ad546f1fd7ee/image.png" alt="">
두 벡터의 내적은 개념적으로 한 벡터의 방향으로 다른 벡터를 투영시켜 곱한다.
즉, 어떤 vector V를 단위벡터 N에 내적한다면, V의 N의 방향으로의 길이를 구할 수 있다.</p>
<hr>
<h2 id="내적을-사용하는-이유">내적을 사용하는 이유</h2>
<p>두 벡터 사이의 각도를 구하려면 arccos 함수를 사용해야 하는데,
삼각함수를 남발하면 프로그램의 성능이 하락할 수 있으므로
몇 번의 곱셈과 덧셈으로 끝나는 내적을 사용하는 것이 이득이다.</p>
<h4 id="내적의-응용사례">내적의 응용사례</h4>
<ul>
<li>3D에서 면이 빛을 받음을 계산할 때 (즉, 명암처리 시)</li>
<li>3D에서 면이 카메라를 향하는지 계산할 때 (즉, Normal 판단 시)</li>
<li>반사 벡터를 구할 때</li>
<li>그림자를 구할 때</li>
</ul>
<hr>
<p><strong>References</strong>
[1] 내적의 정의 : <a href="https://m.blog.naver.com/mindo1103/90103350914">https://m.blog.naver.com/mindo1103/90103350914</a>
[2] 두 벡터의 사이각 구하기 : <a href="https://asteriskhun.tistory.com/40">https://asteriskhun.tistory.com/40</a>
[3] 벡터의 내적 응용문제 : <a href="https://rangsub.tistory.com/15">https://rangsub.tistory.com/15</a>
[4] 반사벡터 구하기 : <a href="https://novemberfirst.tistory.com/112">https://novemberfirst.tistory.com/112</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Culling]]></title>
            <link>https://velog.io/@howru_dv/Culling</link>
            <guid>https://velog.io/@howru_dv/Culling</guid>
            <pubDate>Wed, 13 Dec 2023 03:45:10 GMT</pubDate>
            <description><![CDATA[<p>3D를 올바르게 렌더링하려면 앞쪽에 있는 물체가 뒤에 있는 물체를 가릴수있는 처리가 필요하다.
[ culling ]은 보이지 않는 부분을 숨기는 처리이며, 주로 [ DepthBuffer_(Z Buffer)_ ]방식을 사용한다.
<br></p>
<h2 id="처리-방식">처리 방식</h2>
<p>culling에는 [Z sroting]과 [ Z buffer] 방식 등이 있다.
<img src="https://velog.velcdn.com/images/howru_dv/post/ebf61225-39de-40d6-8659-b3a11bb97aab/image.jpg" alt=""></p>
<ul>
<li>(A) Z sorting:<ul>
<li>간단함</li>
<li>물체끼리 교차하는 전후관계를 결정하기 어려울 때 제대로 렌더링되지 않음</li>
<li>sorting에 시간이 걸림</li>
</ul>
</li>
<li>(B) Z buffer: 거리를 픽셀 단위로 기록하기 위한 [ Depth Buffer ] 필요<ul>
<li>전후관계를 픽셀단위로 판단할 수 있음</li>
<li>일반적으로는 Z 버퍼 기법을 사용</li>
<li>반투명인 물체가 있으면 depth buffer만으로는 제대로 렌더링할 수 없음</li>
</ul>
</li>
<li>alpha sorting: Z buffer로 불투명한 물체 렌더링<ul>
<li>불투명 물체를 먼저 렌더링해 둠</li>
<li>반투명 물체를 뒤에서부터 sorting하여 렌더링한다</li>
</ul>
</li>
<li>Stencil Buffer: 여러가지 효과를 표현하는데 쓰이는 [Stencil Buffer ]를 사용하는 경우도 있음<br>

</li>
</ul>
<h2 id="depthstencil-buffer">DepthStencil Buffer</h2>
<p>DirectX 11에서 Depth Buffer와 Stencil Buffer는 1개의 리소스를 공유하므로, [ DepthStnecil Buffer] 라고 묶어서 취급한다.</p>
<ul>
<li>[ render target ] 과 조합해서 사용</li>
<li>렌더타겟은 동시에 8개까지 설정할 수 있지만 깊이/스텐실 버퍼는 1개 뿐이다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[0. Device Initialize]]></title>
            <link>https://velog.io/@howru_dv/0.-Device-Initialize</link>
            <guid>https://velog.io/@howru_dv/0.-Device-Initialize</guid>
            <pubDate>Wed, 13 Dec 2023 03:40:21 GMT</pubDate>
            <description><![CDATA[<h2 id="flow">Flow</h2>
<p>DirectX 11 의 처리 흐름도는 크게 다음과 같다.</p>
<ul>
<li>(1) Device &amp; Swap Chain 생성</li>
<li>(2) Depth/Stencil Buffer 생성</li>
<li>(3) render target 설정: SwapChain의 BackBuffer
(depth/stencil view 설정)</li>
<li>(4) 어플리케이션 실행, 필요한 처리 수행<ul>
<li>일정간격으로 화면을 렌더링하고 swapChain으로 화면 갱신</li>
<li>윈도우 사이즈의 갱신에 따라 백 버퍼를 리사이징한다</li>
</ul>
</li>
<li>(5) 종료 처리</li>
</ul>
<h2 id="header">header</h2>
<blockquote>
</blockquote>
<p><strong>DirectX 11 library 참조</strong></p>
<pre><code>#include &lt;d3d11.h&gt;
#include &lt;d3dcompiler.h&gt;
#include &lt;DirectXMath.h&gt;
#pragma comment(lib, &quot;d3d11&quot;)
#pragma comment(lib, &quot;d3dcompiler&quot;)
using namespace DirectX;</code></pre><blockquote>
</blockquote>
<p><strong>Smart Pointer library 참조</strong></p>
<pre><code>#include &lt;wrl.h&gt;
using namespace Microsoft::WRL;</code></pre><h3 id="smart-pointer">Smart Pointer</h3>
<p>DirectX의 Reference Counter는 객체에 대한 이해가 필요하므로 관리가 어렵다.
용이한 관리 위해 MS에서 만든 Smart Pointer 기능을 사용한다.</p>
<ul>
<li>원리: template class로 생성, 소멸자에서 해제될 때 release하는 식<ul>
<li><blockquote>
<p>```
template <typename T>
class ComPtr
{
private:
  T* m_Ptr;
public:
  void*    GetAddressOf(){return &m_Ptr;}
T*        Get(){return m_Ptr;}
public:
  ComPtr() :m_Ptr(nullptr){}
~ComPtr(){ if(m_Ptr) Release(m_Ptr); }
}</p>
</blockquote>
</li>
<li>기본생성자 호출되므로 직접 초기화할 필요 X</li>
<li>직접 해제 관리할 필요 X </li>
</ul>
</li>
<li>Caution<ul>
<li>접근지점을 명확히 정해야 함</li>
<li><code>GetAdressOf()</code> : 멤버포인터의 주소를 넘김 (doublePointer)</li>
<li><code>Get()</code> : 멤버포인트가 가진 주소를 넘김 (Pointer)<br>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="step0-feature-level-결정">Step0. Feature Level 결정</h2>
<h3 id="feature-level">Feature Level</h3>
<p>DirectX 11에서는 6단계의 Feature Level을 정의하여 이전 버전의 디바이스여도(DirectX 9/10/10.1) 호환 가능하다.
어플리케이션은 Feature Level에 따라 DirectX 11의 기능을 사용해 실행된다.
이 전 포스팅에서도 설명하였지만 DirectX 11의 기능은 피처 레벨에 의해 6단계로 나누어져있다</p>
<ul>
<li>feature level: GPU가 서포트하는 기능셋의 엄밀한 정의</li>
<li>기본적으로는 level은 하위 level의 기능 포함함</li>
<li>디바이스를 생성할 때 낮은 기능 레벨을 지정하면 DirectX 9, DirectX 10 하드웨어에서도 DirectX 11을 사용 가능</li>
</ul>
<blockquote>
</blockquote>
<p><strong>about D3D_FEATURE_LEVEL</strong></p>
<pre><code>// array of feature levels
 D3D_FEATURE_LEVEL featureLevels[] =                             
{
    D3D_FEATURE_LEVEL_11_0,
    D3D_FEATURE_LEVEL_10_1,
    D3D_FEATURE_LEVEL_10_0,
};
&gt;
// array size
UINT numFeatureLevels = ARRAYSIZE( featureLevels );
&gt;
// device 생성 시 넘길 feature level 변수
D3D_FEATURE_LEVEL       g_featureLevel = D3D_FEATURE_LEVEL_11_0;    </code></pre><h2 id="step1-device--swapchain-생성">Step1. Device &amp; SwapChain 생성</h2>
<p>DirectX 11을 사용하려면 [ Device ] [ Device Context ] [ SwapChain(DXGI) ] 인터페이스를 얻어야 한다.
<code>D3D11CreateDeviceAndSwapChain</code> 함수를 사용하면 위에서 언급한 3개의 인터페이스를 한번에 얻을 수 있다.</p>
<blockquote>
<p><strong>interface 변수 선언</strong></p>
</blockquote>
<pre><code>// interface
ComPtr&lt;ID3D11Device&gt; pDevice;
ComPtr&lt;ID3D11DeviceContext&gt; pImmediateContext;
ComPtr&lt;IDXGISwapChain&gt; pSwapChain;</code></pre><blockquote>
<p><strong>Device flag 설정</strong>
debug version에서는 <code>D3D11_CREATE_DEVICE_DEBUG</code>를, release version에선 0으로 설정한다.</p>
</blockquote>
<ul>
<li><code>D3D11_CREATE_DEVICE_DEBUG</code>: 세팅하는 경우 GPU의 log 출력됨<pre><code>UINT createDeviceFlags = 0;
#ifdef _DEBUG
  createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif</code></pre></li>
</ul>
<blockquote>
</blockquote>
<p><strong>Swap Cahin 설정</strong>
<code>DXGI_SWAP_CHAIN_DESC</code> 구조체를 사용해 설정할 수 있으며
백버퍼 설정, SwapChain과 관련할 윈도우 멀티샘플 설정, 화면모드 설정 등을 지정한다.</p>
<ul>
<li>해당 멤버들은 디폴트 동작이 0으로 설정되어 있는 경우가 많으므로
모든 멤버를 설정하지 않을 경우에는 <code>::ZeroMemory</code> 함수로 초기화하는 것이 편리함</li>
<li>1600*900 resolution의 backBuffer 1개 SwapChain을 설정하는 예<pre><code>DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory( &amp;sd, sizeof( sd ) );                    // 구조체 초기화  
&gt;
sd.BufferCount = 1;                                    // backBuffer Count                                               
sd.BufferDesc.Width = 1600;                            // backBuffer Resolution
sd.BufferDesc.Height = 900;                                                 
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;  // backBuffer Format
sd.BufferDesc.RefreshRate.Numerator = 60;           // 화면 주사율 (기본적으로 60/1)
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;    // backBuffer 용도
sd.OutputWindow = g_hWnd;                           // buffuer output window
sd.SampleDesc.Count = 1;                            // multi sampling count
sd.SampleDesc.Quality = 0;                          // multi sampling quality
sd.Windowed = TRUE;                                 // window mod</code></pre></li>
</ul>
<blockquote>
</blockquote>
<p><strong>D3D11CreateDeviceAndSwapChain 호출</strong></p>
<ul>
<li><code>D3D11CreateDevice</code>, <code>CreateSwapChain</code>으로 나누어 호출해도 됨</li>
<li><code>CreateSwapChain</code>: Factory가 호출<ul>
<li>SwapChain 생성 과정: Device -&gt; Adapter -&gt; Factory -&gt; Swapchain<pre><code>hr = D3D11CreateDeviceAndSwapChain( NULL,                //사용할 IDXGIAdapter 인터페이스
                                D3D_DRIVER_TYPE_HARDWARE, //DirectX 11 디바이스 종류
                                NULL,               //보통  NULL
                                createDeviceFlags,  //디바이스 플래그
                                featureLevels,      //featureLevel 사용할 배열
                                numFeatureLevels,   //featureLevel arr count
                                D3D11_SDK_VERSION,    //DirectX SDK 버전
                                &amp;sd,                //스왑체인 구조체
                                pSwapChain.GetAddressOf(),
                                    //할당할 SwapChain 인터페이스 포인터
                                pDevice.GetAddress(), //할당할 Device 인터페이스 포인터
                                &amp;g_featureLevel,    //featureLevel 얻어낼 포인터
                                pImmediateContext.GetAddressOf() );
                                    //할당할 Device Context 인터페이스 포인터</code></pre></li>
</ul>
</li>
</ul>
<h2 id="step2-backbuffer--depthstencilbuffer-설정">Step2. BackBuffer &amp; DepthStencilBuffer 설정</h2>
<p>swapChain의 backBuffer는 render target으로 설정되어 있지 않다.
swapChain으로부터 backBuffer를 얻어 Device의 renderTarget으로 설정해야 한다.</p>
<blockquote>
<p><strong>Get BackBuffer</strong>
SwapChain으로부터 BackBuffer를 얻어온다.</p>
</blockquote>
<ul>
<li><code>IDXGISwapChain::GetBuffer</code> 함수: backBuffer의 포인터 얻음<pre><code>ComPtr&lt;ID3D11Texture2D&gt; pBackBuffer;
hr = pSwapChain-&gt;GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )pBackBuffer.GetAddress() );
&gt;
if( FAILED( hr ) )
  return hr;</code></pre></li>
</ul>
<blockquote>
<p><strong>Create Render Target View</strong>
texture는 view를 통해 pipeline과 access한다.
render target view는 <code>D3D11_RENDER_TARGET_VIEW_DESC</code> 구조체로 설정하며, 디폴트 설정으로 NULL을 넘긴다.</p>
</blockquote>
<pre><code>hr = g_pd3dDevice-&gt;CreateRenderTargetView( pBackBuffer.Get()
                                    //access할 resource
                                , NULL
                                , &amp;pRenderTargetView.GetAddressOf() );
                                    //render target view를 받아올 변수 ptr
if( FAILED( hr ) )
    return hr;</code></pre><blockquote>
<p><strong>Create Depth Stencil Texture</strong>
<code>D3D11_TEXTURE2D_DESC</code> 구조체로 설정한다.</p>
</blockquote>
<ul>
<li>DepthStencil Buffer: <a href="https://velog.io/@howru_dv/Culling">https://velog.io/@howru_dv/Culling</a><pre><code>D3D11_TEXTURE2D_DESC Desc = {};
ZeroMemory( &amp;descDepth, sizeof(descDepth) );    //초기화
Desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;     // depth 24bit + stencil 8bit
Desc.Width = (UINT)m_vRenderResolution.x;         // render target texture 해상도와 같아야 함
Desc.Height = (UINT)m_vRenderResolution.y;
Desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;         // 용도
Desc.CPUAccessFlags = 0;                         // CPU 접근 불가
Desc.Usage = D3D11_USAGE_DEFAULT;
Desc.SampleDesc.Count = 1;                         // multi sampling
Desc.SampleDesc.Quality = 0;
Desc.MipLevels = 1;                             // 저퀄리티 버전 사본 생성여부
Desc.MiscFlags = 0;                                // 그 외 설정 없음
Desc.ArraySize = 1;
&gt;
hr = m_Device-&gt;CreateTexture2D(&amp;Desc, nullptr, m_DSTex.GetAddressOf());
if (FAILED( hr ))
  return hr;</code></pre></li>
</ul>
<blockquote>
<p><strong>Get Depth Stencil View</strong></p>
</blockquote>
<ul>
<li><code>ID3D11DepthStencilView</code> 인터페이스 사용</li>
<li><code>ID3D11Device::CreateDepthStencilView</code> 함수로 생성<pre><code>m_Device-&gt;CreateDepthStencilView(m_DSTex.Get(), nullptr, m_DSView.GetAddressOf());</code></pre></li>
</ul>
<blockquote>
<p><strong>Set RenderTarget</strong>
Output Merger(OM)에서 render target을 설정한다.
렌더타겟은 동시에 8개까지 설정할 수 있지만 깊이/스텐실 버퍼는 1개 뿐이다.</p>
</blockquote>
<ul>
<li><code>ID3D11DeviceContext::OMSetRenderTargets()</code> 함수를 통해 설정한다<pre><code>g_pImmediateContext-&gt;OMSetRenderTargets( 1                    //renderTarget count
                                     , pRenderTargetView.GetAddressOf()
                                                             //renderTargetView arr pp
                                     , m_DSTex.Get() );    //DepthStencil</code></pre></li>
</ul>
<hr>
<h2 id="step3-viewport-설정">Step3. Viewport 설정</h2>
<p>viewport는 render target의 rendering 영역에 대한 설정이다.
render target에 rendering하려면 각 render target마다 viewport를 설정해야 한다.</p>
<ul>
<li><code>ID3D11DeviceContext::RSSetViewports()</code> 함수로 viewport 설정</li>
<li><code>D3D11_VIEWPORT</code> 구조체로 수행하며, float 형으로 사용<br>

</li>
</ul>
<h3 id="position">Position</h3>
<p>geometry shader, 또는 vertex shader로부터 출력되는 vertex의 위치좌표(3D)는 투영변환 후 투영좌표계의 값이 된다 (x,y = -1 <del>1,  z = 0</del>1)
rasterizer는 뷰포트변환을 수행해 3D 투영좌표계로부터 2D 스크린 좌표(x,y = 0~1)을 계산한다</p>
<ul>
<li>스크린 좌표: 왼쪽 상단이 0,0 으로 Y축이 아래를 향하는 좌표계<ul>
<li>(0,0): backBuffer의 왼쪽 상단</li>
<li>(1,1): bakcBuffer의 오른쪽 하단</li>
</ul>
</li>
<li>viewport 변환식:<ul>
<li>X = (Y+1) * ViewPort.Width * 0.5 + ViewPort.TopLeftX</li>
<li>Y = (1-Y) * ViewPort.Height * 0.5 + ViewPort.TopLeftY</li>
<li>Z = ViewPort.MinDepth + Z * (ViewPort.MaxDepth - ViewPort.MinDepth)</li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>Viewport 설정</strong></p>
</blockquote>
<pre><code>D3D11_VIEWPORT vp;
&gt;
vp.Width =1900.f;
vp.Height = 600.f;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
g_pImmediateContext-&gt;RSSetViewports( 1, &amp;vp );  // rasterizer viewport setting</code></pre><hr>
<p><strong>References</strong>
[1] DirectX Tutorial: <a href="https://blog.naver.com/sorkelf/40161126408">https://blog.naver.com/sorkelf/40161126408</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[DirectX 11 Tutorial]]></title>
            <link>https://velog.io/@howru_dv/DirectX-11</link>
            <guid>https://velog.io/@howru_dv/DirectX-11</guid>
            <pubDate>Wed, 13 Dec 2023 00:36:02 GMT</pubDate>
            <description><![CDATA[<style>
g { color: #00BA71 }
</style>

<h2 id="directx">DirectX</h2>
<p>DirectX는 Windows 프로그램에 고성능 하드웨어 가속 멀티미디어 지원을 제공하는 low-level의 응용 프로그래밍 인터페이스(APl) 집합이다.
<br></p>
<p><strong>[그래픽 하드웨어 연결]</strong></p>
<ul>
<li>DirectX는 응용 프로그램과 그래픽 하드웨어를 연결함</li>
<li>사용자는 해당 그래픽 하드웨어가 DirectX 대응장치이기만 한다면, 하드웨어의 세부사항을 알 필요 없음</li>
<li>DirectX API를 이용해 그래픽 하드웨어에 접근하고, 물체를 렌더링하는 등의 작업 가능<br>

</li>
</ul>
<p><strong>[응용 분야 - 게임 개발]</strong></p>
<ul>
<li>윈도우, 세가, 드림캐스트, 마이크로소프트 엑스박스 및 엑스박스 360 등을 위한 비디오 게임 개발에 많이 사용</li>
</ul>
<hr>
<h2 id="features-of-directx-11">Features of DirectX 11</h2>
<h3 id="compute-shader">Compute Shader</h3>
<p>Compute Shader를 지원함으로써 <strong>*<g>(1)그래픽스 처리</g>*</strong> 이외에도 <strong>*<g>(2)데이터를 병렬처리</g>*</strong>할 수 있는 범용적인 프로세서로써 GPU를 활용할 수 있다.</p>
<ul>
<li>Compute Shader는 DirectX Device를 통해 그래픽스 계열 shader와 resource를 공유하지만, 다른 shader와 직접 연결되진 않음</li>
<li>CPU: OS나 일반 어플리케이션 등을 실행하는 범용 프로세서</li>
<li>GPU: 그래픽스 처리에 특화된 전용 프로세서</li>
</ul>
<p>//</p>
<h3 id="directxgi">DirectXGI</h3>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/52c813ab-fa72-4524-96d6-82f917a4fde7/image.png" alt="">
Direct3D 11은 기초적인 그래픽스 기능을 제공하는 DirectXGI 상에 구축되어 있다.</p>
<p>DirectXGI는 여러 그래픽 API에 공통인 그래픽 관련 작업들을 묶은 것으로, 커널 모드 드라이버 및 시스템 하드웨어와 통신한다. DXGI가 담당하는 영역에는 페이지 전환(스왑체인), 어댑터, 모니터, 디스플레이 모드 등의 그래픽 시스템 정보 등이 있다.</p>
<ul>
<li>간접 조작: DXGI 기능은 Direct3D 11로 접근하므로 어플리케이션 측에서 직접 조작하는 경우는 거의 없음</li>
<li>직접 조작: gamma collection이나 출력 디스플레이 선택하는 등의 컨트롤이 필요할 경우</li>
</ul>
<p>//</p>
<h3 id="swap-chain">Swap Chain</h3>
<p>스왑 체인은 프론트버퍼, 백 버퍼를 포함한 복수의 버퍼의 집합과 이들 사이의 전환 방식의 집합이다.
double buffering의 일종으로, 화면에 그려질 때 깜빡임(flicking)이나 찢어짐(tearing) 현상을 막기 위한 트릭이다. </p>
<p>DirectXGI의 기능으로써 제공된다.</p>
<ul>
<li>메모리 영역: 거의 항상 디스플레이 하위시스템의 메모리에 만들어짐
(대부분 그래픽 카드이지만, 마더보드에도 구현 가능)</li>
<li>Presenting: 페이지를 전환하는 것, 즉 프론트 버퍼와 백 버퍼를 교환해서 화면 상에 백 버퍼를 그리는 행위<br>

</li>
</ul>
<p><strong>[복수의 버퍼 집합]</strong>
DirectX에서는 화면표시, 렌더링을 위해 Front Buffer와 Back Buffer를 사용한다.</p>
<ul>
<li>Front Buffer: 디스플레이에 표시되는 화면 데이터를 가진 버퍼</li>
<li>Back Buffer : 다음 업데이트 내용 씀<br>

</li>
</ul>
<p><strong>[버퍼 전환]</strong>
렌더링이 끝났을 때 Front Buffer의 내용을 갱신한다.</p>
<ul>
<li>갱신 작업 중에는 back buffer에도 렌더링할 수 없음</li>
<li>렌더링 퍼포먼스의 저하를 막기 위해 3개 이상의 버퍼를 준비하는 것도 가능</li>
</ul>
<p>//</p>
<h3 id="device">Device</h3>
<p>DirectX 11 에서는 멀티 스레드 호환이 강화되었다.
DirectX 10의 Device가 11에서는 Device와 DeivceContext로 분할됐다.</p>
<ul>
<li>Device: GPU 메모리 관리 &amp; 리소스 생성</li>
<li>Device Context: GPU 렌더링 명령<br>

</li>
</ul>
<p><strong>[Device]</strong>
리소스 생성에 주로 사용한다. (렌더 타겟 뷰, 상태 변수의 생성 등등에 사용)
각 응용 프로그램에는 하나 이상의 장치가 필요하다. 대부분은 하나의 장치만 만든다.</p>
<ul>
<li>ID3D11Device 인터페이스로 표시</li>
<li>D3D11CreateDevice로 디바이스를 생성하거나, 
D3D11CreateDeviceAndSwapChain으로 device와 swap chain을 동시에 생성<br>

</li>
</ul>
<p><strong>[Device Context]</strong>
device의 설정을 담당한다.
device에서 소유하는 resource를 사용해 파이프라인 상태를 설정하고, 렌더링 명령을 생성할 수 있다. </p>
<ul>
<li>생성된 자원들을 실제로 사용</li>
<li>파이프라인 자체를 조작</li>
</ul>
<p>예시로 상태 변수가 있다.
DepthStencilState 같은 상태 변수를 만들었다면 장치 컨텍스트에 적용시켜줘야 한다.</p>
<ul>
<li>ID3D11DeviceContext 인터페이스로 표시</li>
<li>Imediate Context: device에 직접 렌더링, device에 1개만 존재</li>
<li>Deferred Context: main render thread 이외 worker thread에서 사용</li>
</ul>
<p>//</p>
<h3 id="tessellation">Tessellation</h3>
<p>Tessellation은 정밀도가 낮은 primitive data를 분할해, 보다 정밀한 primitive를 생성해 출력하는 기능이다.</p>
<blockquote>
</blockquote>
<p><strong>[Tessellation OFF]</strong>
<img src="https://velog.velcdn.com/images/howru_dv/post/d9bf7166-5c41-4d89-950d-1d7367d4e4dd/image.jpg" alt=""></p>
<blockquote>
</blockquote>
<p><strong>[Tessellation ON]</strong>
<img src="https://velog.velcdn.com/images/howru_dv/post/47093bd0-02e7-4c3d-8b58-5dd8ad51905a/image.jpg" alt=""></p>
<p>DirectX 11의 graphics pipeline에는 tessellation을 수행하는 1개 stage와 2개 shader(hull shader, domain shader)가 추가돼 realtime으로 tessellation을 수행할 수 있다.</p>
<ul>
<li>primitive: DirectX에서 렌더링하는 도형의 최소단위
(ex 점, 선, 삼각형 ...)<br>

</li>
</ul>
<p>//</p>
<h3 id="dynamic-shader-link">Dynamic Shader Link</h3>
<p>shader를 pipeline에 할당할때 shader code를 드라이버에 최적화할 수 있다.</p>
<ul>
<li>다양한 기능의 셰이더를 사용하기 위해 모든 기능을 갖춘 셰이더를 만들거나, 필요한 조합의 셰이더를 모두 만들 필요가 없어짐</li>
<li>퍼포먼스, 리소스 관리 측면에서 이점</li>
</ul>
<hr>
<h2 id="basic-concept">Basic Concept</h2>
<h3 id="texture--format">Texture &amp; Format</h3>
<p>DirectX에서는 <strong>*<g>특정한 형식을 따르는 자료를 텍스처</g>*</strong>로 저장한다. </p>
<ul>
<li>GPU 필터링, 다중표본화 등의 연산을 텍스쳐에 적용할 수 있음</li>
<li>format: 특정 포맷을 따르는 자료만 저장 가능<br>

</li>
</ul>
<p><strong>[DXGI_FORMAT 예시들]</strong>
텍스처의 자료형들은 DXGI_FORMAT이라는 열거형으로 저장된다.</p>
<blockquote>
</blockquote>
<pre><code>DXGI_FORMAT_R32G32B32_FLOAT     // red,green,blue 32bit float
DXGI_FORMAT_R16G16B16A16_UNORM     // red,green,blue,alpha 16bit로 0~1사이 Normalized 값
DXGI_FORMAT_R32G32_UINT         // red, green 32bit 정수
DXGI_FORMAT_R8G8B8A8_UNORM         // red,green,blue,alpha 8 bit로 0~1값
DXGI_FORMAT_R8G8B8A8_SNORM         // red,green,blue,alpha 8 bit로 -1~1 값
DXGI_FORMAT_R8G8B8A8_SINT         // red,green,blue,alpha 8 bit로 -128~127 값
DXGI_FORMAT_R8G8B8A8_UINT         // red,green,blue,alpha 8 bit로 0~255 값</code></pre><ul>
<li>자료형에는 색상 정보 외에도 3차원 벡터와 같은 다양한 값을 담을 수 있음</li>
</ul>
<blockquote>
</blockquote>
<pre><code>DXGI_FORMAT_R8G8B8A8_TYPELESS     // TYPELESS형</code></pre><ul>
<li>Typeless: 메모리만 확보해두고 해석 방식은 텍스쳐를 파이프라인에 묶을 때 결정</li>
</ul>
<p>//</p>
<h3 id="resource">Resource</h3>
<p>GPU가 어떤 일을 하기 위해선 shader 프로그램이 필요한데, <strong>*<g>shader에 넘겨주는 데이터를 Resource</g>*</strong>라고 한다. 
Scene을 구성하는 기하 도형, 텍스처, 쉐이더 데이터가 모두 resource다.
resource는 buffer와 texture로 구성된다.</p>
<ul>
<li>buffer resource: 1차원 배열(vertex buffer, index buffer 등)</li>
<li>texture resource: 이미지 형태 데이터</li>
</ul>
<p>생명주기: 생성 -&gt; 바인딩 -&gt; 해지</p>
<ul>
<li>Device가 생성</li>
<li>Device Context에 의해 pipeline binding</li>
<li>다 쓰고 나서 Release() 함수로 resource 할당 해제<br>

</li>
</ul>
<p>//</p>
<h3 id="resource-view">Resource View</h3>
<p>resource view는 <strong>*<g>resource를 rendering pipeline에 binding</g>*</strong>해줄 수 있는 객체이다.
하나 이상의 graphics pipeline 단계에서 같은 resource에 접근할 때 resource view로 접근한다.</p>
<ul>
<li>여러 단계의 pipeline은 모두 하나의 같은 resource에 접근</li>
<li>파이프라인 단계마다 resource를 할당하고 복사하지 않기 위해 view 사용<br>

</li>
</ul>
<p><strong>[예외]</strong>
resource는 view를 통해 pipeline에 binding하지만, view 없이 binding 가능한 resource도 있다.</p>
<ul>
<li>Vertex Buffer</li>
<li>Index Buffer</li>
<li>Constant Buffer</li>
<li>Stream Output Buffer<br>

</li>
</ul>
<p><strong>[Resource view list]</strong></p>
<ul>
<li>Render Target View</li>
<li>Depth Stencil View</li>
<li>Shader Resource View</li>
<li>unordered access view (DirectX 11에서 추가)<br>

</li>
</ul>
<p>//</p>
<h3 id="render-target-view">Render Target View</h3>
<p>resource view의 일종으로, Device의 back buffer에 binding되며 생성된다.
rendering pipeline의 출력 중 색상 값을 담는다.
<br></p>
<p><strong>[render target]</strong>
render target은 rendering 대상이다.
예를 들어, texture에 그린다면 texture가, window에 그린다면 back buffer가 render target이다.
<br></p>
<p><strong>[pipeline binding]</strong>
back buffer에 장면을 출력하려고 할 때 render target view를 파이프라인의 마지막 단계인 Output Merget State (OM)에  binding해야 한다.</p>
<ul>
<li>back buffer를 pipeline에 직접 binding할 수 없음</li>
<li>즉, pipeline에서 주는 정보가 back buffer로 바로 연결될 수 없음</li>
<li>pipeline -&gt; render target view -&gt; render target -&gt; graphic device<br>

</li>
</ul>
<p><strong>[render target 설정]</strong>
render target 설정
render target을 설정할 때는 우선 render target view를 만들어준 후, Device Context에서 설정한다.</p>
<pre><code>// backBuffer의 포인터로 render target view 생성
result = m_device-&gt;CreateRenderTargetView(backBufferPtr, NULL, &amp;m_renderTargetView);

// device context 설정
result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &amp;featureLevel, 1,
        D3D11_SDK_VERSION, &amp;swapChainDesc, &amp;m_swapChain, &amp;m_device, NULL, &amp;m_deviceContext);

// device context에 render target 설정
m_deviceContext-&gt;OMSetRenderTargets(1, &amp;m_renderTargetView, m_depthStencilView);</code></pre><p>//</p>
<h3 id="depth-stencil-view">Depth Stencil View</h3>
<p>rendering pipeline의 출력 중 depth와 stencil 값을 담는다.</p>
<p>OM에서 쓰이며, depth와 stencil 모두 output test에 쓰이므로 하나의 view로 묶는다.
<br></p>
<p><strong>[stencil]</strong>
스텐실 값은 두 개 이상 오브젝트가 겹쳤을 때 뭘 표시할지 나타낸다.
depth test와는 달리 앞-뒤 값으로 결정짓는 것이 아니라, 상황에 따른 stencil 값의 대소를 따져 앞-뒤를 계산한다
<br></p>
<p><strong>[code]</strong></p>
<pre><code>// OM setting 시 render target view와 depth stencil buffer를 함께 binding한다
m_deviceContext-&gt;OMSetRenderTargets(1, &amp;m_renderTargetView, m_depthStencilView);</code></pre><p>//</p>
<h3 id="basic-matrix">Basic Matrix</h3>
<ul>
<li>Perspective Projection Matrix <em>원근 투영 행렬</em>: 3D 화면을 2D viewport space으로 변환</li>
<li>Orthographic Projection Matrix <em>직교 투영 행렬</em>: UI와 같은 2D의 요소를 그리기 위해 사용</li>
<li>World Matrix: 오브젝트의 좌표를 3D 세계의 좌표로 변환, 3차원 공간에서의 회전/이동/크기 변환</li>
<li>View Matrix: 현재 장면에서 카메라 위치, 방향 계산</li>
</ul>
<hr>
<h2 id="graphics-pipeline">Graphics Pipeline</h2>
<p><img src="https://velog.velcdn.com/images/howru_dv/post/03a7f432-a419-49bc-abe8-d2135e4ce7e3/image.png" alt=""></p>
<ul>
<li><code>📢필수📢</code> <strong><em>Input-Assembler (IA) :</em></strong>
Vertext Shader에 필요한 데이터 전달
리소스로부터 데이터를 읽어 들여 파이프라인에 데이터를 제공<ul>
<li>Vertex Buffer 와 Index Buffer : 각 프리미티브 정보는 [ 버텍스 버퍼 ] 와 [ 인덱스 버퍼 ] 에 저장하여 파이프라인에 넘김</li>
</ul>
</li>
<li><code>📢필수📢</code> <strong><em>Vertext Shader :</em></strong>
정점의 월드 변환과 뷰 변환 등 필요한 처리</li>
<li><code>🔈선택🔈</code><strong><em>Hull Shader :</em></strong>
Tesselation 기능 구성 shader. 
1<del>32 개의 [ 컨트롤 포인트 ] 를 입력받아, 
1</del>32개의 [컨트롤 포인트] [배치 정수] [테셀레이션 계수] 를 출력</li>
<li><code>🔈선택🔈</code><strong><em>Tessellator :</em></strong>
Tesselation 기능 구성 stage. 
[ 쿼드 배치 ] [ 삼각형 배치 ] [ 선 ]을 입력받아, 
보다 정밀한 다수의 [삼각형] [선] [점]을 출력</li>
<li><code>🔈선택🔈</code><strong><em>Domain Shader :</em></strong>
Tesselation 기능 구성 shader. 
[ Hull Shader ] 와 Tessellator의 출력을 입력받아, 
배치 내의 각 vertex 좌표를 출력</li>
<li><code>🔈선택🔈</code><strong><em>Geometry Shader :</em></strong>
primitive data 1개를 입력받아, primitive의 변형이나 새로운 primitive의 생성을 수행한 후,
0개 또는 1개 이상의 primitive data 출력<ul>
<li>Stream Output  : GS 나 VS 로부터 출력을 리소스 내의 버퍼에 씀</li>
</ul>
</li>
<li><code>📢디폴트📢</code> <strong><em>Rasterizer :</em></strong>
각 정점을 보간해 pixel shader에서 사용할 pregment(픽셀별 정보) 생성</li>
<li><code>📢필수📢</code> <strong><em>Pixel Shader :</em></strong>
픽셀 데이터 1개를 입력받아, 텍스처 처리나 라이팅등을 수행한 후,
픽셀 데이터 1개 출력<ul>
<li>GPU 사용하는 주요 원인</li>
<li>연산 횟수가 가장 많음 (단순 반복 작업)</li>
</ul>
</li>
<li><code>📢디폴트📢</code> <strong><em>Output-Merge(OM) <em>출력 병합기</em> :</em></strong>
pixel shader에서 들어온 색상을 가지고 render target, depth, stencil 등을 고려해,
어떤 걸 표시하고 표시하지 않을지 + 최종 렌더링 색 결정함<ul>
<li>OM에서 계산된 픽셀 색상이 백 버퍼에 그려져서 화면에 보임</li>
</ul>
</li>
</ul>
<hr>
<p><strong>References</strong>
[1] DX11 Feature: <a href="https://blog.naver.com/sorkelf/40160740465">https://blog.naver.com/sorkelf/40160740465</a>
[2] DX Basic Concept: <a href="https://dev-nicitis.tistory.com/46">https://dev-nicitis.tistory.com/46</a>
[3] Graphics Pipeline: <a href="https://learn.microsoft.com/ko-kr/windows/uwp/graphics-concepts/graphics-pipeline">https://learn.microsoft.com/ko-kr/windows/uwp/graphics-concepts/graphics-pipeline</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Library]]></title>
            <link>https://velog.io/@howru_dv/Library</link>
            <guid>https://velog.io/@howru_dv/Library</guid>
            <pubDate>Tue, 12 Dec 2023 04:01:16 GMT</pubDate>
            <description><![CDATA[<h2 id="concept-of-library">Concept of Library</h2>
<p><strong>Library란?</strong>
c언어에서 library는 모듈화를 지원하는 개념이다.</p>
<ul>
<li>목적: 특정한 기능을, 반복적인 코드 작성을 하지 않고 필요한 곳에서 재사용하기 위함</li>
<li>형태: 프로그램이 연결할 수 있는 패키징된 object 파일들의 모음</li>
<li>컴파일된 형태인 object code로 존재하므로(미리 컴파일 되어있으므로) 컴파일 시간 단축됨<blockquote>
</blockquote>
<img src="https://velog.velcdn.com/images/howru_dv/post/b2b0b10f-eaf8-4d44-bdb8-6b7156ea6cb9/image.gif" alt="">
기본적으로 C Programming은 소스 파일을 컴파일하고 그 결과물을 실행한다.
코드가 많아지면 소스파일을 여러 파일로 나누어 격리하고, 목적에 맞는 코드들을 모아 Library를 만든다.
Library는 각각 컴파일되며 링크 단계에서 execute file에 라이브러리(object code)가 연결된다.</li>
</ul>
<p><strong>특징</strong>
header와 구현부가 분리된다.</p>
<ul>
<li>배포하기 쉬움</li>
<li>구현부를 binary code로(.lib 등) 감출 수 있음</li>
</ul>
<p><strong>예시</strong>
게임엔진에서 sound를 처리하기 위해 FMOD를 사용함</p>
<ul>
<li>sound 기능을 이미 잘 구현된 library 활용해 처리</li>
<li>library만 참고해도 내부 함수 사용 가능</li>
</ul>
<hr>
<h2 id="types-of-library">Types of Library</h2>
<p><strong>Library Type</strong>
object code가 Linking되는 방법에 따라 나뉜다.</p>
<ul>
<li>Static Library</li>
<li>Dynamic Linking Library (DLL)<blockquote>
</blockquote>
기능이 추가되면 library의 코드도 많아지고, 각 역할에 맞는 library도 많아져 실행 바이너리의 크기는 점점 증가한다.
한 번만 실행하면 괜찮을 수 있겠지만, 여러번 실행되면 많은 메모리 영역을 차지하고, 그러면 더 많은 메모리가 필요하다.<blockquote>
</blockquote>
따라서 메모리 관리 측면에서, 단일 실행에 적합한 Static Library와 다중 실행에 적합한 Dynamic (Linking) Library 로 library 형태를 구분지을 수 있다.</li>
</ul>
<p><strong>Library Type과 메모리 영역</strong>
<img src="https://velog.velcdn.com/images/howru_dv/post/c1cb7da2-bc0a-45a0-b9c1-1f1cb433fe93/image.png" alt=""></p>
<ul>
<li>Static Library: Text Segment (execute file에 포함됨)</li>
<li>Dynamic Linking Library: Memory Mapping Segment (library process 공유)</li>
</ul>
<hr>
<h2 id="static-library">Static Library</h2>
<p><strong>concept</strong>
compile time에 library가 link된다.</p>
<ul>
<li>object code(*.lib)가 실행 바이너리에 포함됨</li>
<li>각 프로세스는 자체 코드 및 데이터 복사본을 얻음</li>
</ul>
<p><strong>장점</strong></p>
<ul>
<li>runtime 추가 loading 비용 없음: library code는 compile time에 연결되므로 최종 execute file은 runtime 시 library에 종속되지 않음</li>
<li>빠른 속도: 동적 쿼리 등 추가작업 없이 독립적으로(실행 바이너리만으로) library functions 사용 가능</li>
<li>실행 안정성: 한번 execute file을 생성하면, 추후 static library가 제거되더라도 이미 생성된 실행파일을 실행하는 데는 문제 없음</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>바이너리 파일 크기 &amp; 메모리 공간: binary file의 크기가 커지므로 더 많은 공간 필요</li>
<li>update: library를 update할 경우 메인 프로그램을 다시 컴파일해야 함</li>
</ul>
<p><strong>사용</strong></p>
<blockquote>
</blockquote>
<pre><code>#include &lt;*.h&gt;
#pragma comment(lib, &quot;*.lib&quot;)</code></pre><hr>
<h2 id="dynamic-linking-library-dll">Dynamic Linking Library (DLL)</h2>
<p><strong>Concept</strong>
runtime에 library가 link된다</p>
<ul>
<li>object code(*.lib)가 실행 바이너리에 포함되지 않음</li>
<li>라이브러리 프로세스(DLL)는 별도로 존재하며, 각 (실행파일)프로세스는 이를 공유해 사용</li>
<li>특정 시점에 연결하거나, 연결을 끊을 수도 있음</li>
</ul>
<p><strong>Output File</strong></p>
<blockquote>
</blockquote>
<p><strong>*.Lib: DLL의 &quot;Implict Linking&quot; 위한 링크 정보</strong></p>
<ul>
<li>DLL이 제공하고자 하는 함수 정보(함수명)을 가지는 object file</li>
<li>프로그램 실행될 때 어떤 DLL을 쓰겠다는 정보 저장</li>
</ul>
<blockquote>
</blockquote>
<p>*<strong>.DLL: 구현부(binary부)</strong></p>
<ul>
<li>lib의 모든 코드 구현</li>
<li>DLL은 OS에서 두 개 이상 실행되지 않음</li>
<li>execute file 위치에 함께 존재해야 함</li>
</ul>
<p><strong>장점</strong></p>
<ul>
<li>바이너리 파일 크기 &amp; 메모리 공간: 더 작게 사용</li>
<li>update: library를 update하더라도, 이전 버전과 바이너리가 호환되면 다시 컴파일하지 않아도 됨</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>실행 시간: 매번 library 주소에 접근해야 하므로 static library보다 느림</li>
<li>호환성 문제: library가 이미 메모리에 올라가 있지만 변경된 경우, 두 버전의 바이너리가 호환되지 않으면 호환성 문제가 생길 수도 있음(다시 링크해야 함)</li>
</ul>
<hr>
<h2 id="types-of-linking-dll">Types of Linking (DLL)</h2>
<ul>
<li>Implicit Linking <em>암시적 링킹</em></li>
<li>Explicit Linking <em>명시적 링킹</em></li>
</ul>
<p><strong>Implicit Linking</strong>
execute file 자체에 어떤 DLL의 어떤 함수를 사용하겠다는 정보를 포함시킨 링크 방식.</p>
<ul>
<li>DLL의 *.lib 파일 사용</li>
<li>링크 단계: 실행 바이너리의 *.obj 파일들과 DLL의 *.lib 파일을 함께 링크</li>
<li>실행 단계: OS가 프로그램 실행 시(runtime) DLL의 함수 코드를 참조</li>
</ul>
<p><strong>Explicit linking</strong>
프로그램이 실행 중일 때 API를 이용하여 DLL 파일이 있는지 검사하고 동적으로 원하는 함수만 불러와서 사용하는 링크 방식.</p>
<ul>
<li>*.lib 파일 필요 없음</li>
<li>실행 단계: DLL이 필요한 시점에서 로딩하고, 불필요해지면 반환</li>
</ul>
<p>특징</p>
<ul>
<li>메모리 절약</li>
<li>프로그램 실행 중 DLL 교체 및 선택 가능</li>
<li>필요한 순간에 하나씩 DLL을 로딩할 수 있으므로 DLL 로딩에 걸리는 시간 분산 가능</li>
</ul>
<p>예시: Unreal Engine</p>
<ul>
<li>사용자 코드를 DLL로 만듦</li>
<li>코드가 Update되는 경우 이전 버전과 메모리 연결 끊고 다시 빌드, 연결</li>
</ul>
<p>예시: 언어 설정 등의 분기 경우</p>
<ul>
<li>DLL을 사용해서 코드 분기하는 케이스</li>
<li>같은 함수를 찾아 호출하지만, ~한 경우에는 A, ~한 경우에는 B</li>
</ul>
<hr>
<p><strong>Usage</strong></p>
<blockquote>
</blockquote>
<p><strong>&lt;library header&gt;</strong></p>
<ul>
<li><p>export &amp; import</p>
<pre><code>#define DLL_EXPORT extern &quot;C&quot; __declspec(dllexport)
#define DLL_IMPORT extern &quot;C&quot; __declspec(dllimport)</code></pre></li>
<li><p>하나의 헤더로 묶어 처리</p>
<pre><code>#ifdef DYNAMICLIB_EXPORTS
#define MY_DLL extern &quot;C&quot; __declspec(dllexport)
#else
#define MY_DLL extern &quot;C&quot; __declspec(dllimport)
#endif</code></pre></li>
<li><p>library 내에서 사용할 함수, 외부로 공개할 함수 구분 가능</p>
<ul>
<li>export 선언이 있어야 외부로 나감</li>
<li>import 선언이 있어야 참조함</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<p><strong>&lt;Source.cpp&gt;</strong></p>
<pre><code># include &lt;*.h&gt;</code></pre><ul>
<li><p>Implict Linking</p>
<pre><code># pragma comment(lib, *.Lib)</code></pre></li>
<li><p>Explict Linking</p>
<pre><code>// Load DLL
HMODULE hDllHandle = LoadLibrary(L&quot;LibName.dll&quot;);
if (!hDllHandle)
  return 0;
&gt;
// Call DLL Function
// - Funtion Pointer
typedef int(*FUNC_TYPE)(int);
FUNC_TYPE pFunc = nullptr;
pFunc = (FUNC_TYPE)GetProcAddress(hDllHandle, &quot;FuncName&quot;);
if (pFunc)
  int data = pFunc(87);</code></pre></li>
<li><p>LoadLibrary : 필요한 DLL을 프로세스 가상 메모리에 맵핑</p>
</li>
<li><p>GetProcAddress : DLL 함수의 포인터 획득</p>
</li>
<li><p>FreeLibrary : 프로세스 가상 메모리에서 DLL 반환</p>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>