Tutorial 2: Creating a Framework and Window

Tutorial 2: Creating a Framework and Window Before starting to code with DirectX 11 I recommend building a simple code framework. This framework will handle the basic windows functionality and provide an easy way to expand the code in an organized and read

www.rastertek.com

DirectX11의 공부 목적으로 위 링크의 튜토리얼을 보고 제 생각을 포함하여 정리하였습니다.


들어가며

 

win api를 자세히 보기보다 렌더링 부분을 먼저 공부 하고 싶기 때문에 지금 시간인 세팅 부분은 간단하게 넘어가려한다.

 

● 프로젝트 생성시 'win32 console applicaiton' 는 'windows desktop application' 으로 변경 되었다.

 

프레임 워크는 네 클래스로 시작된다.

1. 앱의 진입점인 WinMain 함수

2. WinMain의 기능을 캡슐화한 SystemClass

3. 사용자의 키보드 입력을 처리하기 위한 InputClass

4. DirectX의 그래픽 코드를 처리하기 위한 ApplicationClass

이 네 클래스를 자세히 살펴보겠습니다.

 

main.cpp

 

내가 사용하는 vs에서는 WinMain이  APIENTRY wWinMain으로 생성되었었다.

기본 WinMain과 큰 차이는 없지만 튜토리얼과 같이 WinMain함수로 변경하여 간단하게 만들고 메인작업들을 System class를 이용해 캡슐화하여 사용한다.

WinMain vs wWinMain

#include "systemclass.h"

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,	_In_ LPSTR lpCmdLine, 	_In_ int nShowCmd
)
{
	SystemClass* System;
	bool result;

	// 새로운 개체 생성.
	System = new SystemClass;

	// System 개체 초기화 후 실행.
	result = System->Initialize();
	if (result)
	{
		System->Run();
	}

	// System 개체 종료 후 메모리 해제
	System->Shutdown();
	delete System;
	System = 0;

	return 0;
}

 

튜토리얼의 코드대로 작성하게 되면 이런 경고가 나오는데, 이는 주석 코드(SAL)이 없기 때문에 발생한 경고다.

WinMain의 함수 정의에 SAL이 사용되었기 때문에 정의에서도 사용해주어야 한다.

 

System.h

 

#ifndef _SYSTEMCLASS_H_
#define _SYSTEMCLASS_H_

// 암호화, DDE, RPC, 셸 및 Windows 소켓과 같은 API를 제외 하여 빌드 프로세스 속도를 향상
#define WIN32_LEAN_AND_MEAN

// win32 함수를 사용하려는 목적인 windows.h 포함
#include <windows.h>
#include "inputclass.h"
#include "applicationclass.h"

class SystemClass
{
public:
	SystemClass();
	SystemClass(const SystemClass&);
	// 소멸자가 호출되지 않을 수도 있는 경우가 있기 때문에 소멸 작업은 Shutdown함수에 구현.
	// 그래서 기본 소멸자에 아무것도 없으므로 default 사용
	~SystemClass() = default;

	bool Initialize();
	void Shutdown();
	void Run();

	// Windows 시스템 메시지를 처리하기 위한 핸들
	LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);

private:
	// 실질적으로 매 프레임마다 앱의 처리를 담당
	bool Frame();
	// 앱의 초기화 작업
	void InitializeWindows(int&, int&);
	// 앱의 종료시 작업
	void ShutdownWindows();

private:

	LPCWSTR m_applicationName;
	HINSTANCE m_hinstance;
	HWND m_hwnd;

	// 우리가 만든 클래스
	InputClass* m_Input;
	ApplicationClass* m_Application;
};


static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static SystemClass* ApplicationHandle = 0;

#endif

WinMain의 작업들을 캡슐화하기 위한 클래스.

처음의 WIN32_LEAN_AND_MEAN은 빌드시 암호화, DDE, RPC, 셸 및 Windows 소켓과 같은 API를 제외 하여 빌드 프로세스 속도를 향상시켜준다.

 

System.cpp

 

1. 생성자

SystemClass::SystemClass()
{
	// 우리가 만든 클래스의 개체
	m_Input = nullptr;
	m_Application = nullptr;
}

생성자는 개체의 초기화만 들어있다. 응용 프로그램에서는 개체가 null이 아니면 해당 개체를 정리하려고 시도한다고 하는데 이는 쓰레기 값이 들어지 않게 하려는 의도인거 같다.

