<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>공용 보관함</title>
    <link>https://cherry611.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Fri, 8 May 2026 10:40:00 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>둠칫냐옹</managingEditor>
    <image>
      <title>공용 보관함</title>
      <url>https://tistory1.daumcdn.net/tistory/5614104/attach/7d1c9e10e86a4d00a9177de5913d1bef</url>
      <link>https://cherry611.tistory.com</link>
    </image>
    <item>
      <title>[DX11] 3D 렌더링 엔진 만들기 (3) - Graphics Pipeline</title>
      <link>https://cherry611.tistory.com/13</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Graphics Pipeline&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Shader Stage 들이 직접 코딩할 수 있는 부분이고, 나머지는 API 내부에서 처리해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 다룰 부분은 Vertex Shader와 Pixel Shader이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Vertex shader: 각 vertex에 적용할 수 있는 transformation이나 lighting 등을 수행&lt;/li&gt;
&lt;li&gt;Pixel(fragment) shader : 각 pixel마다 색상을 계산하여 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Cethv/dJMcabjx7Iv/25KhSeiUAGOG9eXVON6R6k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Cethv/dJMcabjx7Iv/25KhSeiUAGOG9eXVON6R6k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Cethv/dJMcabjx7Iv/25KhSeiUAGOG9eXVON6R6k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCethv%2FdJMcabjx7Iv%2F25KhSeiUAGOG9eXVON6R6k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;388&quot; height=&quot;640&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;640&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Input-Assembler(IA) Stage&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇ CPU가 제공한 정보들을 primitive 형태로 모아준다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일반적으로 primitive는 삼각형을 의미한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;관련해서 우리가 해줘야 할 일들은 다음과 같다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1) &lt;span style=&quot;color: #000000;&quot;&gt;Create input buffers&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2) Create the input-layer object&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;3) Bind objects to the input-assembler stage&lt;/li&gt;
&lt;li&gt;4) Specify the primitive type&lt;/li&gt;
&lt;li&gt;5) Call draw methods&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;IA Stage&amp;nbsp; - 1) &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Create input buffers&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;IA Stage에 전달해야 하는 버퍼 : Vertex buffer, Index buffer&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;Create a Vertex Buffer&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. Vertex 구조체를 만든다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Vertex에 기하 정보(position)를 담은 메모리를 할당한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1776018817046&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// header
struct SimpleVertex
{
	XMFLOAT3 Pos;
};

// global variables
ID3D11Buffer* g_pVertexBuffer = nullptr;

///////////////////////////////

SimpleVertex sVertices[] =
    {
        {XMFLOAT3 (0.0f, 0.5f, 0.5f)},
        {XMFLOAT3 (0.5f, -0.5f, 0.5f)},
        {XMFLOAT3 (-0.5f, -0.5f, 0.5f)},
    };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Buffer Description(버퍼 정보들)을 만들어준다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ByteWidth는 buffer의 크기, BindFlags는 어떤 buffer인지를 나타냄.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. &lt;span style=&quot;color: #000000;&quot;&gt;SUBRESOURCE_DATA&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 만든다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실제 데이터 정보에 대한 포인터를 전달해줌.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1776018887859&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;D3D11_BUFFER_DESC bd = {};
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(SimpleVertex) * 3;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;


D3D11_SUBRESOURCE_DATA initData = {};
initData.pSysMem = sVertices;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. &lt;span style=&quot;color: #000000;&quot;&gt;CreateBuffer&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;함수를 호출한다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;D3DDevice에 buffer를 만드는 것을 요청한다.&lt;/li&gt;
&lt;li&gt;함수 인자 값으로 앞서 만든 buffer description, subresource data, 그리고 buffer의 주소를 넣어준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1776018968181&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;hr = g_pd3dDevice-&amp;gt;CreateBuffer(
    &amp;amp;bd,
    &amp;amp;initData,
    &amp;amp;g_pVertexBuffer
    );

if (FAILED(hr))
    return hr;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Create a Index Buffer&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 방식으로 Index Buffer도 만들어준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. Buffer를 만들고 index 정보를 저장한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Buffer description을 생성한다. 이때 flag를 Index buffer로 해야한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1776019087543&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ID3D11Buffer* g_pIndexBuffer = nullptr;

///////////////////////////////

WORD sIndices[] = { 0, 1, 2 };

bd = {};
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(WORD) * 3;
bd.BindFlags = D3D10_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. SUBRESOURCE_DATA&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 만든다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CreateBuffer&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;함수를 호출한다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1776019106451&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;initData = {};
initData.pSysMem = sIndices;

hr = g_pd3dDevice-&amp;gt;CreateBuffer(
    &amp;amp;bd,
    &amp;amp;initData,
    &amp;amp;g_pIndexBuffer
);

if (FAILED(hr))
    return hr;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;IA Stage&amp;nbsp; - 2)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; &lt;span style=&quot;color: #000000;&quot;&gt;Create the Input-Layout Object&lt;/span&gt; &lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;Input-Layout Object&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;는 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IA Stage&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;의 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;input&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에 대한 정보&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앞에서 만든 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;buffer &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;들&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 전달해주는 역할을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Input data에 대한 설명을 해주는 input-element description을 만들어 준다.&lt;/li&gt;
&lt;li&gt;하나의 vertex는 position, normal, uv 등의 element 정보를 가질 수 있음. 하지만 지금은 position만 사용할 예정이기 때문에&amp;nbsp;이를 첫번째 파라미터로 명시해줬다.&lt;/li&gt;
&lt;li&gt;2번째 파라미터 : semantic index&lt;/li&gt;
&lt;li&gt;3번째 파라미터 : element 데이터의 format = 입력 데이터 타입에 따라 명시해주면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1776019392806&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ID3D11InputLayout* g_pVertexLayout = nullptr;

///////////////////////////////

ID3DBlob* pVertexShaderBlob = nullptr;
D3D11_INPUT_ELEMENT_DESC layouts[] =
{
    {&quot;POSITION&quot;,
    0,
    DXGI_FORMAT_R32G32B32_FLOAT,
    0,
    0,
    D3D11_INPUT_PER_VERTEX_DATA,
    0
    },
};

UINT uNumElements = ARRAYSIZE(layouts);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;4번째 파라미터 : input slot&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IA Stage에는 여러 개의 vertex buffer가 들어갈 수 있다.(= 오브젝트가 여러 개인 경우)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 n개의 vertex buffer를 하나의 슬롯으로 할당하여 IA의 input으로 들어간다. 따라서 Input-layout object에서는 몇 번째 slot을 다룰지에 대한 정보가 필요하다. 이게 4번째 파라미터 값이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;5번째 파라미터 : offset = 데이터를 어디서부터 읽을지&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 D3DDevice에세 InputLayout을 만들어달라고 요청한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CreateInputLayout() 파라미터 : layout / element 수 / vertex shader의 포인터 / vertex shader의 크기 / out 파라미터&lt;/li&gt;
&lt;li&gt;Blob : shader 코드 데이터를 가리킨다고 생각하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1776019697212&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;hr = g_pd3dDevice-&amp;gt;CreateInputLayout(
    layouts,
    uNumElements,
    pVertexShaderBlob-&amp;gt;GetBufferPointer(),
    pVertexShaderBlob-&amp;gt;GetBufferSize(),
    &amp;amp;g_pVertexLayout
);

pVertexShaderBlob-&amp;gt;Release();

if (FAILED(hr))
    return hr;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;IA Stage&amp;nbsp; - 3)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;Bind&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Objects&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;the&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IA&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Stage&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&lt;/span&gt;&amp;nbsp; 지금까지 만들어준 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;input buffer&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;들과 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;input layout object&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IA stage&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;binding &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해준다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Stride :&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;vertex buffer&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에서 하나의 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vertex &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정보 크기 = &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SimpleVertex&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구조체의 크기&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Offset : vertex buffer에서 시작 지점&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1776019947517&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;UINT uStride = sizeof(SimpleVertex);
UINT uOffset = 0;

g_pImmediateContext-&amp;gt;IASetVertexBuffers(
    0, 		// slot
    1, 		// buffer의 개수
    &amp;amp;g_pVertexBuffer, 	// vertex buffer
    &amp;amp;uStride, 	    	// stride
    &amp;amp;uOffset	 	// offset
);

g_pImmediateContext-&amp;gt;IASetIndexBuffer(
    g_pIndexBuffer,	 // index buffer
    DXGI_FORMAT_R16_UINT,	 // format of the index data
    0		 	 // offset
);

///////////////////////////

g_pImmediateContext-&amp;gt;IASetInputLayout(g_pVertexLayout);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;IA Stage&amp;nbsp; - 4)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;Specify the Primitive Type&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;nbsp;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IA stage&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에서 어떤 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;primitive type&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;으로 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;assemble&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;할 지에 대해 설정&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앞서 언급한 것 처럼 삼각형 primitive로 설정해줬다.&lt;/span&gt;&lt;/div&gt;
&lt;pre id=&quot;code_1776020234279&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;g_pImmediateContext-&amp;gt;IASetPrimitiveTopology(
    D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;IA Stage&amp;nbsp; - 5)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Call Draw Method&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Binding이 된 후 draw 함수를 호출해서 그려 달라고 요청한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Draw 요청을 하게 되면, DirectX가 그래픽스 파이프라인을 쭉 실행하여 화면에 출력해 준다.&lt;/li&gt;