또한 응용 프로그램에서는 모든 포인터와 변수를 null로 초기화 하지 않으면 일부 릴리즈 빌드가 실패할수 있다고 한다.

나는 보다 명확한 nullptr으로 초기화 하였다.

 

2. 소멸자

빈 소멸자이기에 코드는 없다. 소멸자가 호출되지 않을 수도 있는 경우가 있기 때문에 소멸시 작업은 모두 Shoutdown함수에 구현되었다.

 

3. Initialize

bool SystemClass::Initialize()
{
	int screenWidth, screenHeight;
	bool result;

	screenWidth = 0;
	screenHeight = 0;

	// windows api 초기화.
	InitializeWindows(screenWidth, screenHeight);

	// m_Input은 사용자의 키보드 입력을 처리하는데 사용된다.
	m_Input = new InputClass;
	m_Input->Initialize();

	// m_Application은 모든 그래픽 렌더링을 처리한다.
	m_Application = new ApplicationClass;
	result = m_Application->Initialize(screenWidth, screenHeight, m_hwnd);
	if (!result)
	{
		return false;
	}
	return true;
}

평범한 초기화 함수.

 

4. Shoutdown

void SystemClass::Shutdown()
{
	// 클래스 개체들을 메모리 해제.
	{
		if (m_Application)
		{
			m_Application->Shutdown();
			delete m_Application;
			m_Application = 0;
		}

		if (m_Input)
		{
			delete m_Input;
			m_Input = 0;
		}
	}

	// 창 종료
	ShutdownWindows();

	return;
}

모든 개체를 메모리 해제 후 창을 종료한다.

 

5. Run

함수 Run의 수도 코드와 실제 코드이다.

while ( 실행중 )
    1. Windows 시스템 메시지 확인 
    2. 시스템 메시지 처리 
    3. 응용 프로그램 루프 
    4. 프레임 처리 (처리 중에 사용자가 종료하기를 원하는지 확인)
void SystemClass::Run()
{
	MSG msg;
	bool done, result;


	// 메세지 구조 초기화
	ZeroMemory(&msg, sizeof(MSG));

	// 창이나 사용자로부터 종료 메세지가 나타날 때까지 반복한다.
	// done이 true면 앱의 종료라는 뜻이다.
	done = false;
	while (!done)
	{
		// 윈도우 메세지의 처리
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		// Window가 앱을 종료하라는 신호를 보내면 종료한다.
		if (msg.message == WM_QUIT)
		{
			done = true;
		}
		else
		{
			// 종료 신호가 아니라면 프레임 처리를 수행한다.
			result = Frame();
			if (!result)
			{
				done = true;
			}
		}

	}

	return;
}

Run 함수는 애플리케이션이 반복되고 모든 애플리케이션의 처리를 수행하는 곳이다. 실질적으로 애플리케이션의 처리는 Frame함수에서 하게 된다.

 

6. Frame

프레임마다 그래픽 작업을 수행하는 함수

 

 

 

bool SystemClass::Frame()
{
	bool result;

	// 사용자가 ESC를 누르고 앱을 종료하려고하는지 확인.
	if (m_Input->IsKeyDown(VK_ESCAPE))
	{
		return false;
	}

	// Application 개체를 이용하여 프레임의 그래픽 작업을 수행한다.
	result = m_Application->Frame();
	if (!result)
	{
		return false;
	}

	return true;
}

 

7. MessageHandler

MessageHandler 함수는 Windows 시스템 메세지를 가져와 전달하는 함수

LRESULT CALLBACK SystemClass::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
	switch (umsg)
	{
		// 키보드에서의 키가 눌렸는지 확인.
		case WM_KEYDOWN:
		{
			// 키를 누르면 해당 상태를 저장할 수 있도록 Input개체에 전송한다.
			m_Input->KeyDown((unsigned int)wparam);
			return 0;
		}

		// 키보드에서 키가 해제되었는지 확인.
		case WM_KEYUP:
		{
			m_Input->KeyUp((unsigned int)wparam);
			return 0;
		}

		// 앱에서 사용하지 않는 다른 메세지는 기본 WinAPI메세지 핸들러로 전송한다.
		default:
		{
			return DefWindowProc(hwnd, umsg, wparam, lparam);
		}
	}
}