&lt;li&gt;Draw 함수 종류
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Draw(): Index buffer &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없이 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vertex&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에 따라 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;draw&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DrawIndexed&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;():&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;index buffer&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 이용하여 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;index &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;순서대로 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vertex&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그려준다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Vertex Shader(VS) Stage&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; 모&lt;span style=&quot;color: #000000;&quot;&gt;든 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vertex&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;transformation, skinning, per-vertex lighting &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;과 같은 처리들을 해준다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;vertex 개수만큼 반복 실행된다. = VS의 input도&amp;nbsp;vertex 하나이고, output도 vertex 하나이다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VS&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;는 하나의 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vertex&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 입력으로 하고&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하나의 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vertex&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 출력하는 함수라고 생각하면 된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그리고 앞으로 이 함수를 우리가 정의해 줄 예정이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Vertex Shader&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Shader는 High-Level Shading Language(HLSL)이라는 언어로 작성된다. C++이 아닌 HLSL로 따로 작성하는 이유는 GPU에서 Matrix와 Vector 연산을 훨씬 빠르게 처리할 수 있기 때문이다.&lt;/li&gt;
&lt;li&gt;VS에서 가장 중요한 일은 좌표계 사이를 transform 해주는 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1398&quot; data-origin-height=&quot;178&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTUxXC/dJMcadn4qJj/wYjLSnVc3TRgGYBXFJQl31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTUxXC/dJMcadn4qJj/wYjLSnVc3TRgGYBXFJQl31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTUxXC/dJMcadn4qJj/wYjLSnVc3TRgGYBXFJQl31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTUxXC%2FdJMcadn4qJj%2FwYjLSnVc3TRgGYBXFJQl31%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;655&quot; height=&quot;83&quot; data-origin-width=&quot;1398&quot; data-origin-height=&quot;178&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;input과 output은 float4 형태의 벡터(x,y,z,w)&lt;/li&gt;
&lt;li&gt;POSITION : input parameter의 sementic&lt;/li&gt;
&lt;li&gt;SV_POSITION : 함수의 반환값. 이때 SV는 System Value를 의미한다. = Clip-space의 position&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Rasterizer Stage&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt; 3차원 좌표계에 있는 vertex들을 화면에 그리기 위한 2D pixel(raster image)로 변환해준다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;3D graphic을 2D pixel에 mapping 시키는 단계&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rasterization&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;화면은 2차원 grid로 pixel로 되어있고 각 pixel들은 색깔을 가지고 있다. 이 pixel들을 칠해서 모니터에 화면이 만들어진다.&lt;/li&gt;
&lt;li&gt;아래 그림에서 왼쪽은 3개의 vertex로 구성된 삼각형이고&amp;nbsp;이를 rasterization 하면 오른쪽 그림처럼 된다.&lt;/li&gt;
&lt;li&gt;GPU는 어떤 pixel이 삼각형이 포함되고, 칠해져야 하는지 여부를 계산하게 된다. 이후 칠해져야 하는 pixel들만 pixel shader 단계를 진행하게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;385&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AhO6X/dJMcaaZcHBd/OsI0h61yMF26biLZZPihi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AhO6X/dJMcaaZcHBd/OsI0h61yMF26biLZZPihi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AhO6X/dJMcaaZcHBd/OsI0h61yMF26biLZZPihi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAhO6X%2FdJMcaaZcHBd%2FOsI0h61yMF26biLZZPihi1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;385&quot; height=&quot;180&quot; data-origin-width=&quot;385&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Pixel Shader(PS) Stage&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 최종 pixel의 색깔을 결정하는 단계&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Per-pixel 단위로 Lighting이나 post-processing 같은 처리를 해준다.&lt;/li&gt;
&lt;li&gt;Input : pixel의 색상을 결정할 정보들&lt;/li&gt;
&lt;li&gt;Output : 계산 후 결정된 최종 pixel 색상 정보&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1776021147355&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;float4 PS(float4 Pos : SV_POSITION) : SV_Target
{
    return float4(1.0f, 1.0f, 0.0f, 1.0f);
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;마찬가지로 input과 output은 float 4 타입이다.&lt;/li&gt;
&lt;li&gt;Input의 semantic :&amp;nbsp;SV_POSITION = vertex shader의 output&lt;/li&gt;
&lt;li&gt;Output으로 color(RGBA)를 내보낸다. = SV_Target.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Creating the Shaders&lt;/h3&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;D3DCompileFromFile&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 함수의 인자로 파일 이름이 들어가고&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, shader&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 실행될 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;entry point&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;는 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VS&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로 설정해준다. 이후 컴파일된 결과를 ppBlobOut으로 받아온다.&lt;/span&gt;&lt;/div&gt;
&lt;pre id=&quot;code_1776021292549&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;

#if defined (DEBUG) || defined(_DEBUG)
    dwShaderFlags |= D3DCOMPILE_DEBUG;
    dwShaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
    
    ID3DBlob* pErrorBlob = nullptr;
    hr = D3DCompileFromFile(
    &amp;ldquo;VS.hlsl&amp;rdquo;, 	// FileName
    nullptr, 		// shader macros
    nullptr, 		// include files
    &amp;ldquo;VS&amp;rdquo;,		// Entry point
    &amp;ldquo;vs_5_0&amp;rdquo;,		// shader target
    dwShaderFlags, 	// flag1 
    0, 		// flag2
    ppBlobOut, 		// ID3DBlob out
    &amp;amp;pErrorBlob		// error blob out
    );&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컴파일 한 뒤에는 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Vertex Shader Object&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 만들어준다. 이 과정 역시 Device가 요청하게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파라미터 : 컴파일된 shader의 포인터 / shader의 size / Class link(nullptr) / shader를 가리키는 포인터( &lt;span style=&quot;color: #000000;&quot;&gt;ID3D11VertexShaer*&lt;/span&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1776021449602&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ID3D11VertexShader*  g_pVertexShader = nullptr;

///////////////////////////////

    hr = g_pd3dDevice-&amp;gt;CreateVertexShader(
        pVertexShaderBlob-&amp;gt;GetBufferPointer(), 
        pVertexShaderBlob-&amp;gt;GetBufferSize(), 
        nullptr, 
        &amp;amp;g_pVertexShader);

    if (FAILED(hr))
    {
        pVertexShaderBlob-&amp;gt;Release();
        return hr;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pixel Shader도 마찬가지로 만들어준다.&lt;/p&gt;
&lt;pre id=&quot;code_1776021473438&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ID3D11PixelShader*  g_pPixelShader = nullptr;

///////////////////////////////

    hr = g_pd3dDevice-&amp;gt;CreatePixelShader(
    	pPixelShaderBlob-&amp;gt;GetBufferPointer(), 
    	pPixelShaderBlob-&amp;gt;GetBufferSize(), 
    	nullptr, 
    	&amp;amp;g_pPixelShader);

    if (FAILED(hr))
    {
        pPixelShaderBlob-&amp;gt;Release();
        return hr;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Setting the Shaders&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 만들어둔 shader를 pipeline에 binding 해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1776021586804&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;g_pImmediateContext-&amp;gt;VSSetShader(g_pVertexShader, nullptr, 0);
g_pImmediateContext-&amp;gt;PSSetShader(g_pPixelShader, nullptr, 0);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 포스팅에서는 3D Space와 Transformation 과정에 대해 자세히 다룰 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;KHU 강형엽 교수님 강의의 실습 수업을 수강하며 정리한 내용입니다.&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;</description>
      <category>DX11</category>
      <author>둠칫냐옹</author>
      <guid isPermaLink="true">https://cherry611.tistory.com/13</guid>
      <comments>https://cherry611.tistory.com/13#entry13comment</comments>
      <pubDate>Mon, 13 Apr 2026 04:23:21 +0900</pubDate>
    </item>
    <item>
      <title>[DX11] 3D 렌더링 엔진 만들기 (2) - Window/D3D Initializaiton</title>
      <link>https://cherry611.tistory.com/12</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 포스팅에서는 Window &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;초기화와&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;D3D 11 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;초기화에 대해 설명할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;먼저 Window 초기화부터 코드와 함께 알아보겠다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;InitWindow&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;888&quot; data-origin-height=&quot;334&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ItNpL/dJMcajaKg3d/kJ4PRwnooBLBLERrX1SOo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ItNpL/dJMcajaKg3d/kJ4PRwnooBLBLERrX1SOo1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ItNpL/dJMcajaKg3d/kJ4PRwnooBLBLERrX1SOo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FItNpL%2FdJMcajaKg3d%2FkJ4PRwnooBLBLERrX1SOo1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;469&quot; height=&quot;176&quot; data-origin-width=&quot;888&quot; data-origin-height=&quot;334&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Game.cpp에서 해당 함수에 대한 정의를 해줄 것이고, 아래 3단계로 진행된다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; 1. Register the window class&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; 2. Create window&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; 3. Show window&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;InitWindow - Register window&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1776010714895&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Library::Game.cpp
#include &quot;Game.h&quot;

LPCWSTR g_pszWindowClassName = L&quot;GGPWindowClass&quot;;

HRESULT InitWindow(_In_ HINSTANCE hInstance, _In_ INT nCmdShow)
{
    WNDCLASSEX wcex =
    {
        .cbSize = sizeof(WNDCLASSEX),
        .style = CS_HREDRAW | CS_VREDRAW,
        .lpfnWndProc = WindowProc,
        .cbClsExtra = 0,
        .cbWndExtra = 0,
        .hInstance = hInstance,
        .hIcon = LoadIcon(hInstance,IDI_APPLICATION),
        .hCursor = LoadCursor(nullptr, IDC_ARROW),
        .hbrBackground = reinterpret_cast&amp;lt;HBRUSH&amp;gt;(COLOR_WINDOW + 1),
        .lpszMenuName = nullptr,
        .lpszClassName = g_pszWindowClassName,
        .hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION),
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;좀 중요하게 볼 것들만 적자면&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IpfnWndProc : 현재 window에서 발생한 이벤트를 처리할 window procedure (WindowProc 함수를 만들어줄 예정)&lt;/li&gt;
&lt;li&gt;hInstance : 현재 실행하려는 application. Handle instance로, 식별 ID를 의미한다.&lt;/li&gt;
&lt;li&gt;IpszClassName : 현재 window class의 이름이다. Window끼리 구분을 위해 사용하고 접두사 L은 const wchar_t*를 의미한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1776011339420&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (!RegisterClassEx(&amp;amp;wcex))
{
    DWORD dwError = GetLastError();

    MessageBox(
        nullptr,
        L&quot;Call to RegisterClassEx failed!&quot;,
        L&quot;Game Graphics Programming&quot;,
        NULL
    );

    if (dwError != ERROR_CLASS_ALREADY_EXISTS)
    {
        return HRESULT_FROM_WIN32(dwError);
    }

    return E_FAIL;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WNDCLASSEX를 RegisterClassEx를 통해 등록해준다. 추가로 문제가 있을 경우 오류 처리를 해주는 구문을 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;InitWindow - Creating window&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CreateWindow 함수를 통해서 등록한 window instance를 생성해준다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;창에 대한 handle값을 g_hWnd로 저장한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1776011467275&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Library::Game.cpp

// Global Variable
HWND g_hWnd = nullptr;
HINSTANCE g_hInstance = nullptr;
LPCWSTR g_pszWindowName = L&quot;GGP02: Direct3D 11 Basics&quot;;


// InitWindow() 이어서
g_hInstance = hInstance;
RECT rc = { 0, 0, 800, 600 };
AdjustWindowRect(&amp;amp;rc, WS_OVERLAPPEDWINDOW, FALSE);

g_hWnd = CreateWindow(
    g_pszWindowClassName,
    g_pszWindowName,
    WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
    CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top,
    nullptr,
    nullptr,
    hInstance,
    nullptr
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;InitWindow - Show Window&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마지막으로 윈도우 창을 보여주면 초기화 단계는 끝이 난다! winMain에서 InitWindow를 해주면 실행할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하지만 아직 WindowProc을 구현하지 않았기 때문에 아무것도 보여지지 않고 사용자 입력처리하는 부분도 없다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제 사용자와 OS로부터 event를 어떤식으로 받고 응답하게 되는지 살펴보자.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1776011548700&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Library::Game.cpp

ShowWindow(g_hWnd, nCmdShow);

return S_OK;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Window Messages&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자와 OS로부터 받는 event는 message의 형태로 전달된다. 이때 Message는 단순한 숫자 형태로 정의된다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자 입력 : 마우스 클릭, 키보드 입력&lt;/li&gt;
&lt;li&gt;OS 입력 : 새로운 하드웨어 연결, 저전력 모드 전환&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 &lt;span style=&quot;color: #000000;&quot;&gt;event&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;들은 프로그램이 돌아가는 중에 언제든 일어날 수 있고&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;어떤 순서로 들어올 지 모른다. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이를 유연하게 해결하기 위해&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;window&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에서는 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;message-passing model&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Messages Loop&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇ &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;올바른 window에 message가 전달되도록 프로그램이 while문에서 message를 체크해주는 것&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Application은 실행되는 동안 수천개의 메세지를 받는다. 하지만 여러 개의 window를 가진 프로그램일 수도 있기 때문에 올바른 window에 message가 전달되어야 한다. 이를 위해서는 프로그램이 실행되어 있는 동안, while문으로 무한 반복문을 돌리며 message를 체크해줘야 하고, 이를 message loop라고 부른다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;OS는 이 message들을 다루기 위한 message queue를 만들어 둔다. 이 queue 순서대로 while문에서 처리를 해준다.&lt;/li&gt;
&lt;li&gt;이때 while문에서 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;PeekMessage()&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;s&gt;GetMessage()&lt;/s&gt;) 함수를 통해 queue에서 message를 받아온다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&lt;span&gt; GetMessage()&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일반적으로는 queue에서 message를 받아올 때 GetMessage()를 활용한다.&lt;/li&gt;
&lt;li&gt;이 함수는 queue가 비어 있을 경우, message가 올 때까지 무한히 기다리게 된다.&lt;/li&gt;
&lt;li&gt;특정 이벤트가 없으면 렌더링도 못하고 대기를 해버리기 때문에,, 게임에는 부적합하다. &amp;rarr; 대신 PeekMessage() 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt; Message Loop 동작 예시&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자가 마우스 왼쪽 클릭&lt;/li&gt;
&lt;li&gt;OS가 WM_LBUTTONDOWN message를 queue에 넣음&lt;/li&gt;
&lt;li&gt;Message Loop에서 PeekMessage()함수가 호출됨&lt;/li&gt;
&lt;li&gt;WM_LBUTTONDOWN message를 pull하고,&amp;nbsp; MSG structure에 message 정보를 넣음.&lt;/li&gt;
&lt;li&gt;이후, TranslationMessage()와 DispatchMessage() 함수가 실행됨&lt;/li&gt;
&lt;li&gt;DispatchMessage() 함수에서 메시지에 해당하는 window의 procedure를 실행&lt;/li&gt;
&lt;li&gt;Window procedure에서 해당 메시지를 처리&lt;/li&gt;
&lt;li&gt;다시 Message Loop로 돌아가 다음 메시지를 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Window Procedure&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt; &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;OS에 의해 호출되는 콜백 함수로 message가 발생할 때 해당 이벤트를 처리해준다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우리는 직접 WindowProc 함수를 만들어서 사용할 예정이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1776012573073&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;LRESULT CALLBACK WindowProc(
  _In_ HWND hWnd, 
  _In_ UINT uMsg, 
  _In_ WPARAM wParam, 
  _In_ LPARAM lParam
);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매개변수 : Message 대상이 되는 window의 handle / Message 내용 / Message 추가 정보(wParam, IParam)&lt;/li&gt;
&lt;li&gt;return : LRESULT 값으로, procedure의 결과 값을 나타내는 정수 형태 값이다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1776012713884&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;LRESULT CALLBACK WindowProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_SIZE: // window resizing
        break;
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보통 이런식으로 switch 문을 활용한다. Message 종류가 늘어나면 대응하는 함수를 추가해주면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OS가&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 보내는 모든 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;message&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에 대해 처리를 할 수 없기 때문에&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, (&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해당 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;window&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에 필요 없는 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;message&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;도 포함된&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본적으로 처리하지 않을 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;message&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;들에 대해서는 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DefaultWindowProc&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;함수로&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처리해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Closing Window&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt; DestroyWindow() 함수를 호출해서 창을 닫아준다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자가 window를 끌 때 닫기 버튼을 누를 수도 있고 Alt+F4를 누를 수도 있다. 이 경우 모두 WM_CLOSE message로 전달된다.&lt;/li&gt;
&lt;li&gt;아래 처럼 종료 시에 MessageBox를 통해 확인하는 창을 띄워줄 수도 있다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;WM_DESTROY : Window가 destroy 되기 전에 맞는 Message. 여기서 &lt;span style=&quot;color: #000000;&quot;&gt;PostQuitMessage&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;()를 호출해 &lt;/span&gt;&lt;/span&gt;Message Loop를 멈추고, 할당한 메모리들을 해제해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1776012983957&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;LRESULT CALLBACK WindowProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CLOSE:
        if (MessageBox(hWnd,
            L&quot;진짜 종료하시겠습니까?&quot;,
            L&quot;Game Graphics Programming&quot;,
            MB_OKCANCEL) == IDOK)
        {
            DestroyWindow(hWnd);
        }
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
        
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래와 같은 종료 루프를 가진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;617&quot; data-origin-height=&quot;625&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BDEeG/dJMcahjLO9G/OE28hKAMijrw08hokVOHLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BDEeG/dJMcahjLO9G/OE28hKAMijrw08hokVOHLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BDEeG/dJMcahjLO9G/OE28hKAMijrw08hokVOHLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBDEeG%2FdJMcahjLO9G%2FOE28hKAMijrw08hokVOHLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;358&quot; height=&quot;363&quot; data-origin-width=&quot;617&quot; data-origin-height=&quot;625&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지금까지 Window 초기화에 대해 코드와 함께 알아보았고, 여기서부터는 D3D 초기화에 대해 다룰 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DirectX APIs&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt; Direct2D(D2D) / Direct3D (D3D)는 각각 2D/3D Graphics를 나타내기 위한 API이다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Direct Write는 text layout을 담당한다.&lt;/li&gt;
&lt;li&gt;DirecX Graphics Infrastructure(DXGI)는 low-level에서 rendering 관련된 일을 수행한다. D3D와 그래픽 드라이버 사이를 연결해준다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;D3D는 하드웨어를 가속시킨다. 즉, CPU가 아닌 &lt;b&gt;GPU를 통해 그래픽 연산을 훨씬 빠르게 처리&lt;/b&gt;할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;419&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Kvd3W/dJMb9964Hsg/p7qL5Cah03KFZBxBnrfKT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Kvd3W/dJMb9964Hsg/p7qL5Cah03KFZBxBnrfKT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Kvd3W/dJMb9964Hsg/p7qL5Cah03KFZBxBnrfKT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKvd3W%2FdJMb9964Hsg%2Fp7qL5Cah03KFZBxBnrfKT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;557&quot; height=&quot;275&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;419&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;D3D Initialization&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제 D3D를 통해 만들어진 window에 Scene을 만들어 볼 것이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;초기화를 위해서는 &lt;b&gt;Swap Chain / Device / Immediate Context&lt;/b&gt; 이 세가지를 만들어줘야한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DirectX Device Resource&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;앞서 DXGI를 통해 low-level graphics driver와 D3D를 연결한다고 설명했다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt; 버퍼(buffer)&lt;/b&gt; &lt;/span&gt;: DXGI를 통해 가져오는 그려야 할 공간 = 렌더링하는 메모리 공간. GPU 메모리 상에 버퍼가 있고, 이를 DXGI를 통해 화면에 보여주게 된다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;더블버퍼링(Double Buffering)&lt;/b&gt;&amp;nbsp;&lt;/span&gt;: 화면상에 보이고 있는 버퍼를 &lt;b&gt;'Front Buffer'&lt;/b&gt;라고 하고(수정할 일이 없기 때문에 Read-only), 보이지 않는 버퍼(그리고 있는 버퍼)를 &lt;b&gt;'Back Buffer'&lt;/b&gt;라고 한다. Front가 보여지는 동안 미리 Back Buffer에서 새로운 화면을 그린다. 그리고 화면이 바뀔 때 Front와 Back Buffer를 swap(present)한다. 복사하는 것이 아니라 두 버퍼를 가리키는 포인터를 서로 맞바꾸는 것임.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;렌더 타겟(Render Target)&lt;/b&gt;&lt;/span&gt; : 실제로 렌더링이 일어나고 있는 Back Buffer를 의미한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;403&quot; data-origin-height=&quot;148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s8jZk/dJMcajaKcqr/2O3jnkQbUU0KkXgibaiUBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s8jZk/dJMcajaKcqr/2O3jnkQbUU0KkXgibaiUBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s8jZk/dJMcajaKcqr/2O3jnkQbUU0KkXgibaiUBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs8jZk%2FdJMcajaKcqr%2F2O3jnkQbUU0KkXgibaiUBk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;403&quot; height=&quot;148&quot; data-origin-width=&quot;403&quot; data-origin-height=&quot;148&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;Swap Chain&lt;/b&gt;&lt;/span&gt; : Flip을 하기 위해 순차적으로 쌓이는 DXGI에 있는 버퍼들의 집합을 의미한다. D3D에서는 IDXGISwapChain이라는 인터페이스를 사용한다.&lt;/li&gt;
&lt;li&gt;화면에 draw를 하기 위해 다음 과정을 수행하게 된다.&amp;nbsp;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;application을 위한 window만들기&amp;nbsp;&lt;/li&gt;
&lt;li&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;D3D &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용하기 위한 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 만들기&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;생성된 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;window&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rendering&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하기 위한 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;swap chain&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 만들기&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Render target&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 만들고&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, pixel&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 채운다.&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Swap chain&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;present&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;한다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;. (2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;개의 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;buffer&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 교환하는 것&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;D3D 11 Device &amp;amp; Context&lt;/span&gt;&lt;/h3&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;D3D&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 쓰기 위해서는 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPU&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 위한 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 생성해야 한다. 이때&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ID3D11Device&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;와 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ID3D11DeviceContext가 생성된다.&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ID3D11Device : 자원 관리 (할당/해제)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;픽셀에 &lt;span style=&quot;color: #000000;&quot;&gt;draw&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하기 위한 자원을 할당하고 구성하는 역할&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;필요할 때 호출되는 &lt;span style=&quot;color: #000000;&quot;&gt;method&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;들로 이루어져 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ID3D11DeviceContext : 기능 관리 (렌더링 과정)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;버퍼, 뷰, 기타 자원 로드, drawing과 같은 매 프레임 호출되는 method 들이 포함되어 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;InitDevice에서 D3D Initialization을 해준다. 아래와 같은 다양한 초기화를 담당한다. (자세한 코드는 생략)&lt;/p&gt;
&lt;pre id=&quot;code_1776013605886&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;HRESULT InitDevice()
{
    // Create D3D 11 device &amp;amp; context
    // Obtain DXGI Factory from device
    // Create swap chain
    // Create render target view
    // Setup the viewport
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;초기화 과정에서 D3D11CreateDevice() &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;함수를 통해 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;device&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;와 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;device context&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 모두 만들어준다.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;pre id=&quot;code_1776013646666&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;HRESULT D3D11CreateDevice(
    [in, optional]  IDXGIAdapter*           pAdapter,
                    D3D_DRIVER_TYPE         DriverType,
                    HMODULE                 Software,
                    UINT                    Flags,
    [in, optional]  const D3D_FEATURE_LEVEL*pFeatureLevels,
                    UINT                    FeatureLevels,
                    UINT                    SDKVersion,
    [out, optional] ID3D11Device**          ppDevice,
    [out, optional] D3D_FEATURE_LEVEL*      pFeatureLevel,
    [out, optional] ID3D11DeviceContext**   ppImmediateContext
);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;KHU 강형엽 교수님 강의의 실습 수업을 수강하며 정리한 내용입니다.&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;/div&gt;</description>
      <category>DX11</category>
      <category>DirectX</category>
      <category>Directx11</category>
      <author>둠칫냐옹</author>
      <guid isPermaLink="true">https://cherry611.tistory.com/12</guid>
      <comments>https://cherry611.tistory.com/12#entry12comment</comments>
      <pubDate>Mon, 13 Apr 2026 02:15:36 +0900</pubDate>
    </item>
    <item>
      <title>[DX11] 3D 렌더링 엔진 만들기 (1) - Introduction</title>
      <link>https://cherry611.tistory.com/11</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;목표 : 3D 렌더링 엔진 만들기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Windlow Initialization / D3D Initialization&lt;/li&gt;
&lt;li&gt;Support System&lt;/li&gt;
&lt;li&gt;Cameras / Renderer&lt;/li&gt;
&lt;li&gt;Models&lt;/li&gt;
&lt;li&gt;Materials / Lights&lt;/li&gt;
&lt;li&gt;Etc&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;폴더 구조&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Library Project : 일반적인 렌더링 엔진 구조, 게임에서 공통되게 사용하는 기능들 구현&lt;/li&gt;
&lt;li&gt;Game Project : 어플리케이션에 따라 구체적인 기능들 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/teQMC/dJMcaiiDl6I/0kLnmk9Kzy1q3Enoownmuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/teQMC/dJMcaiiDl6I/0kLnmk9Kzy1q3Enoownmuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/teQMC/dJMcaiiDl6I/0kLnmk9Kzy1q3Enoownmuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FteQMC%2FdJMcaiiDl6I%2F0kLnmk9Kzy1q3Enoownmuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;425&quot; height=&quot;205&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;331&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Window란?&amp;nbsp;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Application window 또는 Main window라고 불란다.&lt;/li&gt;
&lt;li&gt;Frame 구성은 다음과 같다.&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Title bar / Minimize, Maximize button / Other standard UI&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Frame 안에 영역을 Client Area 라고 한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;OK 버튼이나 EditBox들도 Window의 한 종류이다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;422&quot; data-origin-height=&quot;353&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2GF3x/dJMcahRywwk/UaJKnINSo8bMXKHnlDc4t0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2GF3x/dJMcahRywwk/UaJKnINSo8bMXKHnlDc4t0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2GF3x/dJMcahRywwk/UaJKnINSo8bMXKHnlDc4t0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2GF3x%2FdJMcahRywwk%2FUaJKnINSo8bMXKHnlDc4t0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;422&quot; height=&quot;353&quot; data-origin-width=&quot;422&quot; data-origin-height=&quot;353&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Parent Windows &amp;amp; Owner Windows&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UI control window는 application window의 자식 관계이다.&lt;/li&gt;
&lt;li&gt;Parent window는 Child window에게 좌표계를 제공하기 때문에 child는 parent의 좌표계 영역 밖에서 나타나지 않는다.&lt;/li&gt;
&lt;li&gt;새로운 window 알림 창이 나타나는 경우를 dialog라고 한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Window Handles&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Windows들은 object지만 C++의 class는 아니다.&lt;/li&gt;
&lt;li&gt;특정 Window를 나타내기 위해서 handle이라는 변수를 사용한다. 이때 Handle이란 OS가 object를 구분하기 위한 ID 숫자값이다. (포인터가 아니라 단순한 숫자임)&lt;/li&gt;
&lt;li&gt;Window handle의 자료형은 HWND를 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Screen &amp;amp; Window Coordinates&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴퓨터 상에서 좌표계는 pixel 값에 따른다.&lt;/li&gt;
&lt;li&gt;기준에 따라 다음과 같이 3개의 좌표계가 존재한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Screen/Window/Client 좌표계&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모든 좌표계는 좌상단 점을 원점으로 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNAm4Y/dJMcagkOgAC/ThmINvwIKOL3PXUQ87B5v1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNAm4Y/dJMcagkOgAC/ThmINvwIKOL3PXUQ87B5v1/img.png&quot; data-origin-width=&quot;682&quot; data-origin-height=&quot;305&quot; data-is-animation=&quot;false&quot; style=&quot;width: 64.3321%; margin-right: 10px;&quot; data-widthpercent=&quot;65.09&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNAm4Y/dJMcagkOgAC/ThmINvwIKOL3PXUQ87B5v1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNAm4Y%2FdJMcagkOgAC%2FThmINvwIKOL3PXUQ87B5v1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;682&quot; height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLoAcr/dJMcadn4gKB/hPq042QllZ2fMd4KJ6xqSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLoAcr/dJMcadn4gKB/hPq042QllZ2fMd4KJ6xqSk/img.png&quot; data-origin-width=&quot;361&quot; data-origin-height=&quot;301&quot; data-is-animation=&quot;false&quot; style=&quot;width: 34.5051%;&quot; data-widthpercent=&quot;34.91&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLoAcr/dJMcadn4gKB/hPq042QllZ2fMd4KJ6xqSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLoAcr%2FdJMcadn4gKB%2FhPq042QllZ2fMd4KJ6xqSk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;361&quot; height=&quot;301&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;WinMain&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt; 모든 window 프로그램은 WinMain이라는 entry-point가 있다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;C/C++에서 in main 함수와 같은 역할이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5IoVv/dJMcacbEOuB/DlGjfrKzP2TOpipYu26Mi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5IoVv/dJMcacbEOuB/DlGjfrKzP2TOpipYu26Mi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5IoVv/dJMcacbEOuB/DlGjfrKzP2TOpipYu26Mi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5IoVv%2FdJMcacbEOuB%2FDlGjfrKzP2TOpipYu26Mi1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;873&quot; height=&quot;37&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;37&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;hInstance : handle to an instance라고 불리며 OS가 이 값을 이용해서 해당 프로그램이 메모리에 로드될 때 EXE파일의 ID를 구분하게 된다. Handle이기 때문에 포인터가 아닌 정수값이다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;hPrevInstance : 지금은 중요하지 않은 값. 항상 0으로 사용할 것이다.&lt;/li&gt;
&lt;li&gt;pCmdLind : command-lind argument를 Unicode로 인코딩된 string으로 가진다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;pCmdShow : min applicaiton이 minimize/maximize/일반 중 어떤식으로 보여줄 지 나타내는 flag값&lt;/li&gt;
&lt;li&gt;Return 값 : int (C/C++과 동일하게 프로그램의 상태를 나타내는 값이다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Game::Main.cpp - 전처리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UNICODE를 사용해 빌드하기 위해 전처리로 매크로 정의를 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 Windows desktop 프로그램은 &amp;lt;windows.h&amp;gt;를 include 해야한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1775989598654&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#ifndef UNICODE
#define UNICODE
#endif

#include &amp;lt;windows.h&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Game::Main.cpp - wWinMain&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 사용되는 엔진구조는 아래와 같다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;Initialization&lt;/b&gt; &lt;/span&gt;: 어플리케이션이 시작하면서 초기화한다. 필요한 에셋과 데이터를 로드하고 메모리 할당과 같은 초기화 작업을 진행한다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;Game Loop&lt;/b&gt;&lt;/span&gt; : 사용자의 입력의 받아 게임 로직을 수행하고, 이를 렌더링한다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;Destruction&lt;/b&gt;&lt;/span&gt; : 게임이 종료되면 메모리 해제와 같은 Destroy 과정을 거치며 종료한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1775989837123&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;INT WINAPI wWinMain(
    _In_		HINSTANCE hInstance,
    _Int_opt 	HINSTANCE hPrevInstance,
    _In_		LPWSTR IpCmdLine,
    _In_		INT nCmdShow)
{
	// Initialization
    
    while(! /* is game terminated condition set? */)
    {
    	// Handle Input
        // Update (Game Logic)
        // Draw
    }
    
    // Destroy
    
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;wWinMain의 매개변수도 간단히 설명하자면,,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;_In_ : 호출된 함수에 전달되고, 읽기 전용으로 취급&lt;/li&gt;
&lt;li&gt;_Out_ : 호출된 함수가 쓸 공간만 제공. 호출된 함수는 해당 공간에 데이터를 쓴다..&lt;/li&gt;
&lt;li&gt;_In_opt_ : _In_과 같으며, 매개변수가 선택 사항임을 나타낸다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에는 이어서 Window 초기화와 D3D 초기화에 대해 알아보겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;KHU 강형엽 교수님 강의의 실습 수업을 수강하며 정리한 내용입니다.&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;</description>
      <category>DX11</category>
      <category>DirectX</category>
      <category>Directx11</category>
      <author>둠칫냐옹</author>
      <guid isPermaLink="true">https://cherry611.tistory.com/11</guid>
      <comments>https://cherry611.tistory.com/11#entry11comment</comments>
      <pubDate>Sun, 12 Apr 2026 19:37:30 +0900</pubDate>
    </item>
    <item>
      <title>[DirectX12] 5. Output Merger</title>
      <link>https://cherry611.tistory.com/10</link>
      <description>&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;️-direct3d-12-graphics-pipeline&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Direct3D 12 graphics Pipeline&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에는 마지막 단계인 Output Merger를 다룰 예정이다. 여러 요소들을 고려해서 최종 렌더링될 pixel의 섹상을 만들어주는 역할을 한다. 해당 픽셀이 실제 화면에 그려질지, 뒤에 가려지는지, 색을 섞여야하는지 등을 판단하게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WWZhA/dJMcacPS46i/wxNZfievLZCgSoGNsQT971/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WWZhA/dJMcacPS46i/wxNZfievLZCgSoGNsQT971/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WWZhA/dJMcacPS46i/wxNZfievLZCgSoGNsQT971/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWWZhA%2FdJMcacPS46i%2FwxNZfievLZCgSoGNsQT971%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;248&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;354&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-direct3d-12-graphics-pipeline&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Output-Merger(OM) Stage&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt; Pixel Shader의 output인 pixel은 &lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;Depth-Stencil Test, Color Blending&lt;/b&gt;&lt;/span&gt;의 과정을 거친다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;Depth-Stencil Test&lt;/b&gt; : Z-buffer를 활용하여 픽셀이 가려질 경우에 버린다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;Color Blending&lt;/b&gt; : 반투명한 물체나 파티클에서 기존 색과 Blending하는 과정이 필요하다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-direct3d-12-graphics-pipeline&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Pipeline State&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;GPU가 '이 데이터를 어떻게 그릴지' 결정하는 하드웨어 설정들의 집합&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;Rasterizer State&lt;b&gt; : &lt;/b&gt;Cull Mode(Black-face culling), Fill Mode(Wireframe/Solid), Viewport 설정&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;Blend State : Alpha Blending, Additive Blending(파티클) 등&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;Depth-Stencil State : 그릴지 말지 판단 - Depth Test, Stencil Test&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;Primitive Topology : 어떤 형태로 그릴 지 - Triangle, Line 등&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;Shader State : 어떤 셰이더를 쓸 지 - Vertex Shader, Pixel Shader&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt; Pipeline State Object (PSO)&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;: Pipeline State를 하나로 묶어서 미리 생성한 객체&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Direct3D 12에서 대부분의 그래픽 파이프라인 상태는 PSO를 사용하여 설정된다.&lt;/li&gt;
&lt;li&gt;초기화 시 일반적으로 여러 개의 PSO가 미리 생성되고, 이후 렌더링 시에는 상황에 맞는 PSO로 교체한다.&lt;/li&gt;
&lt;li&gt;ex) PSO 1 : 기본 오브젝트(Depth Test On, Blending Off), PSO 2 : 투명 오브젝트(Depth Test ON, Blending ON)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;363&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UGIox/dJMcaaLFtgH/yVmMA565EOVfOPOu7puUBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UGIox/dJMcaaLFtgH/yVmMA565EOVfOPOu7puUBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UGIox/dJMcaaLFtgH/yVmMA565EOVfOPOu7puUBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUGIox%2FdJMcaaLFtgH%2FyVmMA565EOVfOPOu7puUBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;511&quot; height=&quot;281&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;363&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-direct3d-12-graphics-pipeline&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Render Target&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; GPU가 &amp;ldquo;그릴 대상&amp;rdquo;으로 사용하는 버퍼(텍스처) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;렌더링할 때 back buffer에 렌더링하여 바로 화면에 표시하는 대신, temporary intermediate buffer에 렌더링하여 추가적인 작업이나 후처리 효과를 적용할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt; Frame Buffer&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;색(Color) 정보를 저장하는 메모리 영역 = RAM에 저장됨&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;Double Buffering&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Front Buffer&lt;/b&gt; : 현재 화면에 보여지고 있는 버퍼&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Back Buffer&lt;/b&gt; : 지금 그리고 있는 버퍼&lt;/li&gt;
&lt;li&gt;Back Buffer에 미리 렌더링 &amp;rarr; 작업 끝나면 &amp;rarr; Front Buffer와 교체(Swap)&lt;/li&gt;
&lt;li&gt;이 과정을 통해서 화면 깜빡임 문제를 방지할 수 있다. back buffer 없이 바로 화면에 그린다면 중간 상태가 보여지면서 깜빡이는 문제가 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;️-depth-stencil-testing&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Depth-Stencil Testing&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt; Depth-Stencil Buffer를 활용해서 픽셀을 그릴지 말지 결정한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;depth data&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 어떤 픽셀들이 camera에 가장 가까운지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;stencil data&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 어느 pixel을 update할 것인지&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;911&quot; data-origin-height=&quot;284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xxV01/dJMcacpbaLJ/dTPRMiVdcDWHn5NwTKVTKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xxV01/dJMcacpbaLJ/dTPRMiVdcDWHn5NwTKVTKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xxV01/dJMcacpbaLJ/dTPRMiVdcDWHn5NwTKVTKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxxV01%2FdJMcacpbaLJ%2FdTPRMiVdcDWHn5NwTKVTKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;639&quot; height=&quot;199&quot; data-origin-width=&quot;911&quot; data-origin-height=&quot;284&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-depth-stencil-testing&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Depth Test&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt; Depth Buffer를 이용해 어떤 픽셀이 보일지 결정 = &lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;Z-buffering&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1) Depth 값 계산 후 Clamp&amp;nbsp; ( z = min(MaxDepth, max(MinDepth, z)) 활용 )&amp;nbsp; = Viewport 범위 [0~1] 또는 설정 범위로 제한하는 것&lt;/li&gt;
&lt;li&gt;2) Depth Buffer와 비교
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;pixel depth &amp;lt; stored depth : 픽셀이 업데이트 되어야 하는 군 &amp;rarr; Color Buffer, Depth Buffer 업뎃&lt;/li&gt;
&lt;li&gt;pixel depth &amp;gt; stored depth : 안보이는 픽셀 이므로 버림&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt; Z-buffering은 처리되는 순서와 상관없이 동일한 결과가 나온다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MRBrO/dJMcagkNcEA/4FYS2e3Rxsc8LcIXbmG4yK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MRBrO/dJMcagkNcEA/4FYS2e3Rxsc8LcIXbmG4yK/img.png&quot; data-origin-width=&quot;1345&quot; data-origin-height=&quot;620&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.3831%; margin-right: 10px;&quot; data-widthpercent=&quot;49.96&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MRBrO/dJMcagkNcEA/4FYS2e3Rxsc8LcIXbmG4yK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMRBrO%2FdJMcagkNcEA%2F4FYS2e3Rxsc8LcIXbmG4yK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1345&quot; height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mipT8/dJMcadhjjSa/igq8jw4PlgkU10Oh6WZ44K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mipT8/dJMcadhjjSa/igq8jw4PlgkU10Oh6WZ44K/img.png&quot; data-origin-width=&quot;1310&quot; data-origin-height=&quot;603&quot; data-is-animation=&quot;false&quot; width=&quot;602&quot; height=&quot;277&quot; data-widthpercent=&quot;50.04&quot; style=&quot;width: 49.4541%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mipT8/dJMcadhjjSa/igq8jw4PlgkU10Oh6WZ44K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmipT8%2FdJMcadhjjSa%2Figq8jw4PlgkU10Oh6WZ44K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1310&quot; height=&quot;603&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-depth-stencil-testing&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Stencil Test&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;Stencil Buffer 값이 1인 pixel만 Back Buffer로 채운다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;885&quot; data-origin-height=&quot;255&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLSpAe/dJMcabDObz8/crKNtFxcoU6cAtE1w4BFmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLSpAe/dJMcabDObz8/crKNtFxcoU6cAtE1w4BFmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLSpAe/dJMcabDObz8/crKNtFxcoU6cAtE1w4BFmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLSpAe%2FdJMcabDObz8%2FcrKNtFxcoU6cAtE1w4BFmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;631&quot; height=&quot;182&quot; data-origin-width=&quot;885&quot; data-origin-height=&quot;255&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; Tansition effect 적용&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;363&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cx0CCt/dJMcacQe7cb/rxKSvc7nBmzsLnMPqrzTv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cx0CCt/dJMcacQe7cb/rxKSvc7nBmzsLnMPqrzTv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cx0CCt/dJMcacQe7cb/rxKSvc7nBmzsLnMPqrzTv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcx0CCt%2FdJMcacQe7cb%2FrxKSvc7nBmzsLnMPqrzTv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;655&quot; height=&quot;269&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;363&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt; UI에 가려지는 부분 버리기 = fragment 수를 줄여서 성능을 최적화할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqi1TG/dJMb990jRL4/xK9YEqMuGpy67YSd3MEN4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqi1TG/dJMb990jRL4/xK9YEqMuGpy67YSd3MEN4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqi1TG/dJMb990jRL4/xK9YEqMuGpy67YSd3MEN4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbqi1TG%2FdJMb990jRL4%2FxK9YEqMuGpy67YSd3MEN4k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;886&quot; height=&quot;196&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;196&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-depth-stencil-testing&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Color Blending&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt; 새로 그려질 픽셀(c_src)과 기존 화면 색(c_dst)을 섞어서 최종 색(c)을 만드는 과정&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본 렌더링은 Depth Test 통과 시에 덮어쓰게 되지만 반투명한 물체가 있는 경우 뒤의 오브젝트와 Blending이 필요하다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Output value가 렌더 타겟에 찍히기 전에 Pixel Shader의 Output에 Blending Operation이 동작한다.&lt;/li&gt;
&lt;li&gt;블렌딩을 위해서는 불투명한 물체와 투명한 물체를 구분하고, z값이 높은 순으로(&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;back-to-front&lt;/b&gt;&lt;/span&gt;) 처리하게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;912&quot; data-origin-height=&quot;282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bESs7B/dJMcaaZbue4/aLKVV2ba1W6CRKbBbysXKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bESs7B/dJMcaaZbue4/aLKVV2ba1W6CRKbBbysXKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bESs7B/dJMcaaZbue4/aLKVV2ba1W6CRKbBbysXKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbESs7B%2FdJMcaaZbue4%2FaLKVV2ba1W6CRKbBbysXKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;708&quot; height=&quot;219&quot; data-origin-width=&quot;912&quot; data-origin-height=&quot;282&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 Rendering Piepline 포스팅을 마무리하겠습니다--&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;KHU 강형엽 교수님 강의를 수강하며 정리한 내용입니다.&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;</description>
      <category>그래픽스</category>
      <category>DirectX</category>
      <category>그래픽스</category>
      <author>둠칫냐옹</author>
      <guid isPermaLink="true">https://cherry611.tistory.com/10</guid>
      <comments>https://cherry611.tistory.com/10#entry10comment</comments>
      <pubDate>Fri, 10 Apr 2026 15:55:16 +0900</pubDate>
    </item>
    <item>
      <title>[GitHub] Private Repository를 Link로 공유하는 법</title>
      <link>https://cherry611.tistory.com/9</link>
      <description>&lt;h2 id=&quot;-gitfront-사용&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  GitFront 사용&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gitfront.io/&quot;&gt;https://gitfront.io/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;-how-to-&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  How to ?&lt;/h2&gt;
&lt;h3 id=&quot;1-sign-up&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1. Sign Up&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;생략해도 되지만, 하지 않을 경우 생성한 Link에 7일 유효기간이 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;2-add-repository&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. Add Repository&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;로그인 하면 아주 심플한 화면이 나온다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Add Repository 클릭&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Repository URL에 내 GitHub url 주소를 넣어주자.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ytSxi/dJMcaaENRKh/CnyFFJELDLZzUTuEsWkDjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ytSxi/dJMcaaENRKh/CnyFFJELDLZzUTuEsWkDjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ytSxi/dJMcaaENRKh/CnyFFJELDLZzUTuEsWkDjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FytSxi%2FdJMcaaENRKh%2FCnyFFJELDLZzUTuEsWkDjK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;530&quot; height=&quot;388&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;388&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;3-add---convert-to-ssh&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. Add &amp;rarr; Convert to SSH&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Add 버튼 클릭&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Convert to SSH 클릭&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;차례대로 클릭하면 요 화면이 나온다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Copy 해준다&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;543&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dyXg2W/dJMcagE1pEG/PJ778nJh4aahX49dz9s7V0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dyXg2W/dJMcagE1pEG/PJ778nJh4aahX49dz9s7V0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dyXg2W/dJMcagE1pEG/PJ778nJh4aahX49dz9s7V0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdyXg2W%2FdJMcagE1pEG%2FPJ778nJh4aahX49dz9s7V0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;507&quot; height=&quot;543&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;543&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;4-add-key-in-github&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4. Add Key in GitHub&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이제 다시 깃허브로 가준다.&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #f8f9fa; color: #212529; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;본인 프로젝트 -&amp;gt; Settings -&amp;gt; Deploy keys&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Title 마음대로 하고, 내용에 아까 복사한 Key를 넣어준다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;그리고 Add Key&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;675&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDzHrW/dJMcaaENRKk/p3zey2ESshGKRk433wXgE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDzHrW/dJMcaaENRKk/p3zey2ESshGKRk433wXgE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDzHrW/dJMcaaENRKk/p3zey2ESshGKRk433wXgE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDzHrW%2FdJMcaaENRKk%2Fp3zey2ESshGKRk433wXgE0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;675&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;675&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;5-build-in-gitfront&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;5. Build in GitFront&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다시 GitFront로 가서&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Build 클릭&lt;/b&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;543&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IpdYU/dJMcaaENRKg/RYpAPKWaZkoApPSfDnOosK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IpdYU/dJMcaaENRKg/RYpAPKWaZkoApPSfDnOosK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IpdYU/dJMcaaENRKg/RYpAPKWaZkoApPSfDnOosK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIpdYU%2FdJMcaaENRKg%2FRYpAPKWaZkoApPSfDnOosK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;507&quot; height=&quot;543&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;543&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;View 클릭&lt;/b&gt;하면 프로젝트가 보인다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;355&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/04NsU/dJMcafF54aZ/MMfmV2NH74QiuU7y1Ip111/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/04NsU/dJMcafF54aZ/MMfmV2NH74QiuU7y1Ip111/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/04NsU/dJMcafF54aZ/MMfmV2NH74QiuU7y1Ip111/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F04NsU%2FdJMcafF54aZ%2FMMfmV2NH74QiuU7y1Ip111%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;493&quot; height=&quot;355&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;355&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;6-get-link&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;6. Get Link&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;View를 눌러서 프로젝트가 보이면, 오른쪽 상단에 Clone 버튼이 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Clone을 클릭&lt;/b&gt;하면 링크가 나온다. 이제 이 링크를 공유하면 프로젝트를 볼 수 있다.&lt;/li&gt;
&lt;li&gt;❗ 단, 링크 끝에 .git을 지우고 공유해야 한다❗&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1018&quot; data-origin-height=&quot;687&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2DGRu/dJMcaaENRKi/FvgOIyaSdODorSbnJwCEN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2DGRu/dJMcaaENRKi/FvgOIyaSdODorSbnJwCEN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2DGRu/dJMcaaENRKi/FvgOIyaSdODorSbnJwCEN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2DGRu%2FdJMcaaENRKi%2FFvgOIyaSdODorSbnJwCEN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1018&quot; height=&quot;687&quot; data-origin-width=&quot;1018&quot; data-origin-height=&quot;687&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4 id=&quot;reference&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Reference&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=IejuI40oZ5E&quot;&gt;https://www.youtube.com/watch?v=IejuI40oZ5E&lt;/a&gt;&lt;/p&gt;</description>
      <category>Github</category>
      <category>github</category>
      <author>둠칫냐옹</author>
      <guid isPermaLink="true">https://cherry611.tistory.com/9</guid>
      <comments>https://cherry611.tistory.com/9#entry9comment</comments>
      <pubDate>Wed, 1 Apr 2026 17:38:38 +0900</pubDate>
    </item>
    <item>
      <title>Unity 웹 빌드 최적화를 위한 9가지 팁</title>
      <link>https://cherry611.tistory.com/8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Unity WebGL 환경에서는 일반적인 모바일이나 PC 환경보다 성능 제약이 훨씬 크다. 브라우저 위에서 동작하는 구조 특성상 메모리, CPU, GPU 자원이 제한적이며, 특히 고정된 힙 메모리와 싱글 스레드 환경으로 인해 최적화의 중요성이 더욱 커진다. 따라서 단순히 런타임 성능뿐만 아니라 에셋 구성, 로딩 방식, 데이터 처리까지 전반적인 최적화가 필요하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;965&quot; data-origin-height=&quot;427&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfmLi4/dJMcaiJxlIq/XsnGh2VBTgIPDSJkxjaWr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfmLi4/dJMcaiJxlIq/XsnGh2VBTgIPDSJkxjaWr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfmLi4/dJMcaiJxlIq/XsnGh2VBTgIPDSJkxjaWr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfmLi4%2FdJMcaiJxlIq%2FXsnGh2VBTgIPDSJkxjaWr1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;519&quot; height=&quot;230&quot; data-origin-width=&quot;965&quot; data-origin-height=&quot;427&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; 1. 게임 에셋 최적화 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 가장 기본이 되는 최적화는 에셋 자체를 줄이는 것이다. 텍스처와 모델은 게임에서 가장 많은 메모리를 차지하는 요소이기 때문에, 압축 포맷을 사용하거나 해상도를 줄이고, 모델의 폴리곤 수를 낮추는 방식으로 데이터를 줄여야 한다. 이는 메모리 절약뿐만 아니라 다운로드 크기 감소와 로딩 속도 개선에도 직접적인 영향을 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 오브젝트 풀링(Object Pooling) &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; Unity에서 객체를 생성하고 파괴하는 과정은 힙 메모리를 사용하며 GC를 유발한다. WebGL 환경에서는 GC가 메인 스레드를 멈추기 때문에 프레임 드랍이 크게 체감된다. 따라서 오브젝트 풀링을 활용해 객체를 재사용하는 방식이 중요하다. 이는 런타임에서 발생하는 불필요한 메모리 할당을 줄이고, GC 발생 빈도를 낮추는 데 효과적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 다만 오브젝트 풀링을 적용할 때 풀의 크기를 무작정 크게 잡으면 오히려 초기 메모리 사용량이 증가할 수 있다. 특히 WebGL 환경에서는 힙 메모리가 제한되어 있기 때문에, 필요한 만큼만 생성하도록 설계하는 것이 중요하다. 또한 생성 비용이 크지 않거나, 사용 빈도가 낮은 오브젝트까지 풀링하면 오히려 관리 비용만 증가할 수 있기 때문에 총알, 이펙트처럼 반복 생성이 빈번한 객체에 우선적으로 적용하는 것이 효율적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; 3. URP 및 SRP Batcher 활용 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; Unity의 SRP Batcher는 동일한 머티리얼을 사용하는 오브젝트들을 묶어서 처리함으로써 렌더링 시 상태 변경 횟수를 줄여준다. 이를 통해 CPU에서 발생하는 렌더링 비용을 효과적으로 감소시킬 수 있다. 특히 오브젝트 수가 많은 씬에서 성능 향상 효과가 크게 나타난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4. 오클루전 컬링(Occlusion Culling)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 오클루전 컬링은 카메라에 보이지 않는 오브젝트를 렌더링하지 않도록 하는 기술이다. 예를 들어 벽 뒤나 건물 뒤에 가려진 오브젝트는 실제로 화면에 보이지 않지만, 별도의 처리를 하지 않으면 계속 렌더링된다. 오클루전 컬링을 적용하면 이러한 불필요한 GPU 연산을 줄일 수 있어 성능 개선에 도움이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;5. LOD(Level of Detail) 시스템 &lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;1447&quot; data-start=&quot;1284&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; LOD 시스템은 카메라와의 거리에 따라 오브젝트의 디테일을 조절하는 방식이다. 가까이 있는 오브젝트는 높은 디테일을 유지하고, 멀리 있는 오브젝트는 저해상도 모델로 교체함으로써 렌더링 부담을 줄인다. 이를 통해 시각적인 품질을 크게 해치지 않으면서도 GPU 사용량을 효과적으로 줄일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; 6. 조명 베이크(Baked Lighting) &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 실시간 조명은 연산 비용이 높기 때문에 WebGL 환경에서는 부담이 크다. 따라서 가능한 경우 라이트맵과 라이트 프로브를 활용해 조명 정보를 사전에 계산해 두는 것이 좋다. 이렇게 하면 런타임에서의 조명 계산이 줄어들어 전체적인 성능을 안정적으로 유지할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; 7. 문자열 생성 최소화 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; C#에서 문자열은 참조 타입이기 때문에 새로운 문자열을 생성할 때마다 힙 메모리를 사용하게 되고, 이는 GC를 유발한다. 따라서 반복적으로 문자열을 생성하는 로직은 피하는 것이 중요하다. 런타임에 문자열을 빌드해야할 경우 StringBuilder를 사용하거나, JSON이나 XML과 같은 텍스트 기반 데이터 대신 Scriptable Object &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;/ MessagePack / Protobuf 같은 포맷&lt;/span&gt; 바이너리 포맷을 사용하는 것도 성능 개선에 도움이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; 8. Addressable Asset System 활용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; WebGL에서는 모든 리소스를 한 번에 로드하는 방식이 비효율적이다. Addressable을 활용하면 필요한 시점에 필요한 에셋만 비동기적으로 로드할 수 있다. 또한 CDN을 통한 원격 로딩도 가능하기 때문에 초기 로딩 시간을 줄이고 메모리 사용량을 효율적으로 관리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; 9. 포스트 프로세싱 효과 제한 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 블룸이나 모션 블러와 같은 포스트 프로세싱 효과는 전체 화면에 적용되기 때문에 GPU 비용이 크다. WebGL 환경에서는 이러한 효과가 성능 저하의 주요 원인이 될 수 있으므로, 꼭 필요한 경우에만 제한적으로 사용하는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론적으로..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; Unity WebGL 최적화는 특정 기술 하나만 적용한다고 해결되는 문제가 아니다. 에셋, 메모리, 렌더링, 데이터 처리 등 다양한 요소를 종합적으로 고려해야 하며, 각 요소가 서로 영향을 주기 때문에 전체적인 균형이 중요하다. 특히 WebGL 환경에서는 &amp;ldquo;필요한 것만, 최소한의 비용으로 처리한다&amp;rdquo;는 원칙이 핵심이며, 이를 기반으로 설계를 진행하는 것이 안정적인 성능을 확보하는 데 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 사실 위 내용은 꼭 WebGL 환경이 아니라도 사용하는 최적화 방법들이기에,, 다양한 것들을 고려해서 개발하면 좋을 것 같다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://unity.com/how-to/profile-optimize-web-build#the-built-in-render-pipeline-or-urp?&quot;&gt;https://unity.com/how-to/profile-optimize-web-build#the-built-in-render-pipeline-or-urp?&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1775031504659&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;웹 빌드를 프로파일링하고 최적화 (하다) 방법 | Unity&quot; data-og-description=&quot;Unity 웹 프로젝트 최적화(하다) 팁을 확인하세요. 웹 게임이 웹사이트와 소셜 미디어에 효율적으로 배포되고 임베드되도록 최적화해야 합니다.&quot; data-og-host=&quot;unity.com&quot; data-og-source-url=&quot;https://unity.com/how-to/profile-optimize-web-build#the-built-in-render-pipeline-or-urp?&quot; data-og-url=&quot;https://unity.com/how-to/profile-optimize-web-build&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/drB8Y6/dJMb8SXx1QK/7weEH5KRiAfozmvU7byE81/img.jpg?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bRWT9q/dJMb8TB9Rrc/Z7Yp9ff3sMBj1AlIqYYNQK/img.jpg?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://unity.com/how-to/profile-optimize-web-build#the-built-in-render-pipeline-or-urp?&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://unity.com/how-to/profile-optimize-web-build#the-built-in-render-pipeline-or-urp?&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/drB8Y6/dJMb8SXx1QK/7weEH5KRiAfozmvU7byE81/img.jpg?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bRWT9q/dJMb8TB9Rrc/Z7Yp9ff3sMBj1AlIqYYNQK/img.jpg?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;웹 빌드를 프로파일링하고 최적화 (하다) 방법 | Unity&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Unity 웹 프로젝트 최적화(하다) 팁을 확인하세요. 웹 게임이 웹사이트와 소셜 미디어에 효율적으로 배포되고 임베드되도록 최적화해야 합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;unity.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Unity</category>
      <category>unity</category>
      <category>webgl</category>
      <author>둠칫냐옹</author>
      <guid isPermaLink="true">https://cherry611.tistory.com/8</guid>
      <comments>https://cherry611.tistory.com/8#entry8comment</comments>
      <pubDate>Wed, 1 Apr 2026 17:24:13 +0900</pubDate>
    </item>
    <item>
      <title>[DirectX12] 4. Pixel Shader - Lighting</title>
      <link>https://cherry611.tistory.com/7</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-direct3d-12-graphics-pipeline&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Direct3D 12 graphics Pipeline&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 포스팅에서는 pixel shader가 하는 일 중 texturing과 관련해서 texel과 pixel의 해상도 차이로 인한 확대,축소 문제를 어떻게 해결하는지 살펴봤다. 오늘 다룰 내용은 Lighting이다. 전통적인 phong 모델부터 per-pixel lighting, blinn-phong model까지 살펴볼 예정이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WWZhA/dJMcacPS46i/wxNZfievLZCgSoGNsQT971/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WWZhA/dJMcacPS46i/wxNZfievLZCgSoGNsQT971/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WWZhA/dJMcacPS46i/wxNZfievLZCgSoGNsQT971/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWWZhA%2FdJMcacPS46i%2FwxNZfievLZCgSoGNsQT971%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;248&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;354&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-phong-lighting-model&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Phong Lighting Model&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&amp;nbsp;&lt;span&gt; &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;Diffuse / Specular / Ambiend / Emissive 4가지를 섞어 그럴듯하게 빛을 표현하자&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 유명하고 전통적인 방식이다.&lt;/li&gt;
&lt;li&gt;approximation을 어떻게 잘 하는지가 중요하다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-phong-lighting-model&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Light Sources&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&amp;nbsp;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;Point light&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 point로부터 전방향으로 빛을 뿜어낸다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;point로부터 거리에 따라 intensity가 결정된다&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇ &lt;b&gt;Directional&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&amp;nbsp;light&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;scene으로부터 멀리 떨어진 곳에서 보내는 빛&amp;nbsp; ex) 태양&lt;/li&gt;
&lt;li&gt;scene 전체에서 one direction이다.&lt;/li&gt;
&lt;li&gt;내가 어디에 존재하든 일정한 direction과 크기를 가진다&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&amp;nbsp;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;Spotlight&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;cone shaped light&lt;/li&gt;
&lt;li&gt;거리와 각도에 따라 intensity가 달라진다.&lt;/li&gt;
&lt;li&gt;ex) 형광등, 백열등&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&amp;nbsp;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;Ambient&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;은은하게 밝혀주는 간접광&lt;/li&gt;
&lt;li&gt;반사되어 떠도는 빛을 계산하기 어렵기 때문에 constant value로 뭉개서 계산한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-phong-lighting-model&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Diffuse (난반사광)&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇ &lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;물체 표면에 빛이 반사되었을 때 전방향으로 uniform하게 퍼지는 것을 modeling한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Lambert's law&lt;/b&gt;를 따른다&amp;nbsp; &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;= 입사각이 작을 수록 밝게 보인다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Diffuse 조명은 표면의 밝기가 빛의 입사각&lt;span&gt;&amp;nbsp;&lt;/span&gt;cos(&amp;theta;)에 비례한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&amp;theta;: 빛의 방향과 표면 법선 벡터(normal) 사이의 각도&lt;/li&gt;
&lt;li&gt;관찰자의 위치와 밝기는 무관하다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhzdGc/dJMcahwUh5u/NM1jEjhZiQCVP2rIk3v8y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhzdGc/dJMcahwUh5u/NM1jEjhZiQCVP2rIk3v8y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhzdGc/dJMcahwUh5u/NM1jEjhZiQCVP2rIk3v8y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdhzdGc%2FdJMcahwUh5u%2FNM1jEjhZiQCVP2rIk3v8y1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;396&quot; height=&quot;236&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Diffuse computation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;386&quot; data-origin-height=&quot;59&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KDqF5/dJMcafy5KPB/xLofp5Cr3Y7cCjwWXEezj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KDqF5/dJMcafy5KPB/xLofp5Cr3Y7cCjwWXEezj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KDqF5/dJMcafy5KPB/xLofp5Cr3Y7cCjwWXEezj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKDqF5%2FdJMcafy5KPB%2FxLofp5Cr3Y7cCjwWXEezj1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;386&quot; height=&quot;59&quot; data-origin-width=&quot;386&quot; data-origin-height=&quot;59&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li data-end=&quot;370&quot; data-start=&quot;335&quot;&gt;&lt;b&gt;n&lt;/b&gt; : surface normal (표면 법선 벡터)&lt;/li&gt;
&lt;li data-end=&quot;406&quot; data-start=&quot;371&quot;&gt;&lt;b&gt;l&lt;/b&gt; : light direction (빛 방향 벡터)&lt;/li&gt;
&lt;li data-end=&quot;433&quot; data-start=&quot;407&quot;&gt;&lt;b&gt;n &amp;middot; l&lt;/b&gt; : 두 벡터의 내적&lt;/li&gt;
&lt;li data-end=&quot;459&quot; data-start=&quot;434&quot;&gt;&lt;b&gt;max(n&amp;middot;l, 0)&lt;/b&gt; : 음수 제거&lt;/li&gt;
&lt;li data-end=&quot;489&quot; data-start=&quot;460&quot;&gt;&lt;b&gt;s_d&lt;/b&gt; : light color (빛 색)&lt;/li&gt;
&lt;li data-end=&quot;531&quot; data-start=&quot;490&quot;&gt;&lt;b&gt;m_d&lt;/b&gt; : material diffuse color (물체 색)&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;position: absolute;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4TVa8/dJMcaiCxK1U/6Lc0zksGdGVlXWNvrCOypk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4TVa8/dJMcaiCxK1U/6Lc0zksGdGVlXWNvrCOypk/img.png&quot; data-alt=&quot;white light (1,1,1)이 들어올 때, 물체가 노란색이면 R,G값은 반사하고 B는 흡수한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4TVa8/dJMcaiCxK1U/6Lc0zksGdGVlXWNvrCOypk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4TVa8%2FdJMcaiCxK1U%2F6Lc0zksGdGVlXWNvrCOypk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;687&quot; height=&quot;238&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;340&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;white light (1,1,1)이 들어올 때, 물체가 노란색이면 R,G값은 반사하고 B는 흡수한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;️-phong-lighting-model&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Specular (정반사광)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;물체 표면에 빛이 닿을 때, 특정 방향으로 강하게 반사되는 조명 효과&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;표면 특정 부분에 highlight 효과를 줄 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;관찰자의 방향에 따라 밝기가 달라진다.
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: view vector&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: reflection vector&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;h&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: shininess &lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;(클수록 날카롭고 작은 하이라이트)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: light source의 gray-scale value&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: highlight on the surface&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;317&quot; data-origin-height=&quot;61&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Glkt7/dJMcadOJwLW/jnSwLmbYGQlaYlJcbT2uLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Glkt7/dJMcadOJwLW/jnSwLmbYGQlaYlJcbT2uLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Glkt7/dJMcadOJwLW/jnSwLmbYGQlaYlJcbT2uLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGlkt7%2FdJMcadOJwLW%2FjnSwLmbYGQlaYlJcbT2uLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;317&quot; height=&quot;61&quot; data-origin-width=&quot;317&quot; data-origin-height=&quot;61&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwYz2w/dJMcacbhrmT/PxeqhzkNUpzho1BWkOrUR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwYz2w/dJMcacbhrmT/PxeqhzkNUpzho1BWkOrUR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwYz2w/dJMcacbhrmT/PxeqhzkNUpzho1BWkOrUR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwYz2w%2FdJMcacbhrmT%2FPxeqhzkNUpzho1BWkOrUR0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;553&quot; height=&quot;344&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;452&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-ambient-term&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Ambient&lt;span&gt;&amp;nbsp;&lt;/span&gt;(간접광)&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt; 주변에 퍼져있는 일관된 빛&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;씬 내의 다양한 물체에 반사된 빛&lt;/li&gt;
&lt;li&gt;표면에 도달한 주변 조명은 모든 방향에서 동일한 강도로 산란된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-emissive-term&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Emissive&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt; &lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;표면 자체에서 방출되는 빛&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;351&quot; data-origin-height=&quot;298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coTOk8/dJMcaa5BJTA/9D1fBLAcAMqe6jbStUBSp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coTOk8/dJMcaa5BJTA/9D1fBLAcAMqe6jbStUBSp0/img.png&quot; data-alt=&quot;emissive 적용 전(좌), emissive 적용 후(우)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coTOk8/dJMcaa5BJTA/9D1fBLAcAMqe6jbStUBSp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoTOk8%2FdJMcaa5BJTA%2F9D1fBLAcAMqe6jbStUBSp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;351&quot; height=&quot;298&quot; data-origin-width=&quot;351&quot; data-origin-height=&quot;298&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;emissive 적용 전(좌), emissive 적용 후(우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;️-phong-lighting-model&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Phong Lighting Model&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&amp;nbsp;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #0593d3; text-align: start;&quot;&gt;Diffuse / Specular / Ambiend / Emissive 4가지 term을 합쳐서 표현한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;845&quot; data-origin-height=&quot;597&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tQksF/dJMcadOJxhD/oO81c4Xp8rPmQlSLmA8dC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tQksF/dJMcadOJxhD/oO81c4Xp8rPmQlSLmA8dC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tQksF/dJMcadOJxhD/oO81c4Xp8rPmQlSLmA8dC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtQksF%2FdJMcadOJxhD%2FoO81c4Xp8rPmQlSLmA8dC1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;563&quot; height=&quot;398&quot; data-origin-width=&quot;845&quot; data-origin-height=&quot;597&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-per-pixel-lighting&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Per-pixel Lighting&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&amp;nbsp;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt; &lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;각 픽셀 단위에서 조명을 계산하는 방식&lt;/span&gt; &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;per-vertex 방식에 비해 high quality&lt;/li&gt;
&lt;li&gt;per-vertex 방식은 정점만 밝기 계산을 하고, 그 사이 픽셀은 선형 보간해서 부드럽지 않은 부분이 생긴다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;411&quot; data-origin-height=&quot;208&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TuKfS/dJMcaakeIQY/kXV0sHdicITDsEZvqy3oR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TuKfS/dJMcaakeIQY/kXV0sHdicITDsEZvqy3oR1/img.png&quot; data-alt=&quot;per-vertex(좌), per-pixel(우)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TuKfS/dJMcaakeIQY/kXV0sHdicITDsEZvqy3oR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTuKfS%2FdJMcaakeIQY%2FkXV0sHdicITDsEZvqy3oR1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;411&quot; height=&quot;208&quot; data-origin-width=&quot;411&quot; data-origin-height=&quot;208&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;per-vertex(좌), per-pixel(우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; background-color: #ffffff;&quot;&gt;&lt;b&gt; pixel shader에서 per-pixel 조명 계산을 위해 필요한 벡터&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #0593d3; background-color: #ffffff;&quot;&gt;&lt;b&gt;&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;l&lt;/b&gt; : light vector&lt;/li&gt;
&lt;li&gt;&lt;b&gt;n&lt;/b&gt; : normal&lt;/li&gt;
&lt;li&gt;&lt;b&gt;v&lt;/b&gt; : view vector&lt;/li&gt;
&lt;li&gt;&lt;b&gt;r&lt;/b&gt; : reflection vector&amp;nbsp; ( r = 2n(n&amp;middot;l) - l )&lt;/li&gt;
&lt;li&gt;(이때 l은 directional light로 모든 surface에서 동일 / n,r,v는 픽셀마다 다름)&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;중요한 점은 l이 world space 기준이기 때문에 n,v도 world space 기준 좌표가 필요하다!&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;n과 v는 vertex shader에서 pixel shader로 넘겨주는 값이고, r은 직접 계산이 가능하기 때문에 파라메터를 하나 줄일 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;403&quot; data-origin-height=&quot;401&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mLCFY/dJMcabjamTj/t0FKkHSR7kEby5FQHAhRc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mLCFY/dJMcabjamTj/t0FKkHSR7kEby5FQHAhRc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mLCFY/dJMcabjamTj/t0FKkHSR7kEby5FQHAhRc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmLCFY%2FdJMcabjamTj%2Ft0FKkHSR7kEby5FQHAhRc1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;217&quot; height=&quot;216&quot; data-origin-width=&quot;403&quot; data-origin-height=&quot;401&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; background-color: #ffffff;&quot;&gt;&lt;b&gt;&lt;span&gt; Normal이 pixel마다 생기는 과정&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;vertex shader : vertex normal을 &lt;b&gt;world space&lt;/b&gt;로 변환&lt;/li&gt;
&lt;li&gt;rasterizer : vertex normal을 보간&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kCg3C/dJMcagSiocN/hN1KFQKE2wUZn6vbJL7fCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kCg3C/dJMcagSiocN/hN1KFQKE2wUZn6vbJL7fCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kCg3C/dJMcagSiocN/hN1KFQKE2wUZn6vbJL7fCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkCg3C%2FdJMcagSiocN%2FhN1KFQKE2wUZn6vbJL7fCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;374&quot; height=&quot;197&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;331&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; background-color: #ffffff;&quot;&gt;&lt;b&gt;&lt;span&gt;&lt;span&gt; View vector가&lt;/span&gt;&amp;nbsp;pixel마다 생기는 과정&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;vertex shader : v = cameraPos - vertexPos (&lt;b&gt;world space&lt;/b&gt; 좌표임)&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;rasterizer&lt;span&gt; &lt;/span&gt;&lt;/span&gt;: vector 보간&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;326&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m9b0C/dJMcahDDybU/c3L9DchrMtpdBGyoqBPLUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m9b0C/dJMcahDDybU/c3L9DchrMtpdBGyoqBPLUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m9b0C/dJMcahDDybU/c3L9DchrMtpdBGyoqBPLUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm9b0C%2FdJMcahDDybU%2Fc3L9DchrMtpdBGyoqBPLUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;179&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;326&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; background-color: #ffffff;&quot;&gt;&lt;b&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt; 최종 pixel 별 Phong lighting 계산&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;n,v,l이 준비되었기 때문에 r은 계산을 통해서 구할 수 있다.&lt;/li&gt;
&lt;li&gt;다음 최종적으로 pixel마다 phong lighting을 계산하면 per-pixel을 구현할 수 있게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;704&quot; data-origin-height=&quot;344&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nUHL6/dJMcagLxkBw/pJtVW9DKRtZUa9UGKxxBd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nUHL6/dJMcagLxkBw/pJtVW9DKRtZUa9UGKxxBd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nUHL6/dJMcagLxkBw/pJtVW9DKRtZUa9UGKxxBd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnUHL6%2FdJMcagLxkBw%2FpJtVW9DKRtZUa9UGKxxBd1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;475&quot; height=&quot;232&quot; data-origin-width=&quot;704&quot; data-origin-height=&quot;344&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-blinn-phong-reflection-model&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Blinn-Phong Reflection Model&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&amp;nbsp;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt; &lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;Phong model의 modified(수정된) version&lt;/span&gt; &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;Phong은 lighting approximation에 효율적이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;그러나 &lt;b&gt;specular term에서 가끔 unrealistic한 결과&lt;/b&gt;를 낸다.&lt;/span&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;317&quot; data-origin-height=&quot;61&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Glkt7/dJMcadOJwLW/jnSwLmbYGQlaYlJcbT2uLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Glkt7/dJMcadOJwLW/jnSwLmbYGQlaYlJcbT2uLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Glkt7/dJMcadOJwLW/jnSwLmbYGQlaYlJcbT2uLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGlkt7%2FdJMcadOJwLW%2FjnSwLmbYGQlaYlJcbT2uLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;317&quot; height=&quot;61&quot; data-origin-width=&quot;317&quot; data-origin-height=&quot;61&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;188&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VeXgl/dJMcahp8kKR/DyZhmowwotEdESUi4Uusi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VeXgl/dJMcahp8kKR/DyZhmowwotEdESUi4Uusi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VeXgl/dJMcahp8kKR/DyZhmowwotEdESUi4Uusi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVeXgl%2FdJMcahp8kKR%2FDyZhmowwotEdESUi4Uusi1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;629&quot; height=&quot;188&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;188&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;dot project는 cos 계산이기 때문에 90도를 넘기면 음수를 반환하고, 그대로 max()를 통과하면 0이 된다.&lt;/li&gt;
&lt;li&gt;이런 급격한 cut off 때문에 &lt;b&gt;경계(boundray)&lt;/b&gt;가 생긴다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tmxk5/dJMcajuGf1p/zymNIhQmqj8zGYXNkScLhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tmxk5/dJMcajuGf1p/zymNIhQmqj8zGYXNkScLhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tmxk5/dJMcajuGf1p/zymNIhQmqj8zGYXNkScLhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ftmxk5%2FdJMcajuGf1p%2FzymNIhQmqj8zGYXNkScLhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;565&quot; height=&quot;215&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span&gt; Blinn-Phong reflection model - specular term&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;reflection vector(r) 대신에 &lt;b&gt;halfway vector(h)&lt;/b&gt;를 이용한다.&lt;/li&gt;
&lt;li&gt;h : &lt;span style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #212529; text-align: start;&quot;&gt;&amp;nbsp;(view vector) 와&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #212529; text-align: start;&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;l&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #212529; text-align: start;&quot;&gt;&amp;nbsp;(light vector)을 이등분(&lt;/span&gt;&lt;b&gt;bisects&lt;/b&gt;&lt;span style=&quot;color: #212529; text-align: start;&quot;&gt;)하는 벡터&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #212529; text-align: start;&quot;&gt;blinn phong의 장점 &lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #212529;&quot;&gt;r과 v의 차이가 90도가 넘더라도, h와 n 사이 각도는 90도가 넘지 않기 때문에 이전의 문제점이 해결된다!&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #212529;&quot;&gt;추가로 r을 구하기 위해서 내부적으로 내적을 했었는데, 이 과정이 없어지고 단순한 덧셈 연산으로 중간 벡터를 구하기 때문에 처리도 빨라진다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;161&quot; data-origin-height=&quot;87&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Vfrma/dJMcaaLiVZG/5YVcOkmU82njBGOJ7Aqn10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Vfrma/dJMcaaLiVZG/5YVcOkmU82njBGOJ7Aqn10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Vfrma/dJMcaaLiVZG/5YVcOkmU82njBGOJ7Aqn10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVfrma%2FdJMcaaLiVZG%2F5YVcOkmU82njBGOJ7Aqn10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;135&quot; height=&quot;73&quot; data-origin-width=&quot;161&quot; data-origin-height=&quot;87&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;422&quot; data-origin-height=&quot;84&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wGanU/dJMcac9764t/ZeazJwafwgwd859Nv3ekI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wGanU/dJMcac9764t/ZeazJwafwgwd859Nv3ekI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wGanU/dJMcac9764t/ZeazJwafwgwd859Nv3ekI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwGanU%2FdJMcac9764t%2FZeazJwafwgwd859Nv3ekI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;387&quot; height=&quot;77&quot; data-origin-width=&quot;422&quot; data-origin-height=&quot;84&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;178&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbAJ99/dJMcacbhtjx/VxmAEhUgHJrTNR3mYaXzyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbAJ99/dJMcacbhtjx/VxmAEhUgHJrTNR3mYaXzyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbAJ99/dJMcacbhtjx/VxmAEhUgHJrTNR3mYaXzyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbAJ99%2FdJMcacbhtjx%2FVxmAEhUgHJrTNR3mYaXzyK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;578&quot; height=&quot;178&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;178&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;적용 결과
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;specular term을 개선한 것이기 때문에, 바다에 반사되는 햇빛이나 젖은 땅에 멀리 떨어진 가로등이 반사되는 등 평면에 대한 반사를 표현할 때 훨씬 현실적인 표현이 가능해진다고 한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;856&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sbp2M/dJMcaiJigcE/VIGBJmNdHZkMuQrzqG07y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sbp2M/dJMcaiJigcE/VIGBJmNdHZkMuQrzqG07y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sbp2M/dJMcaiJigcE/VIGBJmNdHZkMuQrzqG07y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsbp2M%2FdJMcaiJigcE%2FVIGBJmNdHZkMuQrzqG07y1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;616&quot; height=&quot;304&quot; data-origin-width=&quot;856&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;KHU 강형엽 교수님 강의를 수강하며 정리한 내용입니다.&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;</description>
      <category>그래픽스</category>
      <category>DirectX</category>
      <category>그래픽스</category>
      <author>둠칫냐옹</author>
      <guid isPermaLink="true">https://cherry611.tistory.com/7</guid>
      <comments>https://cherry611.tistory.com/7#entry7comment</comments>
      <pubDate>Fri, 13 Mar 2026 23:06:44 +0900</pubDate>
    </item>
    <item>
      <title>[DirectX12] 3. Pixel Shader - Texturing</title>
      <link>https://cherry611.tistory.com/6</link>
      <description>&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;️-direct3d-12-graphics-pipeline&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Direct3D 12 graphics Pipeline&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rasterizer를 통해 pixel이 생성되고, 일부 값들을 보간해서 채워줬다. 이제 Pixel shader에서는 그 위에 Texturing과 Lighting 작업을 해준다. 이번 포스팅에서는 그 중에서 Texturing에 대해 알아볼 예정이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1457&quot; data-origin-height=&quot;415&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWISAE/dJMcaiJh7Fn/r2917p6s5sfDhpvkUSku60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWISAE/dJMcaiJh7Fn/r2917p6s5sfDhpvkUSku60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWISAE/dJMcaiJh7Fn/r2917p6s5sfDhpvkUSku60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWISAE%2FdJMcaiJh7Fn%2Fr2917p6s5sfDhpvkUSku60%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;744&quot; height=&quot;212&quot; data-origin-width=&quot;1457&quot; data-origin-height=&quot;415&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;-image-texturing&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Image Texturing&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&amp;nbsp; &lt;/span&gt; &lt;b&gt;&lt;span style=&quot;text-align: start;&quot;&gt;rasterizer가 보간한 texture 좌표에 texture 해상도를 곱해서 실제 texture에서 rgb값을 꺼내오는 것&lt;/span&gt; &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1) 모델링 단계에서 polygon mesh의 각 정점마다&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;texture coordination&lt;/b&gt;가 설정되어야 한다. (s,t)&lt;/li&gt;
&lt;li&gt;2) 이후 rasterizer가 각 pixel에 따라&lt;span&gt;&amp;nbsp;&lt;/span&gt;interpolation&lt;span&gt;&amp;nbsp;&lt;/span&gt;해서 넘겨준다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;3) texture 좌표 (s,t)에 실제 texture의 해상도를 곱해서 (s', t')를 구한다.&lt;/li&gt;
&lt;li&gt;4) &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;(s', t') = c의 좌표를 활용해서 실제 texture(c)에서 rgb 값을 가져온다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;52&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dHQ3Zp/dJMcah4JBce/Imyick5rdqNRySh9bm5040/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dHQ3Zp/dJMcah4JBce/Imyick5rdqNRySh9bm5040/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dHQ3Zp/dJMcah4JBce/Imyick5rdqNRySh9bm5040/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdHQ3Zp%2FdJMcah4JBce%2FImyick5rdqNRySh9bm5040%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;393&quot; height=&quot;52&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;52&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;875&quot; data-origin-height=&quot;315&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhg6a1/dJMcahXXomZ/0fb9xklFonWQvZdoc5jwv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhg6a1/dJMcahXXomZ/0fb9xklFonWQvZdoc5jwv1/img.png&quot; data-alt=&quot;(a) 정점 별 texture 좌표 (b) 보간된 texture 좌표 (c) texture 해상도를 곱한 후&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhg6a1/dJMcahXXomZ/0fb9xklFonWQvZdoc5jwv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbhg6a1%2FdJMcahXXomZ%2F0fb9xklFonWQvZdoc5jwv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;716&quot; height=&quot;258&quot; data-origin-width=&quot;875&quot; data-origin-height=&quot;315&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;(a) 정점 별 texture 좌표 (b) 보간된 texture 좌표 (c) texture 해상도를 곱한 후&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;texture coordintate의 s와 t는 0과 1 사이로 nomalize 되어있어 다양한 텍스쳐에 적용될 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;753&quot; data-origin-height=&quot;317&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zyETE/dJMcach3peA/y8FjRAspDod7xxqbTtbxUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zyETE/dJMcach3peA/y8FjRAspDod7xxqbTtbxUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zyETE/dJMcach3peA/y8FjRAspDod7xxqbTtbxUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzyETE%2FdJMcach3peA%2Fy8FjRAspDod7xxqbTtbxUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;753&quot; height=&quot;317&quot; data-origin-width=&quot;753&quot; data-origin-height=&quot;317&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;-parameterization&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Surface Parameterization&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&amp;nbsp;&lt;span&gt; 복잡한 2D,3D 표면을 단순한 2D 좌표계 (s,t)로 표현하는 방법&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;867&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciNtIw/dJMcah4JBrS/iIoTPgAGiIJ9u3Pb6qQs10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciNtIw/dJMcah4JBrS/iIoTPgAGiIJ9u3Pb6qQs10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciNtIw/dJMcah4JBrS/iIoTPgAGiIJ9u3Pb6qQs10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciNtIw%2FdJMcah4JBrS%2FiIoTPgAGiIJ9u3Pb6qQs10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;616&quot; height=&quot;355&quot; data-origin-width=&quot;867&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;-parameterization&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Chart and Atlas&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇ &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #212529; letter-spacing: 0px;&quot;&gt;복잡한 polygon mesh는 patch(ex.머리, 몸 , 팔)들로 나누어 관리한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 patch들로 나누어 surface parameterization을 수행한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;chart&lt;/b&gt; : 각 patch들의 이미지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;atlas&lt;/b&gt; : 여러 개의 chart들이 texture에 합쳐진 것&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1379&quot; data-origin-height=&quot;485&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uv2lv/dJMcabjahOP/BQPV2ApTnwyrIwXM4fFgC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uv2lv/dJMcabjahOP/BQPV2ApTnwyrIwXM4fFgC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uv2lv/dJMcabjahOP/BQPV2ApTnwyrIwXM4fFgC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fuv2lv%2FdJMcabjahOP%2FBQPV2ApTnwyrIwXM4fFgC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;626&quot; height=&quot;220&quot; data-origin-width=&quot;1379&quot; data-origin-height=&quot;485&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;-parameterization&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Texture Wrapping&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt; &lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;range를 벗어난 (s,t)들을 처리해주는 방법&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Clamp-to-Edge (c) : 벗어날 경우 edge color로 렌더링한다.&lt;/li&gt;
&lt;li&gt;Repeat (d) : 반복으로 타일링하는 방식&lt;/li&gt;
&lt;li&gt;Mirrored-Repeat (e),(f) : 그냥 Repeat을 하면 경계가 부자연스러울 수 있기 때문에 mirrored 방식을 사용할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1153&quot; data-origin-height=&quot;307&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLlLwU/dJMcafy5He5/z2rjtlKdoRG2uIacEvklF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLlLwU/dJMcafy5He5/z2rjtlKdoRG2uIacEvklF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLlLwU/dJMcafy5He5/z2rjtlKdoRG2uIacEvklF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLlLwU%2FdJMcafy5He5%2Fz2rjtlKdoRG2uIacEvklF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;830&quot; height=&quot;221&quot; data-origin-width=&quot;1153&quot; data-origin-height=&quot;307&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;-texture-filtering&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Texture Filtering&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt; &lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;텍셀(texel) &amp;rarr;&amp;nbsp;&lt;/span&gt;화면 픽셀(pixel)&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;로 맵핑할 때, 해상도 차이를 보정하는 기술&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;텍스처 해상도와 화면 해상도가 다를 경우 생기는 왜곡/노이즈 문제가 발생할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Magnification&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;(확대) : &lt;/b&gt;pixel &amp;gt; texel&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;847&quot; data-origin-height=&quot;358&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCt4lT/dJMcaiWPqOt/qV7kSY8zaiw6XY5dz2ByeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCt4lT/dJMcaiWPqOt/qV7kSY8zaiw6XY5dz2ByeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCt4lT/dJMcaiWPqOt/qV7kSY8zaiw6XY5dz2ByeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCt4lT%2FdJMcaiWPqOt%2FqV7kSY8zaiw6XY5dz2ByeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;637&quot; height=&quot;269&quot; data-origin-width=&quot;847&quot; data-origin-height=&quot;358&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;b&gt;Minification (축소) : &lt;/b&gt;pixel &amp;lt; texel&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;771&quot; data-origin-height=&quot;342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YIgUg/dJMcacbhnJa/lxk3sLVkPpWkMdQ2j75mH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YIgUg/dJMcacbhnJa/lxk3sLVkPpWkMdQ2j75mH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YIgUg/dJMcacbhnJa/lxk3sLVkPpWkMdQ2j75mH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYIgUg%2FdJMcacbhnJa%2Flxk3sLVkPpWkMdQ2j75mH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;679&quot; height=&quot;301&quot; data-origin-width=&quot;771&quot; data-origin-height=&quot;342&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;-texture-filtering&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Filtering for Magnification&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span&gt; pixel이 texel보다 많은 경우 = 하나의 texel이 여러 pixel을 표현하게 된다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Option 1: Nearest point sampling&lt;/b&gt; &lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 픽셀에 가장 가까운 텍셀 하나의 값을 그대로 가져온다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;가장 간단하지만 같은 texture 값을 여러 번 가져오면서 block image 문제가 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AdTuc/dJMb99S9ppQ/mAt7DYtUGYaKAbwdGKvwdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AdTuc/dJMb99S9ppQ/mAt7DYtUGYaKAbwdGKvwdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AdTuc/dJMb99S9ppQ/mAt7DYtUGYaKAbwdGKvwdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAdTuc%2FdJMb99S9ppQ%2FmAt7DYtUGYaKAbwdGKvwdk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;547&quot; height=&quot;264&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;354&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Option 2 : Bilinear interpolation &lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;주변 4개의 텍셀 값을 이용해 보간(Interpolation)하여 중간색을 계산&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;수평/수직 방향으로 보간을 2번 해서 최종 c를 구한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;경계가 부드럽고 자연스러운 색 표현이 가능하지만, 연산량이 많은 단점이 있다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;323&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rB6fr/dJMcabwEZ2o/7PwL7dAOJ2zTXYWyZ5tlBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rB6fr/dJMcabwEZ2o/7PwL7dAOJ2zTXYWyZ5tlBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rB6fr/dJMcabwEZ2o/7PwL7dAOJ2zTXYWyZ5tlBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrB6fr%2FdJMcabwEZ2o%2F7PwL7dAOJ2zTXYWyZ5tlBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;595&quot; height=&quot;264&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;323&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Filtering for Minification&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;◇&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;pixel이 texel보다 적은 경우, texel의 숫자를 줄여야 한다! = 확대보다 심각한 문제&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Aliasing 문제&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어떤 texel을 샘플링하느냐에 따라 결과가 달라지는 aliasing 문제가 발생한다.&lt;/li&gt;
&lt;li&gt;표현하고자 하는 texture와 전혀 다르게 표현될 수 있는 심각한 문제다!&amp;nbsp;&lt;/li&gt;
&lt;li&gt;이를 위해 Mipmapping을 활용할 예정&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;776&quot; data-origin-height=&quot;222&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uMkHX/dJMcafeOfWJ/mMrjlvgNGzWTcNA4Zke0Nk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uMkHX/dJMcafeOfWJ/mMrjlvgNGzWTcNA4Zke0Nk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uMkHX/dJMcafeOfWJ/mMrjlvgNGzWTcNA4Zke0Nk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuMkHX%2FdJMcafeOfWJ%2FmMrjlvgNGzWTcNA4Zke0Nk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;776&quot; height=&quot;222&quot; data-origin-width=&quot;776&quot; data-origin-height=&quot;222&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 id=&quot;-minimapping&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Mipmapping&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;◇&lt;/span&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span&gt;&lt;span&gt; Aliasing 문제를 해결하기 위한 방법 - down sampling을 통해 minmap을 만들자!&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;목표 : texel의 수를 줄여서 pixel 수에 최대한 가까워지게 할 것&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;mipmap&lt;/b&gt; : &lt;span style=&quot;text-align: start;&quot;&gt;downsampling 한 level-&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;lambda;&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;nbsp;texture의 모음&lt;/span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;원래 텍스처의 해상도가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;2^&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;l&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;times;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;2^&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;l&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;인 경우, (l+1)개의 레벨로 구성된 피라미드(mipmap)를 구축한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;283&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bp3sAe/dJMcaaYO7FA/TvAuJKmy5Dqn6cHJAOD13k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bp3sAe/dJMcaaYO7FA/TvAuJKmy5Dqn6cHJAOD13k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bp3sAe/dJMcaaYO7FA/TvAuJKmy5Dqn6cHJAOD13k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbp3sAe%2FdJMcaaYO7FA%2FTvAuJKmy5Dqn6cHJAOD13k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;649&quot; height=&quot;245&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;283&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;text-align: start;&quot;&gt;이때 각 pixel에 맞는 level-&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;lambda;&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;nbsp;texture는 각 pixel이 차지하는 texel의 가로 or 세로 개수 m을 log_2(m)으로 표현하면 해당 level이 된다. 즉, &lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;lambda;&lt;/span&gt; = &lt;/b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;b&gt;log_2(m)&lt;/b&gt; 이다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;로그 계산이 딱 떨어지면 좋겠지만, 아래 처럼 m=3인 예시에서만 봐도 문제가 발생한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Option 1) 가장 가까운 level 고르기. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt;o&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;d&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&amp;lambda;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;Option 2) &lt;span style=&quot;color: #212529; text-align: start;&quot;&gt;level 1과 level2의 결과를 선형보간 (bilinear interpolation)&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1235&quot; data-origin-height=&quot;414&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pNNou/dJMcafsinLj/6DqTzynrnbGwjYFRhtfKdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pNNou/dJMcafsinLj/6DqTzynrnbGwjYFRhtfKdK/img.png&quot; data-alt=&quot;m = 3인 경우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pNNou/dJMcafsinLj/6DqTzynrnbGwjYFRhtfKdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpNNou%2FdJMcafsinLj%2F6DqTzynrnbGwjYFRhtfKdK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;773&quot; height=&quot;259&quot; data-origin-width=&quot;1235&quot; data-origin-height=&quot;414&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;m = 3인 경우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;b&gt;Reference&lt;/b&gt; KHU 강형엽 교수님 강의를 수강하며 정리한 내용입니다.&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;</description>
      <category>그래픽스</category>
      <category>DirectX</category>
      <category>그래픽스</category>
      <author>둠칫냐옹</author>
      <guid isPermaLink="true">https://cherry611.tistory.com/6</guid>
      <comments>https://cherry611.tistory.com/6#entry6comment</comments>
      <pubDate>Fri, 13 Mar 2026 21:33:24 +0900</pubDate>
    </item>
    <item>
      <title>[DirectX12] 2. Rasterizer</title>
      <link>https://cherry611.tistory.com/5</link>
      <description>&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;️-direct3d-12-graphics-pipeline&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Direct3D 12 graphics Pipeline&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이중에서 오늘 알아볼 단계는 Rasterizer다. Shader와 달리 하드웨어로 고정된 연산이 이루어지고, 따로 프로그래밍이 불가능하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;926&quot; data-origin-height=&quot;279&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHacRH/dJMcabDrxoC/7SjXHWwq0BrugPJ4axWQf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHacRH/dJMcabDrxoC/7SjXHWwq0BrugPJ4axWQf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHacRH/dJMcabDrxoC/7SjXHWwq0BrugPJ4axWQf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHacRH%2FdJMcabDrxoC%2F7SjXHWwq0BrugPJ4axWQf0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;926&quot; height=&quot;279&quot; data-origin-width=&quot;926&quot; data-origin-height=&quot;279&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;️-input-assembler-stage-ia&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Rasterizer&lt;/h2&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;◇&amp;nbsp;&lt;span&gt; &lt;/span&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;primitive를 2차원 이미지 요소(pixels)로 분할한다.&lt;/span&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앞선 vertex shader가 vectex들을 clip space로 옮긴 후에 rasterizer에게 넘겨준다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이후 raterizer는 크게 5가지의 역할을 수행한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt; &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;Primitive&lt;/span&gt; Clipping&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Perspective division&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Back-face culling&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Viewport transform&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Rasterization&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;요약하면 primitive를 pixel로 쪼개고, pixel 마다 필요한 data들을 넣어준다. 그리고 pixel shader가 연산량이 많기 때문에 이전에 불필요한 pixel들을 제거해주는 역할도 하게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;809&quot; data-origin-height=&quot;203&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEtabo/dJMcacI8dDM/zK5Zy7Q6I6W6XpPG3u3Sbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEtabo/dJMcacI8dDM/zK5Zy7Q6I6W6XpPG3u3Sbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEtabo/dJMcacI8dDM/zK5Zy7Q6I6W6XpPG3u3Sbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEtabo%2FdJMcacI8dDM%2FzK5Zy7Q6I6W6XpPG3u3Sbk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;498&quot; height=&quot;125&quot; data-origin-width=&quot;809&quot; data-origin-height=&quot;203&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-vertex-shader&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Primitive Clipping&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;안보이는(= clipping volume 밖) primitive 자르기&lt;/span&gt; &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;이전 포스팅에서 설명했듯이 사다리꼴 모양이 아닌 clipping volume을 기준으로 일어난다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;점(Point), 선(Line), 삼각형(Triangle)에 따라 겹쳤을 때의 처리 방식이 조금씩 다르다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;Point&lt;/b&gt; : 크기가 1 pixel보다 클 경우에 중점을 체크해서 버릴 지 결정&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;Line&lt;/b&gt; : 새로운 vertex 생성 후 자르기&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;Triangle&lt;/b&gt; : 경계선에 vertex를 생성하고 자르기&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dEwMg5/dJMcaflxhxt/NrT7K75hvnios6ZRNUV6X0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dEwMg5/dJMcaflxhxt/NrT7K75hvnios6ZRNUV6X0/img.png&quot; data-origin-width=&quot;461&quot; data-origin-height=&quot;287&quot; data-is-animation=&quot;false&quot; style=&quot;width: 53.8806%; margin-right: 10px;&quot; data-widthpercent=&quot;54.51&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dEwMg5/dJMcaflxhxt/NrT7K75hvnios6ZRNUV6X0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdEwMg5%2FdJMcaflxhxt%2FNrT7K75hvnios6ZRNUV6X0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;461&quot; height=&quot;287&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8M9Kn/dJMcabXJS05/zY7KjqzeSk7CQr8ASTvNf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8M9Kn/dJMcabXJS05/zY7KjqzeSk7CQr8ASTvNf0/img.png&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;435&quot; data-is-animation=&quot;false&quot; style=&quot;width: 44.9566%;&quot; data-widthpercent=&quot;45.49&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8M9Kn/dJMcabXJS05/zY7KjqzeSk7CQr8ASTvNf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8M9Kn%2FdJMcabXJS05%2FzY7KjqzeSk7CQr8ASTvNf0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;583&quot; height=&quot;435&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;️-vertex-shader&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;Perspective Division&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;w로 나누기를 통해 원근 구현&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;homogeneous(clip) 좌표를 Cartesian 좌표로 변환하는 과정에서 모든 좌표를 w로 나눈다 (이때 w = z)&amp;nbsp;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;아래 사진을 보면 연산 후에는 camera에 멀리 떨어져있던 선분이 더 짧아지게 된다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이 결과로 얻은 좌표를 &lt;b&gt;NDC(Normalized Device Coordinates)&lt;/b&gt;라고 부른다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;845&quot; data-origin-height=&quot;343&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lvqxS/dJMcabpVrbK/eNEADrSqhsRjRj26mPjcoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lvqxS/dJMcabpVrbK/eNEADrSqhsRjRj26mPjcoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lvqxS/dJMcabpVrbK/eNEADrSqhsRjRj26mPjcoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlvqxS%2FdJMcabpVrbK%2FeNEADrSqhsRjRj26mPjcoK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;608&quot; height=&quot;247&quot; data-origin-width=&quot;845&quot; data-origin-height=&quot;343&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;844&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dg57UP/dJMcacI8ePB/R1LQr8MK3XOgpuRDgWP9Vk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dg57UP/dJMcacI8ePB/R1LQr8MK3XOgpuRDgWP9Vk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dg57UP/dJMcacI8ePB/R1LQr8MK3XOgpuRDgWP9Vk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdg57UP%2FdJMcacI8ePB%2FR1LQr8MK3XOgpuRDgWP9Vk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;724&quot; height=&quot;262&quot; data-origin-width=&quot;844&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-vertex-shader&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;Viewport&amp;nbsp;&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;실제 window에서 내가 그림을 그릴 영역 &amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;screen space, viewport 모두 3차원 공간이다. (DirectX = 2&amp;times;2&amp;times;1/OpenGL = 2&amp;times;2&amp;times;2)&lt;/li&gt;
&lt;li&gt;아래처럼 여러가지 변수들로 Viewport를 정의한다.&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JjT66/dJMcabQXqCM/PhvaG6i5vxO081QNK8aQMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JjT66/dJMcabQXqCM/PhvaG6i5vxO081QNK8aQMK/img.png&quot; data-origin-width=&quot;627&quot; data-origin-height=&quot;451&quot; data-is-animation=&quot;false&quot; width=&quot;402&quot; height=&quot;289&quot; data-widthpercent=&quot;53.34&quot; style=&quot;width: 52.7173%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JjT66/dJMcabQXqCM/PhvaG6i5vxO081QNK8aQMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJjT66%2FdJMcabQXqCM%2FPhvaG6i5vxO081QNK8aQMK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;627&quot; height=&quot;451&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/moFh6/dJMcabDrA4Y/XsFwAQa3MHgIqy3zT2exUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/moFh6/dJMcabDrA4Y/XsFwAQa3MHgIqy3zT2exUK/img.png&quot; data-origin-width=&quot;793&quot; data-origin-height=&quot;652&quot; data-is-animation=&quot;false&quot; style=&quot;width: 46.1199%;&quot; data-widthpercent=&quot;46.66&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/moFh6/dJMcabDrA4Y/XsFwAQa3MHgIqy3zT2exUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmoFh6%2FdJMcabDrA4Y%2FXsFwAQa3MHgIqy3zT2exUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;793&quot; height=&quot;652&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-vertex-shader&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Viewport Transform&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span&gt;&lt;span&gt; NDC space에서 window space로 변환하는 과정&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Perspective Division을 해서 원근까지 표현했지만, 그 값들은 camera가 보는 시점에서 기준이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;이 단계에서 모니터의 비율에 맞게 NDC 좌표들을 변환하게 된다.&lt;/li&gt;
&lt;li&gt;scaling과 translation을 통해 계산된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;958&quot; data-origin-height=&quot;373&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWtFlY/dJMb996GZm1/uWBzwj2Im4PHmXv9CMitiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWtFlY/dJMb996GZm1/uWBzwj2Im4PHmXv9CMitiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWtFlY/dJMb996GZm1/uWBzwj2Im4PHmXv9CMitiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWtFlY%2FdJMb996GZm1%2FuWBzwj2Im4PHmXv9CMitiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;719&quot; height=&quot;280&quot; data-origin-width=&quot;958&quot; data-origin-height=&quot;373&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보통의 경우 vieport가 전체 모니터 스크린을 의미하기 때문에 아래 값을 대입해주면 깔끔한 matrix가 나온다.&lt;/li&gt;
&lt;li&gt;TopLeftx = 0, TopLeftY = 0, MinDepth = 0, MaxDepth = 1&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1613&quot; data-origin-height=&quot;419&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzZEin/dJMcafZ7dlz/In0RWApYK5AxOeoY8MXksK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzZEin/dJMcafZ7dlz/In0RWApYK5AxOeoY8MXksK/img.png&quot; data-alt=&quot;scaling과 translation을 적용한 최종 matrix&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzZEin/dJMcafZ7dlz/In0RWApYK5AxOeoY8MXksK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzZEin%2FdJMcafZ7dlz%2FIn0RWApYK5AxOeoY8MXksK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;737&quot; height=&quot;191&quot; data-origin-width=&quot;1613&quot; data-origin-height=&quot;419&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;scaling과 translation을 적용한 최종 matrix&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;️-vertex-shader&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Back-face Culling&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; Camera를 등지고 있는 면들을 없애버리자!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;camera 기준 3D 오브젝트의 뒷면에 해당하는 부분은 보이지 않기 때문에 Culling을 해준다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;GPU 비용이 비싼 R&lt;/span&gt;asterization, Pixel Shader 단계 전에 제거해준다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;삼각형의 앞면/뒷면 여부는 삼각형의 vectex 순서로 결정된다.&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;357&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4McSJ/dJMcafy5lPP/hD0KSgZpyGKIATET34QuL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4McSJ/dJMcafy5lPP/hD0KSgZpyGKIATET34QuL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4McSJ/dJMcafy5lPP/hD0KSgZpyGKIATET34QuL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4McSJ%2FdJMcafy5lPP%2FhD0KSgZpyGKIATET34QuL1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;497&quot; height=&quot;239&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;357&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;위 사진을 참고하면 Projection Transform 이후에는 모든 projection line이 z축과 평행하게 된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; 삼각형을 xy 평면에 투영한 뒤 간단한 행렬식을 계산하여 front/back을 판단한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt; &lt;span&gt;행렬식 &amp;lt; 0 = Front face = CW&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;행렬식 &amp;gt; 0&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; = Back face = CCW&lt;/span&gt; &lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;행렬식 = 0&lt;span&gt;&amp;nbsp; =&amp;nbsp; edge on&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1336&quot; data-origin-height=&quot;398&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgKXjW/dJMcajambae/Btl0Yn4jkQeH6ee3ziD5oK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgKXjW/dJMcajambae/Btl0Yn4jkQeH6ee3ziD5oK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgKXjW/dJMcajambae/Btl0Yn4jkQeH6ee3ziD5oK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgKXjW%2FdJMcajambae%2FBtl0Yn4jkQeH6ee3ziD5oK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1336&quot; height=&quot;398&quot; data-origin-width=&quot;1336&quot; data-origin-height=&quot;398&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 행렬식은 사실 두 edge vector의 외적이다. 즉, normal vector의 방향을 나타낸다고 볼 수 있다.&lt;/li&gt;
&lt;li&gt;따라서 행렬식의 부호에 따라 해당 삼각형이 바라보는 방향을 판단할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;361&quot; data-origin-height=&quot;123&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HgvVV/dJMcahwTUN2/YZGtQkZo3t9B7KxhqfLl70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HgvVV/dJMcahwTUN2/YZGtQkZo3t9B7KxhqfLl70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HgvVV/dJMcahwTUN2/YZGtQkZo3t9B7KxhqfLl70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHgvVV%2FdJMcahwTUN2%2FYZGtQkZo3t9B7KxhqfLl70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;361&quot; height=&quot;123&quot; data-origin-width=&quot;361&quot; data-origin-height=&quot;123&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; 만약 반투명 물체라면?&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반투명일 경우 back face를 날려버리면 안된다.&lt;/li&gt;
&lt;li&gt;DirectX에서는 &lt;span style=&quot;letter-spacing: 0px;&quot;&gt; Rasterizer 상태에서 cull mode를 설정해서 옵션을 변경할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;None : 아무것도 제거 X&lt;/li&gt;
&lt;li&gt;Front : front face 제거 = 내부 단면을 보이게 한다.&lt;/li&gt;
&lt;li&gt;Back : 일반적인 back face culling (DirectX 기본 설정)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;167&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccunKE/dJMcafZ7hs7/QE9nrkyXlB9nqPIzUmqec0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccunKE/dJMcafZ7hs7/QE9nrkyXlB9nqPIzUmqec0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccunKE/dJMcafZ7hs7/QE9nrkyXlB9nqPIzUmqec0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccunKE%2FdJMcafZ7hs7%2FQE9nrkyXlB9nqPIzUmqec0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;921&quot; height=&quot;167&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;167&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-vertex-shader&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Rasterization&amp;nbsp;&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;vector 정보를 pixel로 쪼개자!&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;크게 두가지 단계로 진행된다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;1) 그리드에서 어떤 픽셀들이 삼각형에 포함되어있는지 확인한다. (Edge Equation 활용)&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;2) 선택된 &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;픽셀&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;마다 &lt;/span&gt;color와 depth value 정보를 넣어준다.&amp;nbsp;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;이후 pixel shader가 나중에 최종 색 렌더링을 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-vertex-shader&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Edge Equation&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;픽셀이 삼각형 안에 포함되는 지를 판단할 때 사용&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;point가 왼쪽에 있는 경우 : negative number(음수)&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;point가 오른쪽에 있는 경우 : positive number(양수)&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;point가 line 위에 있는 경우 : zero number&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;226&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wqU1d/dJMcahjn1Bd/jgOdzWMnNWAbI9XDgLINHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wqU1d/dJMcahjn1Bd/jgOdzWMnNWAbI9XDgLINHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wqU1d/dJMcahjn1Bd/jgOdzWMnNWAbI9XDgLINHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwqU1d%2FdJMcahjn1Bd%2FjgOdzWMnNWAbI9XDgLINHK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;538&quot; height=&quot;178&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;226&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;point가 삼각형 내부에 있다면 모든 edge들에 right side에 위치한 것이다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;즉, 세 개의 edge모두 edge function이 양수를 return한 경우이다.&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;325&quot; data-origin-height=&quot;320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBhJRe/dJMb99S9jHy/2kiBvb3IkGZjgKnlmw0ue1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBhJRe/dJMb99S9jHy/2kiBvb3IkGZjgKnlmw0ue1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBhJRe/dJMb99S9jHy/2kiBvb3IkGZjgKnlmw0ue1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBhJRe%2FdJMb99S9jHy%2F2kiBvb3IkGZjgKnlmw0ue1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;325&quot; height=&quot;320&quot; data-origin-width=&quot;325&quot; data-origin-height=&quot;320&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;함수에 대해 좀 더 설명해보자면,, &lt;b&gt;E =&amp;nbsp; A x B = A와 B의 외적&lt;/b&gt;이다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;A = v1 - v0, B = p - v0 (아래 사진에서 파란색, 초록색으로 표시되어있다.)&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;외적을 했을 때 아래와 같은 성질 때문에, 결과의 부호로 p의 위치를 판단할 수 있다.&lt;/li&gt;
&lt;li&gt;0 &amp;lt; &amp;theta; &amp;lt; 180 : positive value&lt;/li&gt;
&lt;li&gt;180 &amp;lt; &amp;theta; &amp;lt; 360 : negative value&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;33&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQ3t2q/dJMcacvBE82/Tvlc2AtgjgzhEyKA7wDvw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQ3t2q/dJMcacvBE82/Tvlc2AtgjgzhEyKA7wDvw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQ3t2q/dJMcacvBE82/Tvlc2AtgjgzhEyKA7wDvw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQ3t2q%2FdJMcacvBE82%2FTvlc2AtgjgzhEyKA7wDvw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;731&quot; height=&quot;33&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;33&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biQhh0/dJMcabKeLQA/q5BxB8ptKep3GzQyuWlfJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biQhh0/dJMcabKeLQA/q5BxB8ptKep3GzQyuWlfJk/img.png&quot; data-origin-width=&quot;303&quot; data-origin-height=&quot;283&quot; data-is-animation=&quot;false&quot; style=&quot;width: 27.7169%; margin-right: 10px;&quot; data-widthpercent=&quot;28.04&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biQhh0/dJMcabKeLQA/q5BxB8ptKep3GzQyuWlfJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiQhh0%2FdJMcabKeLQA%2Fq5BxB8ptKep3GzQyuWlfJk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;303&quot; height=&quot;283&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MRtEB/dJMcadnGvIB/kHQAquHWkzQBEKMtWT0hEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MRtEB/dJMcadnGvIB/kHQAquHWkzQBEKMtWT0hEK/img.png&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;277&quot; data-is-animation=&quot;false&quot; style=&quot;width: 71.1203%;&quot; data-widthpercent=&quot;71.96&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MRtEB/dJMcadnGvIB/kHQAquHWkzQBEKMtWT0hEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMRtEB%2FdJMcadnGvIB%2FkHQAquHWkzQBEKMtWT0hEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;761&quot; height=&quot;277&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-attribute-interpolation&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Attribute Interpolation&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;fragment(pixel)에 속성값(color,depth,normal 등)을 보간해서 부여하자!&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;삼각형 내부 점은&lt;b&gt; 세 꼭짓점의 가중합&lt;/b&gt;으로 표현 가능&lt;/li&gt;
&lt;li&gt;C0, C1, C2 = 꼭짓점 색상&lt;/li&gt;
&lt;li&gt;p = 내부 픽셀&lt;/li&gt;
&lt;li&gt; 0,  1,  2 = 픽셀 p가 삼각형 내에서 얼마나 각 꼭짓점에 가까운지를 나타내는 가중치&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;271&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v5EAy/dJMcajamsCu/UhCbccTsUuwPrQFiE2NF91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v5EAy/dJMcajamsCu/UhCbccTsUuwPrQFiE2NF91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v5EAy/dJMcajamsCu/UhCbccTsUuwPrQFiE2NF91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv5EAy%2FdJMcajamsCu%2FUhCbccTsUuwPrQFiE2NF91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;271&quot; height=&quot;96&quot; data-origin-width=&quot;271&quot; data-origin-height=&quot;96&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;579&quot; data-origin-height=&quot;156&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dlpk1O/dJMcadVvPqs/6NHuUKRAFf35ftrKtetlnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dlpk1O/dJMcadVvPqs/6NHuUKRAFf35ftrKtetlnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dlpk1O/dJMcadVvPqs/6NHuUKRAFf35ftrKtetlnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdlpk1O%2FdJMcadVvPqs%2F6NHuUKRAFf35ftrKtetlnK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;579&quot; height=&quot;156&quot; data-origin-width=&quot;579&quot; data-origin-height=&quot;156&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 id=&quot;-barycentric-coordinate-중심-좌표계&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Barycentric coordinate (중심 좌표계)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt; &lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;픽셀 p에 대한  0,  1,  2를 구하는 수학적인 방법 (Edge Equation 활용)&lt;/span&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;T : 전체 삼각형 면적&lt;/li&gt;
&lt;li&gt;예를 들어) T0 = area(p,v1,v2) , &amp;lambda;0 = p가 v0쪽에 얼마나 가까운지를 의미한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;347&quot; data-origin-height=&quot;84&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QYuE0/dJMb99ZXd5e/xugKyYZDwa0Ti9DUaVwmQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QYuE0/dJMb99ZXd5e/xugKyYZDwa0Ti9DUaVwmQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QYuE0/dJMb99ZXd5e/xugKyYZDwa0Ti9DUaVwmQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQYuE0%2FdJMb99ZXd5e%2FxugKyYZDwa0Ti9DUaVwmQ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;347&quot; height=&quot;84&quot; data-origin-width=&quot;347&quot; data-origin-height=&quot;84&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이때 &lt;b&gt;T0 = 0.5 &amp;lowast; E(p, v1 , v2)&lt;/b&gt; 이다! 왜냐면 Edge Equation은 외적, 즉 평행사변형의 넓이를 의미하기 때문에 반띵만 해주면 된다. 0.5는 약분되어 사라지고, 아래와 같은 식이 완성된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;76&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baW61M/dJMcacbhkqm/gjBzlX8sGpAGu8L7l9Ibk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baW61M/dJMcacbhkqm/gjBzlX8sGpAGu8L7l9Ibk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baW61M/dJMcacbhkqm/gjBzlX8sGpAGu8L7l9Ibk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaW61M%2FdJMcacbhkqm%2FgjBzlX8sGpAGu8L7l9Ibk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;591&quot; height=&quot;54&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;76&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;365&quot; data-origin-height=&quot;348&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xfGkX/dJMb99MmFUN/wnVCPtKtlXg0RPZcZpq0a0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xfGkX/dJMb99MmFUN/wnVCPtKtlXg0RPZcZpq0a0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xfGkX/dJMb99MmFUN/wnVCPtKtlXg0RPZcZpq0a0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxfGkX%2FdJMb99MmFUN%2FwnVCPtKtlXg0RPZcZpq0a0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;261&quot; height=&quot;249&quot; data-origin-width=&quot;365&quot; data-origin-height=&quot;348&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;-barycentric-coordinate-중심-좌표계&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Rasterization Rule (Top-left Rule)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start; color: #000000;&quot;&gt; ◇&amp;nbsp;&lt;/span&gt; &lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;겹치는 픽셀이 있을 때 한쪽만 포함 시키자!&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;삼각형의 edge가 겹칠 때, 겹치는 픽셀이 두 번 계산되지 않도록 처리해야 한다.&lt;/li&gt;
&lt;li&gt;겹치는 edge를 기준으로&lt;b&gt; left edge와 top edge&lt;/b&gt;를 선택하게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N9a4T/dJMcabDrVG7/2Kfw8Kxy3dT5aBA0ZoSbT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N9a4T/dJMcabDrVG7/2Kfw8Kxy3dT5aBA0ZoSbT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N9a4T/dJMcabDrVG7/2Kfw8Kxy3dT5aBA0ZoSbT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN9a4T%2FdJMcabDrVG7%2F2Kfw8Kxy3dT5aBA0ZoSbT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;882&quot; height=&quot;274&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;KHU 강형엽 교수님 강의를 수강하며 정리한 내용입니다.&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;</description>
      <category>그래픽스</category>
      <category>DirectX</category>
      <category>그래픽스</category>
      <author>둠칫냐옹</author>
      <guid isPermaLink="true">https://cherry611.tistory.com/5</guid>
      <comments>https://cherry611.tistory.com/5#entry5comment</comments>
      <pubDate>Fri, 13 Mar 2026 20:20:36 +0900</pubDate>
    </item>
    <item>
      <title>[DirectX12] 1. Input Assembler, Vertex Shader</title>
      <link>https://cherry611.tistory.com/4</link>
      <description>&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;️-direct3d-12-graphics-pipeline&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Direct3D 12 graphics Pipeline&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래와 같은 구조의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;pipeline&lt;/b&gt;을 통해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;GPU는 rendering&lt;/b&gt;을 한다.&lt;/li&gt;
&lt;li&gt;전체 pipeline을 frame 마다 수행&lt;/li&gt;
&lt;li&gt;한 스테이지의 output은 다음 stage의 input이 된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Shader&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: programming 가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Input assembler, Tessellator, Rasterizer, Output merger&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: hard-wired(역할, 목적이 고정되어있는) stage이다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;고정된 함수&lt;/b&gt;만 사용하여 일을 수행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qgRQh/dJMcaa5AiPB/WVbbKHmy6dkWZZvZNwUr01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qgRQh/dJMcaa5AiPB/WVbbKHmy6dkWZZvZNwUr01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qgRQh/dJMcaa5AiPB/WVbbKHmy6dkWZZvZNwUr01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqgRQh%2FdJMcaa5AiPB%2FWVbbKHmy6dkWZZvZNwUr01%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;877&quot; height=&quot;294&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Shader에 대한 간단한 정보들..&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Shader&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그래밍 가능한 영역 (&lt;b&gt;programmable&lt;/b&gt;)&lt;/li&gt;
&lt;li&gt;floating point 연산이 배우 빠르다&lt;/li&gt;
&lt;li&gt;특정 program guideline(ex. input output structure)에 맞게 디자인 되어야 함.&lt;/li&gt;
&lt;li&gt;랜더링 파이프라인에는 5가지 종류가 있음 (Vertex, Hull, Domain, Geometry, Pixel)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;vertex shader&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 생략 불가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;pixel shader&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 생략 가능&lt;/li&gt;
&lt;li&gt;DirectX : HLSL / OpenGL : GLSL&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-input-assembler-stage-ia&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Input-Assembler Stage (IA)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;◇&amp;nbsp; &lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;vertex 정보들을 primitive(도형 - 삼각형, 선 등) 단위로 묶는 역할&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;user-specified buffer(vertex, index buffer)에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;vertex 정보를 읽는다.&lt;/li&gt;
&lt;li&gt;user들은 IASetPrimitiveTopolgy(data를 어떻게 자를 건지)를 활용하여 &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;primitive type를 정할 수 있다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-vertex-shader&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Vertex Shader&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;vertex의 최종 position 계산 + camera space에 표시될 vectex 선별&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Input : vertex specifications&lt;/li&gt;
&lt;li&gt;vertex specifications&lt;span&gt;&amp;nbsp;&lt;/span&gt;: input-assembler에서 vertex,index buffer를 통해 제공된다.&lt;/li&gt;
&lt;li&gt;각 vertex 마다 한번씩 동작한다.&lt;/li&gt;
&lt;li&gt;참고로 GPU는 for문이 안좋다 - dependancy 때문에 성능이 저하될 수 있기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xCjyZ/dJMcaio1k6R/MTWKVg5wUZM3V60YTw88zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xCjyZ/dJMcaio1k6R/MTWKVg5wUZM3V60YTw88zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xCjyZ/dJMcaio1k6R/MTWKVg5wUZM3V60YTw88zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxCjyZ%2FdJMcaio1k6R%2FMTWKVg5wUZM3V60YTw88zk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;816&quot; height=&quot;232&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;️-vertex-shader&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Vertex 좌표 변환 과정&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUHvVQ/dJMcac96Hjg/Hcqch5McpG1Ze1qRijKJl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUHvVQ/dJMcac96Hjg/Hcqch5McpG1Ze1qRijKJl1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUHvVQ/dJMcac96Hjg/Hcqch5McpG1Ze1qRijKJl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUHvVQ%2FdJMcac96Hjg%2FHcqch5McpG1Ze1qRijKJl1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;122&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;122&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 id=&quot;-object-space&quot; style=&quot;color: #212529; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Object space&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;오브젝트 내에서의 위치&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;오브젝트에 따라 axes가 바뀐다&lt;/li&gt;
&lt;li&gt;= model space&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;-object-space&quot; style=&quot;color: #212529; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;World space&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;3D World space에서의 위치&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;-object-space&quot; style=&quot;color: #212529; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Camera space&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Camera를 중점으로 한 상대좌표&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;world space coordinate가 target camera를 기준으로 다시 계산된다.&lt;/li&gt;
&lt;li&gt;= eye space&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;-object-space&quot; style=&quot;color: #212529; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Clip space&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;camera space에서 projection transform을 한 것&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-vertex-shader&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;World Transform&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;◇&amp;nbsp;&lt;span style=&quot;color: #0593d3;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;b&gt;scaling, roation, translation 과정을 통해 object space &amp;rarr; world space로 옮겨준다&lt;/b&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존의 object space에서는 각 model들끼리 독립적인 공간이다.&lt;/li&gt;
&lt;li&gt;반면 &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;world space에서는 모든 model들을 assemble = &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;하나의 coordinate system으로 합치는 것&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;World Matrix = &lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;span&gt;∣&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;]&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;rarr; 이게 S&amp;middot;R&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&amp;middot;&lt;/span&gt;T를 적용한 최종 matrix (DirectX기준 순서)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;L = combined linear transform&lt;/li&gt;
&lt;li&gt;t = combined translation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;675&quot; data-origin-height=&quot;306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bji1Is/dJMcadOH864/5lw8RHHuQD8tYR7nKttCIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bji1Is/dJMcadOH864/5lw8RHHuQD8tYR7nKttCIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bji1Is/dJMcadOH864/5lw8RHHuQD8tYR7nKttCIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbji1Is%2FdJMcadOH864%2F5lw8RHHuQD8tYR7nKttCIk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;675&quot; height=&quot;306&quot; data-origin-width=&quot;675&quot; data-origin-height=&quot;306&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;️-vertex-shader&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;World Transform - normal vector&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt; normal vector가 찌그러지는 것을 방지하기 위해 inverse transpose를 사용해야 한다. &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;non-uniform scaling :&lt;/b&gt;&amp;nbsp;객체의 각 축(x, y, z)을 서로 다른 비율로 확대/축소하는 스케일 변환&lt;/li&gt;
&lt;li&gt;non-uniform scaling이 있을 때, normal에도 그대로 L을 곱해주게 되면 아래 사진처럼 normal이 직교하지 않고 찌그러진다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YelKV/dJMcadgVVHj/wf9ogGhmFhb9uBzanWeQc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YelKV/dJMcadgVVHj/wf9ogGhmFhb9uBzanWeQc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YelKV/dJMcadgVVHj/wf9ogGhmFhb9uBzanWeQc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYelKV%2FdJMcadgVVHj%2Fwf9ogGhmFhb9uBzanWeQc0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1086&quot; height=&quot;306&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;306&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해결 방법 : normal에는 &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;L&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;minus;&lt;/span&gt;&lt;span&gt;T를 취해준다! 그러면 아래처럼 직교를 유지하게 된다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;(사실 &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;uniform scaling인 경우에는 그냥 L을 곱해도 가능하다.)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;285&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sTi02/dJMcafFPkxW/qfk7GKhiFf7Hvk7Llky770/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sTi02/dJMcafFPkxW/qfk7GKhiFf7Hvk7Llky770/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sTi02/dJMcafFPkxW/qfk7GKhiFf7Hvk7Llky770/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsTi02%2FdJMcafFPkxW%2Fqfk7GKhiFf7Hvk7Llky770%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;638&quot; height=&quot;239&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;285&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;-view-transform&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;View Transform&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt; &lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;월드 좌표(World Space)를 카메라 기준 좌표(View Space)로 변환하는 과정&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;'카메라를 움직이는 것이 아니라, 세상을 카메라 기준 좌표계로 바꾸는 것' 이라고 생각하면 편하다.&lt;/li&gt;
&lt;li&gt;아까 world matrix가 있었던 것 처럼 여기도 View Matrix를 계산해서 사용한다.&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;camera space : (u, v, n, EYE)&amp;nbsp;&lt;/b&gt; - 이때 EYE는 카메라의 위치이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;world space : (e1, e2, e3, O)&lt;/span&gt; &lt;b&gt;&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Step 1) 카메라 위치(&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;EYE)를 world space의 원점으로 translation&lt;/span&gt; &lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;649&quot; data-start=&quot;631&quot;&gt;즉, world space 전체를 &amp;minus;EYE 만큼 이동한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1388&quot; data-origin-height=&quot;469&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bal3RS/dJMcabwDIJ5/QBm2qx3XrKQUJTL4TKWKT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bal3RS/dJMcabwDIJ5/QBm2qx3XrKQUJTL4TKWKT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bal3RS/dJMcabwDIJ5/QBm2qx3XrKQUJTL4TKWKT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbal3RS%2FdJMcabwDIJ5%2FQBm2qx3XrKQUJTL4TKWKT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1388&quot; height=&quot;469&quot; data-origin-width=&quot;1388&quot; data-origin-height=&quot;469&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Step 2) 좌표축 정렬 (Rotation / Basis Change) &lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이제 카메라의 좌표축 (u, v, n)을 월드 좌표축 (e1, e2, e3)와 맞춰야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1283&quot; data-origin-height=&quot;628&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/T6wMd/dJMcac96K3r/4RDBfAL3aYDF5rT6YmVDF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/T6wMd/dJMcac96K3r/4RDBfAL3aYDF5rT6YmVDF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/T6wMd/dJMcac96K3r/4RDBfAL3aYDF5rT6YmVDF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FT6wMd%2FdJMcac96K3r%2F4RDBfAL3aYDF5rT6YmVDF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1283&quot; height=&quot;628&quot; data-origin-width=&quot;1283&quot; data-origin-height=&quot;628&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;-view-transform&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;View Transform - View Matrix&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 위와 같은 과정을 거쳐서 최종 View Matrix는 아래와 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;473&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cYT75D/dJMcacbf6t5/Vi2HRVoJ4uk5wWWMuCsCu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cYT75D/dJMcacbf6t5/Vi2HRVoJ4uk5wWWMuCsCu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cYT75D/dJMcacbf6t5/Vi2HRVoJ4uk5wWWMuCsCu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcYT75D%2FdJMcacbf6t5%2FVi2HRVoJ4uk5wWWMuCsCu1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;506&quot; height=&quot;265&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;473&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;-view-transform&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;View Frustum (절두체)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0593d3; text-align: start;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;우리가 볼 수 있는 영역을 의미하며 view volume이라고도 부른다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;field of view(fov)가 제한되어있기 때문에 카메라는 모든 물체를 볼 수 없다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;4가지 변수들 : fovy(시야각), aspect(넓이-높이의 비율), n(가장 가까운 지점), f(가장 먼 지점)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;변수들을 활용해서 아래 사진 처럼 사다리꼴 또는 공간을 정의할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;culling이나 clipping을 통해서 보여지지 않는 부분은 버려지게 된다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;297&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FdE3b/dJMcafMCiCl/tyroCIDVfWTiGwoyMGoxY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FdE3b/dJMcafMCiCl/tyroCIDVfWTiGwoyMGoxY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FdE3b/dJMcafMCiCl/tyroCIDVfWTiGwoyMGoxY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFdE3b%2FdJMcafMCiCl%2FtyroCIDVfWTiGwoyMGoxY1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;850&quot; height=&quot;297&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;297&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;-view-frustum-culling&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;View frustum culling&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;text-align: start; color: #0593d3;&quot;&gt;시야 밖의 object를 없애버리자&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;out of frustum인 물체들은 &lt;b&gt;GPU pipeline에 들어가기전에 버려진다(discard).&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;discard의 의미는 아예 memory에 올리지 않거나 음수로 만들어 다음 stage에서 제외시키는 방법이 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;-clipping&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Clipping (by the rasterization stage)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;◇&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: start; color: #0593d3;&quot;&gt; 시야에 걸리는 일부분만 가져오자&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;레스터라이저가 하는 일이기 때문에 자세한 것은 이후에 설명할 예정,,&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3ToO4/dJMcaaLhyDF/O0uRm08kUlQwGMdPaMjNbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3ToO4/dJMcaaLhyDF/O0uRm08kUlQwGMdPaMjNbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3ToO4/dJMcaaLhyDF/O0uRm08kUlQwGMdPaMjNbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3ToO4%2FdJMcaaLhyDF%2FO0uRm08kUlQwGMdPaMjNbK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1003&quot; height=&quot;252&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;252&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id=&quot;️-projection-transform&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Projection Transform&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;text-align: start; color: #0593d3;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;◇&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;text-align: start; color: #0593d3;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;b&gt;&lt;span style=&quot;text-align: start; color: #0593d3;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt; view frustum &amp;rarr; 정규화된 cube 로 변환 &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;view frustum을 원점을 중심으로 하는 axis-aligned cube에 다시 위치시킨다.&lt;/li&gt;
&lt;li&gt;위에 clipping을 언급했는데, 피라미드 형태에서 하는 것이 아니라 이 단계에서 큐브 형태로 만든 후에 clipping을 하게된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;피라미드에서 clipping을 하게 되면 훨씬 복잡해지 때문..&lt;/li&gt;
&lt;li&gt;homogeneous coordinate의 &lt;b&gt;w에 깊이 정보를 저장&lt;/b&gt;하여 이후 수행되는 perspective divide를 통해 &lt;b&gt;원근 투영 효과&lt;/b&gt;가 생성된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;725&quot; data-origin-height=&quot;242&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WVrIp/dJMcahwS5aR/ck6P5qClJdiSp0sjUvXuz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WVrIp/dJMcahwS5aR/ck6P5qClJdiSp0sjUvXuz0/img.png&quot; data-alt=&quot;View Frustum(좌)은 Projection Transform을 통해 Clip Space(우)로 위치된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WVrIp/dJMcahwS5aR/ck6P5qClJdiSp0sjUvXuz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWVrIp%2FdJMcahwS5aR%2Fck6P5qClJdiSp0sjUvXuz0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;614&quot; height=&quot;205&quot; data-origin-width=&quot;725&quot; data-origin-height=&quot;242&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;View Frustum(좌)은 Projection Transform을 통해 Clip Space(우)로 위치된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DirectX (LHS) vs OpenGL (RHS)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1222&quot; data-origin-height=&quot;320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjmHqO/dJMcacPRU5E/Lk208D9G14QMoE5v2orRTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjmHqO/dJMcacPRU5E/Lk208D9G14QMoE5v2orRTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjmHqO/dJMcacPRU5E/Lk208D9G14QMoE5v2orRTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjmHqO%2FdJMcacPRU5E%2FLk208D9G14QMoE5v2orRTK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;814&quot; height=&quot;213&quot; data-origin-width=&quot;1222&quot; data-origin-height=&quot;320&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Projection Transform M&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;atrix&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;text-align: start; color: #0593d3;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;◇&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;text-align: start; color: #0593d3;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;b&gt;&lt;span style=&quot;text-align: start; color: #0593d3;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt; &lt;b&gt;DirectX 기준 최종 Matrix&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아까 위에서 설명했던 view frustum의 변수들로 구성되어있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;마지막 행이 왜 (0 0 1 0) 일까? &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&amp;rarr;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt; 이건 레스터라이저에서 perspective divide을 할 때 필요하다. 다음 정리에서 설명될 예정&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OJKS6/dJMcafFPtte/tOUhDKdb8nnkOg2wbnSkc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OJKS6/dJMcafFPtte/tOUhDKdb8nnkOg2wbnSkc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OJKS6/dJMcafFPtte/tOUhDKdb8nnkOg2wbnSkc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOJKS6%2FdJMcafFPtte%2FtOUhDKdb8nnkOg2wbnSkc0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;534&quot; height=&quot;179&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;172&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;text-align: start; color: #0593d3;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;◇&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;text-align: start; color: #0593d3;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;b&gt;&lt;span style=&quot;text-align: start; color: #0593d3;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;OpenGL 기준 최종 Matrix&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요건 참고용으로 가져왔는데, 마지막 행 -1이 들어가는 것을 볼 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;173&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/plkbS/dJMcaaExjws/cxKNfXXaaUZb9rKZoudkIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/plkbS/dJMcaaExjws/cxKNfXXaaUZb9rKZoudkIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/plkbS/dJMcaaExjws/cxKNfXXaaUZb9rKZoudkIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FplkbS%2FdJMcaaExjws%2FcxKNfXXaaUZb9rKZoudkIk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;514&quot; height=&quot;173&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;173&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;rasterizer는 shader와 달리 사용자가 수정할 수 없다.&lt;/li&gt;
&lt;li&gt;rasterizer는 clip space를 LHS로 취급하기 때문에 shader에서 미리 RHS&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&amp;rarr;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;LHS로 변환해줘야 한다.&lt;/li&gt;
&lt;li&gt;이를 위해 z축에 대해 -1을 곱해주게 되는데, 이 과정을 하지 않으면 아래 사진 처럼 뒤집어진 그림이 나오게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;564&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2DYiW/dJMcabKdIma/7oxs2kE67VoKQk0k5lo9Zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2DYiW/dJMcabKdIma/7oxs2kE67VoKQk0k5lo9Zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2DYiW/dJMcabKdIma/7oxs2kE67VoKQk0k5lo9Zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2DYiW%2FdJMcabKdIma%2F7oxs2kE67VoKQk0k5lo9Zk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;589&quot; height=&quot;379&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;KHU 강형엽 교수님 강의를 수강하며 정리한 내용입니다.&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;</description>
      <category>그래픽스</category>
      <category>DirectX</category>
      <category>그래픽스</category>
      <author>둠칫냐옹</author>
      <guid isPermaLink="true">https://cherry611.tistory.com/4</guid>
      <comments>https://cherry611.tistory.com/4#entry4comment</comments>
      <pubDate>Thu, 12 Mar 2026 22:10:07 +0900</pubDate>
    </item>
  </channel>
</rss>