여기서 우리는 관심 있는 특정 메세지만을 Input 개체에 전송한다. 우리가 필요없는 다른 메세지는 기본 Windows 메세지 핸들러로 전송한다.

 

8. InitializeWindows

렌더링에 사용할 창을 빌드하기 위한 함수

void SystemClass::InitializeWindows(int& screenWidth, int& screenHeight)
{
	WNDCLASSEX wc;
	DEVMODE dmScreenSettings;
	int posX, posY;


	// System클래스의 포인터를 가져온다.
	ApplicationHandle = this;

	// HInstance는 앱(프로그램)의 핸들을 말한다. 운영체제가 제공해주는 핸들을 GetModuleHandle을 통해 가져온다.
	m_hinstance = GetModuleHandle(NULL);

	// 앱의 이름을 작성.
	m_applicationName = L"Engine";

	// 윈도우 클래스의 변수들을 작성한다. (앱의 창 크기, 앱의 핸들, ...)
	wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = m_hinstance;
	wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
	wc.hIconSm = wc.hIcon;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = m_applicationName;
	wc.cbSize = sizeof(WNDCLASSEX);

	// 위에서 작성한 설정 값을 등록한다.
	RegisterClassEx(&wc);

	// 사용자의 모니터 해상도를 가져온다.
	screenWidth = GetSystemMetrics(SM_CXSCREEN);
	screenHeight = GetSystemMetrics(SM_CYSCREEN);

	// 전체 화면으로 실행하는지, 창 모드로 실행하는지에 따라 화면 설정을 설정합니다. 
	if (FULL_SCREEN)
	{
		// 전체 화면인 경우 화면을 사용자 데스크톱의 최대 크기 및 32비트로 설정합니다. 
		memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
		dmScreenSettings.dmSize = sizeof(dmScreenSettings);
		dmScreenSettings.dmPelsWidth = (unsigned long)screenWidth;
		dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight;
		dmScreenSettings.dmBitsPerPel = 32;
		dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

		// 디스플레이 세팅을 전체 화면으로 변경한다.
		ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);

		// 창의 위치를 왼쪽 상단으로 설정한다.
		posX = posY = 0;
	}
	else
	{
		// 창 모드인 경우 해상도를 800x600으로 설정합니다. 
		screenWidth = 800;
		screenHeight = 600;

		// 창을 화면 중앙에 배치하게끔 왼쪽 상단 position을 구하여 설정한다.
		posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth) / 2;
		posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2;
	}

	// 화면 설정으로 창을 만들고 이에 대한 핸들을 가져온다.
	m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName,
		WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP,
		posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL);

	// 창을 띄워 메인 포커스로 설정한다.
	ShowWindow(m_hwnd, SW_SHOW);
	SetForegroundWindow(m_hwnd);
	SetFocus(m_hwnd);

	// 마우스 커서를 숨긴다.
	ShowCursor(false);

	return;
}

. 주석으로 어떤 역할인지 알기 쉽다. FULL_SCREEN 전역 변수는 Application class에 있는데 이는 나중에 이해가 될 것이라 한다.

 

9. ShoutdownWindows

화면 설정을 다시 정상으로 되돌리고 창과 관련된 핸들을 해제하는 함수.

void SystemClass::ShutdownWindows()
{
	// Show the mouse cursor.
	ShowCursor(true);

	// 전체 화면을 종료하는 경우 디스플레이 설정을 수정한다.
	if (FULL_SCREEN)
	{
		ChangeDisplaySettings(NULL, 0);
	}

	// Remove the window.
	DestroyWindow(m_hwnd);
	m_hwnd = NULL;

	// Remove the application instance.
	UnregisterClass(m_applicationName, m_hinstance);
	m_hinstance = NULL;

	// Release the pointer to this class.
	ApplicationHandle = NULL;

	return;
}

 

 

10. WndProc

Windows가 메세지를 보내는 함수

LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
	switch (umessage)
	{
		// Check if the window is being destroyed.
		case WM_DESTROY:
		{
			PostQuitMessage(0);
			return 0;
		}

		// Check if the window is being closed.
		case WM_CLOSE:
		{
			PostQuitMessage(0);
			return 0;
		}

		// 다른 메세지는 System 클래스의 MessageHandler 함수로 전달된다.
		// 이곳으로 메세지가 들어오는 이유는 Initialize 함수에서 wc.lpfnWndProc = WndProc으로 지정했기 때문.
		default:
		{
			return ApplicationHandle->MessageHandler(hwnd, umessage, wparam, lparam);
		}
	}
}

 

InputClass.h

 

사용자의 키보드 입력을 처리하는 클래스.

이러한 입력처리는 DirectInput이 더 우수하지만 튜토리얼을 단순하게 유지하기 위해 사용.

아까 보았던 SystemClass::MessageHandler 함수에서 이 InputClass 개체로 메세지를 전달해준다.

#pragma once
#ifndef _INPUTCLASS_H_
#define _INPUTCLASS_H_

class InputClass
{
public:
	// 빈 생성자, 빈 소멸자이기에 default를 사용했다.
	InputClass() = default;
	InputClass(const InputClass&);
	~InputClass() = default;

	void Initialize();

	void KeyDown(unsigned int);
	void KeyUp(unsigned int);

	bool IsKeyDown(unsigned int);

private:
	bool m_keys[256];
};

#endif

 

키의 저장은 m_keys라는 배열에 저장하게 되고 키에 대한 쿼리를 받으면 그 키에 대한 index를 찾아 호출 기능에 알려주는 형식이다.

 

InputClass.cpp

 

간단한 cpp 파일

#include "InputClass.h"

InputClass::InputClass(const InputClass& other)
{
}

void InputClass::Initialize()
{
	// 키의 값을 누르지 않은 뜻인 false로 모두 초기화
	for (int i = 0; i < 256; i++)
	{
		m_keys[i] = false;
	}

	return;
}


void InputClass::KeyDown(unsigned int input)
{
	// If a key is pressed then save that state in the key array.
	m_keys[input] = true;
	return;
}


void InputClass::KeyUp(unsigned int input)
{
	// If a key is released then clear that state in the key array.
	m_keys[input] = false;
	return;
}


bool InputClass::IsKeyDown(unsigned int key)
{
	// 키가 눌렸는지, 눌리지 않았는지의 상태를 반환한다.
	return m_keys[key];
}

 

ApplicationClass.h

 

앱의 모든 그래픽 기능은 이 클래스에 캡슐화되어 사용된다. 또한 해상도 변경 등 모든 그래픽 관련 전역 설정에 대해 이 파일의 헤더를 사용할 것이다.

향후 튜토리얼의 모든 그래픽 개체를 포함하게 된다.

#pragma once
#ifndef _APPLICATIONCLASS_H_
#define _APPLICATIONCLASS_H_

#include <windows.h>

const bool FULL_SCREEN = false;
const bool VSYNC_ENABLED = true;
const float SCREEN_DEPTH = 1000.0f;
const float SCREEN_NEAR = 0.3f;

class ApplicationClass
{
public:
	ApplicationClass();
	ApplicationClass(const ApplicationClass&);
	~ApplicationClass();

	bool Initialize(int, int, HWND);
	void Shutdown();
	bool Frame();

private:
	bool Render();

private:
};
#endif

 

Application.cpp

 

지금 시간에서는 별다를게 없어 모두 비워져 있다!

 


요약

 

기본적인 프레임워크를 구성하고 앱의 창을 띄웠다.

주석만 따라간다면 크게 어려운것은 없었다.

'DirectX 11 > DX11 Tutorial' 카테고리의 다른 글

[05] 텍스쳐링  (0) 2024.05.23
[04] 버퍼, 셰이더, HLSL  (0) 2024.05.21
[03] DirectX 11 초기화 (3)  (0) 2024.05.20
[02] DirectX 11 초기화 (2)  (0) 2024.05.20
[01] DirectX 11 초기화 (1)  (0) 2024.05.19

결과물

정규화 된 타일맵에서의 위치를 구한다.

 


코드

Terrain.cpp

현재 위치의 높이를 float으로 반환

GetHeightDemo.cpp

 


추가

이 방법의 단점

더보기

각타일이 크기가 정규화 되어야 사용가능하다.

비정규화된 맵에서 높이를 가져오려면 Trace를 사용해야한다.

'DirectX 11 > 코드 분석' 카테고리의 다른 글

Normal vector / Shadow  (0) 2022.02.09
Height map  (0) 2022.02.08
Texture Sampler  (0) 2022.02.08
Texture  (0) 2022.02.08
Grid / Camera  (0) 2022.02.08

결과물

 

각 타일의 수직벡터 Line debuging


코드

Terrian.fx

 

Terrian.cpp

[ 여기서 구하고자 하는 Normal값은 각 타일 삼각형의 노멀값이다 // 음영을 계산하기 위해 구함 ]

'DirectX 11 > 코드 분석' 카테고리의 다른 글

Get Height  (0) 2022.02.09
Height map  (0) 2022.02.08
Texture Sampler  (0) 2022.02.08
Texture  (0) 2022.02.08
Grid / Camera  (0) 2022.02.08

동차 표기법은 무엇인가 많이 검색하고 찾아봤지만 나에게는 다 두루뭉실하게 들렸다ㅠ

 

내가 정의한 동차 표기법은

"차원을 하나 더 추가하는 표기법" 이다.

하나 더 추가하는 이유는 그 차원의 값을 통하여 여러가지 계산을 쉽게 할 수 있기 때문이다.

실제로 차원이 더 늘어나는게 아님


예를들어 3차원에서 3x3행렬으로도 회전, 스케일링 등의 선형변환을 나타낼 수 있다.

하지만 이동은 3x3행렬로 표현할 수 없다

 

그래서 한차원을 추가해서 4x4행렬로 만든다면 행렬곱을 통하여 이동 및 여러 변환을 쉽게 시킬수가 있다.

한차원을 추가 : 3차원 (x, y, z) => 4차원 (x, y, z, w)


또 다른 기능이 있는데 방향벡터와 위치벡터를 구분해줄수있다.

벡터에는 위치를 나타내는 위치벡터와 방향을 나타내는 방향벡터가 있다.

 

근데 방향벡터에 이동이 필요한가?

한다면 정규화된 값이 방향벡터이라 의미가 없다고 생각한다.

 

그렇기 때문에 방향 벡터는 w의 값을 0, 위치벡터는 w의 값을 1로 사용하여

두 벡터를 구분할 수 있다.

 

이는 VertexShader에서 확인이 가능한데

vertex shader의 매개변수 구조체

다들 Vs를 작성해봤었다면 정점의 위치는 float4, 방향벡터는 float3로 정의하여 값을 옮겼을 것이다.

위치데이터가 float4인 이유는 바로 저 동차표기로 이동을 계산해야하기 때문이다.

그래서 float4로 정의하면 w값에 1이 초기값으로 들어간다.

 

Normal은 방향벡터로 w가 쓸일이 없으니까 굳이 w값까지 필요 없기에 float3로 받아오는것이다.


또 다른 사용의도가 있는데 이번에는 Pixel Shader에서 화면 비율과 관련된 의도인데

아직 사용을 안해봐서 직접해보고 추가로 작성해야겠다.

 

 


https://coding-groot.tistory.com/89

 

Homogeneous Coordinates를 왜 쓸까?

Homogeneous Coordinates에 대한 정리 수학적으로 $Homogeneous \ Coordinates$를 왜 쓰는지 이해는 못했다. 하지만 실용적으로 어떤 편의를 위해서 쓰는지는 알겠다. 검색하면서 정리한 여러 사용법에 대해서

coding-groot.tistory.com

https://enghqii.tistory.com/59?category=206685 

 

'DirectX 11 > 개념 정리' 카테고리의 다른 글

D3D11_USAGE / Resource Usage Type  (0) 2022.02.08
Vertex Shader, Pixel Shader, Rasterizer  (0) 2022.02.07
Device & Device Context / COM객체  (0) 2022.02.06

결과물

 


코드

 


추가

Height map

더보기

채널의 값을 불러와 높이정보로 사용할 수 있는 이미지를 뜻한다.

모두 흑백사진인데 이는 검은색( 0, 0, 0 ) 흰색 ( 1, 1, 1 ) 색상값을 통하여

0 ~ 1까지의 높이 비율로 표현할 수 있다.

많은 HeightMap

 

'DirectX 11 > 코드 분석' 카테고리의 다른 글

Get Height  (0) 2022.02.09
Normal vector / Shadow  (0) 2022.02.09
Texture Sampler  (0) 2022.02.08
Texture  (0) 2022.02.08
Grid / Camera  (0) 2022.02.08

결과물


코드

TextrueSampler.fx

픽셀셰이더 두개

 


'DirectX 11 > 코드 분석' 카테고리의 다른 글

Normal vector / Shadow  (0) 2022.02.09
Height map  (0) 2022.02.08
Texture  (0) 2022.02.08
Grid / Camera  (0) 2022.02.08
Index Buffer / World Scale, World Translation  (0) 2022.02.08

결과물


코드

TextureDemo.cpp

 


Texture.fx

 


추가

셰이더 리소스 뷰(Shader Resource View)

더보기

먼저 "리소스 뷰"는 리소스를 파이프라인에 연결해주는 객체이다.

'View' 라는 단어가 붙은 이유는 리소스를 특정 '시각'으로 해석한다는 의미이다.

 

그래서 종류가 4가지가 있는데 그중 셰이더 리소스 뷰는 

프로그램 가능 셰이더 단계가 리소스를 읽을 수 있게 한다.

프로그램 가능 셰이더 단계: vs, ps, gs...

읽을 수만 있기 때문에 기록하지는 못한다.

 

Sampler

더보기

계산된 픽셀에 맞도록 이미지를 맞춰주는것

이미지를 맞춰주는것 : address mode라는것과 filter가 있다.

 

  • address mode

uv좌표에서 u값이나 v값이 1이 넘어가면 어떻게 될까?

그 부분을 어떻게 처리할지 설정하는게 address mode이다.

u값, v값이 1보다 큰 픽셀에 어떻게 처리되는지 설정이 된다.
  • filter

우리가 넣을 텍스쳐는 크기가 정해져있다.

근데 그 텍스쳐를 매핑한 (정점4개로 이루어진)사각형의 크기가 크면 확대될것이고

사각형의 크기가 작으면 축소될것이다.

 

이는 즉 축소된다면 픽셀은 줄어들것이고 그 픽셀들의 색상은 어떻게 결정하고

확대되면 픽셀은 늘어날것인데 추가된 픽셀의 색상은 어떻게 결정할것인가?

=> 여러가지 보간방법으로 색상을 결정하는게 filter의 역할이다.

각 다른 보간법 / Anisotropic는 게임설정에 많이 나오던 MSAA와 연결된다.

※Linear의 식은 'A'------랜덤한 지점'x'------'B' 가 있다면

(1 - x) * A + x * B 이다.

 

 

보간기(Interpolator)

더보기

 

uv값은 정점의 실수 값이다. 

픽셀셰이더는 픽셀에 대한 계산인데 어떻게 계산이 될까? 궁금했다.

 

그건 레스터라이저단계에서 레스터라이저가

정점의 위치데이터를 가지고 픽셀들을 계산해준다면

같은 레스터라이저 단계에서 "보간기"라는게 정점의 다른데이터들을 픽셀에 맞게 보간해준다.

다른데이터 : 정점의 Normal값, 정점의 uv값...등등

그래서 픽셀셰이더에서 보간기로 수정된 uv값을 이용하여 계산할 수 있다.

 

텍스쳐 추가시

더보기

텍스쳐를 추가할때 사이즈를 2의 n승 에 맞게 가져오는게 성능상 좋다.

자동으로 2의n승에 맞게 사이즈가 조정되어 가져온다고한다.

ex) 589사이즈로 가져온다면 512로 조정된다.

 

 

https://www.3dgep.com/texturing-lighting-directx-11/

 

Texturing and Lighting in DirectX 11

In this tutorial you will learn how to implement Texturing and Lighting using a Pixel Shader in DirectX 11.

www.3dgep.com

 

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=masca140&logNo=220719096462 

 

Direct3D 11의 자원들 (1)

자원을 이야기 하자면 자원 사용의 두 측면을 모두 살펴보는 것이 타당하다. 응용 프로그램의 관점에서 중...

blog.naver.com

 

'DirectX 11 > 코드 분석' 카테고리의 다른 글

Height map  (0) 2022.02.08
Texture Sampler  (0) 2022.02.08
Grid / Camera  (0) 2022.02.08
Index Buffer / World Scale, World Translation  (0) 2022.02.08
World, View, Projection  (0) 2022.02.08

결과물


코드

GrideDemo.cpp


Camera.cpp

 

Freedom.cpp ( class Freedom : public Camera )

 

'DirectX 11 > 코드 분석' 카테고리의 다른 글

Texture Sampler  (0) 2022.02.08
Texture  (0) 2022.02.08
Index Buffer / World Scale, World Translation  (0) 2022.02.08
World, View, Projection  (0) 2022.02.08
Triangle  (0) 2022.02.07

+ Recent posts