◤ 2022๋ 7์ 31์ผ ์ผ์์ผ
● ์ธ๋ฆฌ์ผ ์์ง์ผ๋ก ๋ง๋ ๋ฎค์ง ๋น์ฅฌ์ผ๋ผ์ด์
◤ 2022๋ 7์ 29์ผ ๊ธ์์ผ
● DirectXTex ์ฌ์ฉ
//by JSHong CodeBlock//
#include "Core.h"#include "TextureLoader.h"#include <DirectXTex.h>#include <Utility/STLException.h>
namespace STL{ std::unordered_map<std::wstring, ID3D11ShaderResourceView*> TextureLoader::textureMap;
ID3D11ShaderResourceView* TextureLoader::CreateShaderResourceView(ID3D11Device* device, const std::wstring& filename) { auto search = textureMap.find(filename); if (search != textureMap.end()) { return search->second; }
std::wstring extension = filename.substr(filename.find_last_of(TEXT(".")) + 1); std::transform(extension.begin(), extension.end(), extension.begin(), tolower);
static auto basePath = std::filesystem::current_path().parent_path();
auto finalPath = basePath; finalPath /= "Content\\Textures"; finalPath /= filename;
DirectX::ScratchImage image; HRESULT hr = E_FAIL; if (extension == TEXT("tga") || extension == TEXT("targa")) { hr = DirectX::LoadFromTGAFile( finalPath.c_str(), nullptr, image ); } else { hr = DirectX::LoadFromWICFile( finalPath.c_str(), DirectX::WIC_FLAGS_NONE, nullptr, image ); }
ThrowIfFailed(hr, "Failed to load scratch image.");
ID3D11Texture2D* texture = nullptr; hr = DirectX::CreateTexture( device, image.GetImages(), image.GetImageCount(), image.GetMetadata(), reinterpret_cast<ID3D11Resource**>(&texture) );
ThrowIfFailed(hr, "Failed to create texture.");
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; memset(&srvDesc, 0, sizeof(srvDesc)); srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MipLevels = 1; srvDesc.Format = image.GetMetadata().format;
ID3D11ShaderResourceView* shaderResourceView = nullptr; hr = device->CreateShaderResourceView( texture, &srvDesc, &shaderResourceView );
SafeRelease(texture); ThrowIfFailed(hr, "Failed to shader resource view.");
textureMap.insert({ filename, shaderResourceView });
return shaderResourceView; }
void TextureLoader::Release() { for (auto pair : textureMap) { SafeRelease(pair.second); } }}
◤ 2022๋ 7์ 28์ผ ๋ชฉ์์ผ
● ๊นํ๋ธ ๊ณต๋ถํด๋ณด๊ธฐ
◤ 2022๋ 7์ 27์ผ ์์์ผ
● ๊นํ๋ธ ์ฒซ ์ฌ์ฉ
◤ 2022๋ 7์ 25์ผ ์์์ผ
● 7์ 25์ผ ์์์ผ
◤ 2022๋ 7์ 22์ผ ๊ธ์์ผ
● ๋น์ฃผ์ผ ์คํ๋์ค ํ๋ก์ ํธ ๋น๋ ์ค์
//๋น๋ ์ ์ด๋ฒคํธ
not exist "$(OutDir)..\Application" mkdir "$(OutDir)..\Application"
if not exist "$(SolutionDir)Lib\Engine\$(Platform)\$(Configuration)" mkdir "$(SolutionDir)Lib\Engine\$(Platform)\$(Configuration)"
//๋น๋ ํ ์ด๋ฒคํธ
copy "$(OutDir)Engine.dll" "$(Outdir)..\Application\"
copy "$(OutDir)Engine.lib" "$(SolutionDir)Lib\Engine\$(Platform)\$(Configuration)\"
Engine.vcxproj ํ์ผ(xml)์ ์ด์ด์ ๋ฉ๋ชจ์ฅ์์ ์์ ํด์ค๋ ๋๋ค.
● ๋น์ฃผ์ผ ์คํ๋์ค ์์ ์๋ ์๋ฌ ๋ ๋?
Application
- Pixelshder.hlsl ๋ง๋ค๊ณ
- VertexShader.hlsl ๋ง๋ค๊ณ
Engine
- Test.h ๋ง๋ค๊ณ
- Test.cpp ๋ง๋ค๊ณ
!!!!!! VIsual Studio์์ Path ์ค์ ์ ์คํ์ด์ค ์ธ์ ์ค๋ฅ๋๋ค!!! ์ ๊ธธ!!!!!!!!
$(SolutionDir)Engine\;$(SolutionDir)Engine\Source\;$(VC_IncludePath);$(WindowsSDK_IncludePath);
;๋ค์ ํ์นธ ๋๋ฉด ๋ท ๋ถ๋ถ ์ธ์ ๋ชปํจ ใ ใ
# UE ๋ฐ์ดํฐ ์ค๋ฏธ์ค (ํ๋ฌ๊ทธ์ธ)
- ์ธ๋ฆฌ์ผ์ด ๊ธฐ๋ณธ์ ์ผ๋ก FBX๋ง ์ง์ํ์ง๋ง ๋ฐ์ดํฐ์ค๋ฏธ์ค๋ฅผ ์ด์ฉํ์ฌ ๋ค์ํ ํฌ๋งท๋ ์ง์ ๊ฐ๋ฅํ๋ค.
# ๋น์ฅฌ์ผ ์คํ๋์ค 2019, 2022 ๋ค ์ค์น ๋ผ์ ์ฌ์ฉํ๋ค๊ฐ ์ด์ํ๊ฒ ์๊พธ ์ค๋ฅ๊ฐ ๋๊ธธ๋.. ํน์๋ ํด์ 2019๋ฅผ ์ญ์ ํ๋๊น ํด๊ฒฐ์ด ๋์๋ค
- ๊ตฌ๋ฌธ ํด์ ์ค์๊ฐ ์ ์๋๋ ํ์
- ์ด์ํ๊ฒ ์ค์ ์ค๋ฅ๊ฐ ๋์ include, link๊ฐ ์ ์๋ผ์ ์ค๋ฅ ๋๊ธฐ๋ ํจ
- 2019 ์ ๊ฑฐํ๊ณ 2022 ํ๋๋ง ์ฌ์ฉํ๋ ๊น๋ํ๊ฒ ํด๊ฒฐ์ด ๋จ ใ
ใ
ใ
● ์ ํ๋ธ ๋น๋์ค ์ฑํฐ ์ ๋ณด๋ฅผ ๊ฐ๊ณ ์ฌ ์ ์์๊น?
const axios = require('axios').default; // You have to install axios (npm install axios) in order to use this code
const youtubeApiKey = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; // Your YouTube API Key here
// Function for filtering array elements which don't contain a timestamp
const notText = (array) => {
const regexTimePattern = /\d:\d/;
for (let i = 0; i < array.length; i++) {
let result = regexTimePattern.exec(array[i]);
if (result === null) {
array[i] = "";
}
}
}
const main = async (videoId) => {
const videoDataResponse = await axios.get(
`https://youtube.googleapis.com/youtube/v3/videos?part=snippet&id=${videoId}&key=${youtubeApiKey}`,
{ headers: { 'Accept': 'application/json' } }
);
const description = JSON.stringify(videoDataResponse.data.items[0].snippet.description); //DESCRIรรO DO VรDEO
// Find [number]:[number] pattern in description
const numberNumberPattern = /\d:\d/gi;
let descriptionLines = [], numberNumbeResult;
while ((numberNumbeResult = numberNumberPattern.exec(description))) {
descriptionLines.push(numberNumbeResult.index);
}
let min = [], sec = [], hour = [], chapterTitle = [], chapterStartIndex, chapterEndIndex;
// Verifies if last [number]:[number] correspondence is in the last description line
if (description.indexOf("\\n", descriptionLines[descriptionLines.length - 1]) === -1) { //รฉ na รบltima linha
chapterEndIndex = description.length - 1;
} else { // not in the last line
chapterEndIndex = description.indexOf("\\n", descriptionLines[descriptionLines.length - 1]);
}
// Verifies if first [number]:[number] correspondence is in the first description line
switch (descriptionLines[0]) {
case 1: // it's in the first line ([number]:[number] pattern)
chapterStartIndex = 1;
break;
case 2: // it's in the first line ([number][number]:[number] pattern)
chapterStartIndex = 2;
break;
default: //it's not in the first line
const auxiliarString = description.substring(descriptionLines[0] - 6);
chapterStartIndex = auxiliarString.indexOf("\\n") + descriptionLines[0] - 4;
}
// get description part with timestamp and titles
const chapters = description.substring(chapterStartIndex, chapterEndIndex);
// separete lines
const notFilteredLine = chapters.split("\\n");
// filter lines which don't have [number]:[number] pattern
notText(notFilteredLine);
// filter empty lines
const filteredLine = notFilteredLine.filter(Boolean);
for (let i = 0; i < filteredLine.length; i++) {
const notNumberOrColonRegex = /[^:\d]/; // not number nor ":"
const numberRegex = /\d/; // number
let numberResult = numberRegex.exec(filteredLine[i]);
filteredLine[i] = filteredLine[i].substring(numberResult.index); // starts line in first number found
let notNumberOrColonResult = notNumberOrColonRegex.exec(filteredLine[i]);
let tempo = filteredLine[i].substring(0, notNumberOrColonResult.index); // timestamp end (not number nor ":")
let tempoSeparado = tempo.split(":"); // split timestamps in each ":"
switch (tempoSeparado.length) {
case 2: // doesn't have hour
hour[i] = 0;
min[i] = Number(tempoSeparado[0]);
sec[i] = Number(tempoSeparado[1]);
break;
case 3: // has hour
hour[i] = Number(tempoSeparado[0]);
min[i] = Number(tempoSeparado[1]);
sec[i] = Number(tempoSeparado[2]);
break;
}
const numberOrLetterRegex = /[a-z0-9]/i; // number or letter
const auxiliarString = filteredLine[i].substring(notNumberOrColonResult.index); // auxiliar string starts when not number nor ":"
let numberOrLetterResult = numberOrLetterRegex.exec(auxiliarString);
// chapter title starts in first letter or number found in auxiliarString
chapterTitle[i] = auxiliarString.substring(numberOrLetterResult.index);
}
let chaptersData = [];
for (let i = 0; i < chapterTitle.length; i++) {
chaptersData[i] = {
chapterTitle: chapterTitle[i],
chapterTimestamp: [hour[i], min[i], sec[i]]
}
}
console.log(chaptersData);
// chaptersData contains the data we are looking for
// chaptersData is an array of objects, in the format {chapterTitle: 'chapter title example', chapterTimestamp: [01, 25, 39]}
// chapterTimestamp is in the format [hour, minute, second]
}
// calls main with the ID of the video of interest
main('videoId'); // For example: main('R3WDe7byUXo');
#youtube video chapters API
◤ 2022๋ 7์ 21์ผ ๋ชฉ์์ผ
● ์ผ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <tchar.h>
#include <string>
//#include <time.h>
//#include <cmath>
// DX Header
#include <d3d11.h> // DirectX11 ํค๋
#include <d3dcompiler.h> // ์์ด๋ ์ปดํ์ผ๋ฌ ๊ธฐ๋ฅ ์ ๊ณต
#include <comdef.h>
// lib ๋งํน
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dcompiler.lib")
// ๋ณ์
// ์ ์ญ ๋ณ์ <-> ํจ์ ๋ด์ ์๋ ๋ณ์๋ ์ง์ญ ๋ณ์
std::wstring className = TEXT("Sample Window Class");
std::wstring title = TEXT("STL Render Engine");
HINSTANCE hInstance = nullptr;
int width = 1600;
int height = 900;
HWND hwnd = nullptr;
// DX ๋ณ์
// DX ์ฅ์น
ID3D11Device* device = nullptr;
ID3D11DeviceContext* context = nullptr;
IDXGISwapChain* swapChain = nullptr;
ID3D11RenderTargetView* renderTargetView = nullptr;
// ์ ์ ๋ฒํผ ๊ด๋ จ ๋ณ์
unsigned int vertexByteWidth = 0u;
unsigned int vertexCount = 0u;
ID3D11Buffer* vertexBuffer = nullptr;
ID3D11VertexShader* vertexShader = nullptr;
ID3D11PixelShader* pixelShader = nullptr;
ID3D11InputLayout* inputlayout = nullptr;
// DX ์ฅ์น ์ด๊ธฐํ
void InitializeDevice();
// ์ฅ๋ฉด ์ด๊ธฐํ
void InitializeScene();
void Draw();
// ์ค๋ฅ ๋ฉ์์ง ์ป์ด์ค๋ ํจ์
std::wstring GetErrorMessage(HRESULT hr)
{
_com_error error(hr);
return error.ErrorMessage();
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nShowCmd)
{
// Register the window class.
::hInstance = hInstance; // ::์ ์ญ ๋ณ์๋ฅผ ๊ฐ๋ฆฌํด
WNDCLASS wc = { };
//memset(&wc, 0, sizeof(wc));
// Invoke
wc.lpfnWndProc = WindowProc; // ์ฝ๋ฐฑ(Callback) / ์์(Delegate)
wc.hInstance = hInstance;
wc.lpszClassName = className.c_str();
// ์ฐฝ ํด๋์ค ์ด๋ฆ ๋ฑ๋ก
RegisterClass(&wc);
// Create the window.
// ์ฐฝ ํฌ๊ธฐ ์กฐ์ .
// RECT๋ ์ง์ฌ๊ฐํ ๊ตฌ์กฐ์ฒด, (left, top, right, bottom)
RECT rect = { 0, 0, static_cast<long>(width), static_cast<long>(height) };
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
// ์กฐ์ ๋ ์ง์ฌ๊ฐํ ํฌ๊ธฐ๋ก ์ฐฝ ๊ฐ๋ก/์ธ๋ก ํฌ๊ธฐ ๊ตฌํ๊ธฐ(Window๋ ์ข์ธก ์๋จ์ด ๊ธฐ์ค์ )
int windowWidth = rect.right - rect.left;
int windowHeight = rect.bottom - rect.top;
// ํ๋ฉด ์ค์ฌ์์ ์ฐฝ์ ๊ทธ๋ฆฌ๊ธฐ ์ํ ์์ฑ์ขํ ๊ตฌํ๊ธฐ
// GetSystemMetrics(SM_CXSCREEN) -> ๋ชจ๋ํฐ ๊ฐ๋ก ํฌ๊ธฐ ๊ตฌํ๋ ํจ์
// GetSystemMetrics(SM_CYSCREEN) -> ๋ชจ๋ํฐ ์ธ๋ก ํฌ๊ธฐ ๊ตฌํ๋ ํจ์
int xPosition = (GetSystemMetrics(SM_CXSCREEN) - windowWidth) / 2;
int yPosition = (GetSystemMetrics(SM_CYSCREEN) - windowHeight) / 2;
hwnd = CreateWindowEx(
0, // Optional window styles.
className.c_str(), // Window class
title.c_str(), // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position (์คํ ์ ์์น์ ํฌ๊ธฐ)
//CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
xPosition, yPosition, windowWidth, windowHeight,
nullptr, // Parent window
nullptr, // Menu
hInstance, // Instance handle
nullptr // Additional application data
);
if (hwnd == nullptr)
{
return 0;
}
ShowWindow(hwnd, SW_SHOW); // window ์ฐฝ ์ผ๋ฐ์ ์ธ ์ํ๋ก ๋ณด์ด๊ธฐ
UpdateWindow(hwnd); // ์ฐฝ ์
๋ฐ์ดํธ
// ------ ์ฐฝ ์์ฑ ------ //
// DX ์ด๊ธฐํ
InitializeDevice();
// ์ฅ๋ฉด ์ด๊ธฐํ
InitializeScene();
// Run the message loop.
MSG msg = { }; // MSG ๊ตฌ์กฐ์ฒด์ ๋ง์ฐ์ค ํด๋ฆญ ๋ฐ์ ๋ฑ์ด ๋ค์ด์์
// WM_QUIT ๋ฉ์์ง๊ฐ ์๋๋ฉด ๊ณ์ ๋ฃจํ ์คํ
while (msg.message != WM_QUIT)
{
// ์๋์ฐ๊ฐ ๋ฉ์์ง ์ ๋ฌํ๋ฉด ์คํ
//if (GetMessage(&msg, NULL, 0, 0) > 0)
if (PeekMessage(&msg, nullptr, 0u, 0u, PM_REMOVE))
{
// ์๋์ฐ(OS)๊ฐ ์ ๋ฌํ ๋ฉ์์ง ํด์ ๋ฐ ์ ๋ฌ(WindowProc ํจ์ ํธ์ถ)
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
Draw();
// GameLoop
// Rendering (DX ์์
์ ์ฌ๊ธฐ์ ์คํ)
// ProcessInput
// Update
// Render
// PostRender
}
}
// ์ฐฝ ๋ฑ๋ก ํด์
UnregisterClass(className.c_str(), hInstance);
return 0;
}
void InitializeDevice()
{
// ์ฅ์น ์์ฑํ ๋ ์ ๋ฌํ ์ต์
๊ฐ
unsigned int createFlag = 0;
#if _DEBUG
// Debug ๋ชจ๋์ธ ๊ฒฝ์ฐ,
// ์ฅ์น ์์ฑ ๊ณผ์ ์์ ์ค๋ฅ๊ฐ ๋ฐฉ์ํ์ ๋ ๋๋ฒ๊น
์ ๋ณด๋ฅผ ๋ ๋ง์ด ์ ๋ฌํด๋ฌ๋ผ๋ ์ต์
์ถ๊ฐ
createFlag |= D3D11_CREATE_DEVICE_DEBUG;
#endif
// DX11 ๋ฒ์ ์ง์
// ์์ ๋ฒ์ ์ ์์ ๋ฃ์ผ๋ฉด ๋จผ์ ์๋ํด๋ณด๊ณ , ์ง์ํ์ง ์์ผ๋ฉด ๋ค์ ๋ฒ์ ์ผ๋ก ๋์ด๊ฐ
D3D_FEATURE_LEVEL levels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0
};
// ์ค์์ฒด์ธ ์์ฑ์ ์ํ ๊ตฌ์กฐ์ฒด ์ค์
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
swapChainDesc.BufferCount = 1; // ๋ฐฑ๋ฒํผ ๊ฐ์ ์ค์
swapChainDesc.BufferDesc.Width = width; // ํ๋ ์(์ด๋ฏธ์ง) ๊ฐ๋ก ํฌ๊ธฐ
swapChainDesc.BufferDesc.Height = height; // ํ๋ ์(์ด๋ฏธ์ง) ์ธ๋ก ํฌ๊ธฐ
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // ์ด๋ฏธ์ง ์ฑ๋๋ณ ํฌ๋ฉง
swapChainDesc.Windowed = true; // ์ฐฝ(Window) ๋ชจ๋ ์ฌ๋ถ ์ค์
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // ํ๋ ์(์ด๋ฏธ์ง)์ ์ฉ๋ (๋ ๋๋ง)
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // Front <-> Back ๋ฒํผ ๋ณ๊ฒฝํ ๋ ํจ๊ณผ ๋ฃ์์ง ์ค์
swapChainDesc.SampleDesc.Count = 1; // ๋ฉํฐ ์ํ๋ง ํ ์ง ์ฌ๋ถ ์ค์ -> ์ํจ
swapChainDesc.SampleDesc.Quality = 0; // ๋ฉํฐ ์ํ๋ง ํ์ง ์ค์ -> ๊ธฐ๋ณธ ๊ฐ (Count - 1)
swapChainDesc.OutputWindow = hwnd; // DX๊ฐ ๊ทธ๋ฆด ์ฐฝ ํธ๋ค
D3D_FEATURE_LEVEL finalFeature;
// ์ฅ์น ์ด๊ธฐํ
auto result = D3D11CreateDeviceAndSwapChain(
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
nullptr,
createFlag,
levels,
//ARRAYSIZE(levels),
_countof(levels),
D3D11_SDK_VERSION,
&swapChainDesc,
&swapChain,
&device,
&finalFeature,
&context
);
// ์คํจ ์ฌ๋ถ ํ์ธ
if (FAILED(result))
{
//MessageBox(nullptr, L"Failed to create device.", L"Error", MB_OK);
MessageBox(nullptr, GetErrorMessage(result).c_str(), L"Error", MB_OK);
exit(-1);
}
// ๋๋(Render, ๊ทธ๋ฆฐ๋ค, Draw) ํ๊ฒ (๋ฐฑ๋ฒํผ) -> ์ฐ๋ฆฌ๊ฐ ์ด๋ฏธ์ง๋ฅผ ๊ทธ๋ฆด ๋ฒํผ(๋ฉ๋ชจ๋ฆฌ)
ID3D11Texture2D* backbuffer = nullptr;
// ๊ทธ๋ํฝ์นด๋๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ฐฑ๋ฒํผ ์ ๋ณด๋ฅผ ์ป์ด์จ๋ค.
result = swapChain->GetBuffer(
0,
__uuidof(ID3D11Texture2D),
reinterpret_cast<void**>(&backbuffer)
);
// ์ค๋ฅ ํ์ธ
if (FAILED(result))
{
MessageBox(nullptr, GetErrorMessage(result).c_str(), L"Error", MB_OK);
exit(-1);
}
// ๋ ๋ ํ๊ฒ ๋ทฐ(RenderTargetView) ์์ฑ
renderTargetView = nullptr;
result = device->CreateRenderTargetView(
backbuffer,
nullptr,
&renderTargetView
);
// ์ค๋ฅ ํ์ธ
if (FAILED(result))
{
MessageBox(nullptr, GetErrorMessage(result).c_str(), L"Error", MB_OK);
exit(-1);
}
// ๋ฐฑ๋ฒํผ ํด์
// COM
backbuffer->Release();
// ๋ ๋ ํ์ผ ๋ทฐ ์ค์
context->OMSetRenderTargets(1, &renderTargetView, nullptr);
// ํ๋ฉด(Viewport) ์ค์
D3D11_VIEWPORT viewport = {};
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
viewport.Width = static_cast<float>(width); // width๊ฐ int ์ด๋ฏ๋ก float ๋ก ํ๋ณํ
viewport.Height = static_cast<float>(height); // height๊ฐ int ์ด๋ฏ๋ก float ๋ก ํ๋ณํ
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
// ๋ทฐํฌํธ ์ค์
context->RSSetViewports(1, &viewport);
}
void InitializeScene()
{
// 1. ์ ์ (Virtex) ๋ฐ์ดํฐ ์์ฑ
struct Vertex
{
float x;
float y;
float z;
};
// ์ ๋ฐ์ดํฐ
// NDC-(Viewport)
Vertex vertices[] =
{
{ 0.0f, 0.5f, 0.5f }, /*{x, y, z?}*/
{ 0.5f, -0.5f, 0.5f },
{ -0.5f, -0.5f, 0.5f }
};
//
vertexByteWidth = sizeof(Vertex);
vertexCount = _countof(vertices);
// ์ ์ ๋ฒํผ๋ฅผ ์ค๋ช
ํ๋ ๊ตฌ์กฐ์ฒด
D3D11_BUFFER_DESC vertexBufferDesc = {};
vertexBufferDesc.ByteWidth = sizeof(Vertex) * _countof(vertices);
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
// ์ ์ ๋ฐฐ์ด(๋ฐ์ดํฐ)์ ๋ด์ ๊ตฌ์กฐ์ฒด
D3D11_SUBRESOURCE_DATA vertexData = {};
vertexData.pSysMem = vertices;
// ์ ์ ๋ฒํผ
//ID3D11Buffer* vertexBuffer = nullptr;
// ์ ์ ๋ฒํผ ์์ฑ
auto result = device->CreateBuffer(
&vertexBufferDesc,
&vertexData,
&vertexBuffer
);
// ์ค๋ฅ ํ์ธ
if (FAILED(result))
{
MessageBox(nullptr, GetErrorMessage(result).c_str(), L"Error", MB_OK);
exit(-1);
}
// ์
ฐ์ด๋(Shader-๊ทธ๋ํฝ ์นด๋์์ ์ฌ์ฉํ๋ ํ๋ก๊ทธ๋จ) ์์ฑ (์ ์ ์
ฐ์ด๋ / ํฝ์
์
ฐ์ด๋)
// ์ ์ ์
ฐ์ด๋ ์์ฑ
// 1. ์ปดํ์ผ
// 2. ์ปดํ์ผ๋ ์ด์ง ํ์ผ ๋ก๋
// 3. ์
ฐ์ด๋ ์์ฑ
ID3DBlob* vertexShaderBuffer = nullptr;
result = D3DCompileFromFile(
L"VertexShader.hlsl",
nullptr,
nullptr,
"main",
"vs_5_0",
0u,
0u,
&vertexShaderBuffer,
nullptr
);
// ์ค๋ฅ ํ์ธ
if (FAILED(result))
{
MessageBox(nullptr, GetErrorMessage(result).c_str(), L"Error", MB_OK);
exit(-1);
}
// ์ ์ ์
ฐ์ด๋ ์์ฑ
//ID3D11VertexShader* vertexShader = nullptr;
result = device->CreateVertexShader(
vertexShaderBuffer->GetBufferPointer(),
vertexShaderBuffer->GetBufferSize(),
nullptr,
&vertexShader
);
// ์ค๋ฅ ํ์ธ
if (FAILED(result))
{
MessageBox(nullptr, GetErrorMessage(result).c_str(), L"Error", MB_OK);
exit(-1);
}
// ํฝ์
์
ฐ์ด๋
ID3DBlob* pixelShaderBuffer = nullptr;
result = D3DCompileFromFile(
L"pixelShader.hlsl",
nullptr,
nullptr,
"main",
"ps_5_0",
0u,
0u,
&pixelShaderBuffer,
nullptr
);
// ์ค๋ฅ ํ์ธ
if (FAILED(result))
{
MessageBox(nullptr, GetErrorMessage(result).c_str(), L"Error", MB_OK);
exit(-1);
}
// ํฝ์
์
ฐ์ด๋ ์์ฑ
//ID3D11VertexShader* vertexShader = nullptr;
result = device->CreatePixelShader(
pixelShaderBuffer->GetBufferPointer(),
pixelShaderBuffer->GetBufferSize(),
nullptr,
&pixelShader
);
// ์ค๋ฅ ํ์ธ
if (FAILED(result))
{
MessageBox(nullptr, GetErrorMessage(result).c_str(), L"Error", MB_OK);
exit(-1);
}
// ์
๋ ฅ ๋ ์ด์์ ์์ฑ (์
๋ ฅ=์ ์ , ์ ์ ์ ์๊น์)
//ID3D11InputLayout* inputlayout = nullptr;
//LPCSTR SemanticName;
//UINT SemanticIndex;
//DXGI_FORMAT Format;
//UINT InputSlot;
//UINT AlignedByteOffset;
//D3D11_INPUT_CLASSIFICATION InputSlotClass;
//UINT InstanceDataStepRate;
D3D11_INPUT_ELEMENT_DESC inputElementDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
result = device->CreateInputLayout(
inputElementDesc,
_countof(inputElementDesc),
vertexShaderBuffer->GetBufferPointer(),
vertexShaderBuffer->GetBufferSize(),
&inputlayout
);
// ์ค๋ฅ ํ์ธ
if (FAILED(result))
{
MessageBox(nullptr, GetErrorMessage(result).c_str(), L"Error", MB_OK);
exit(-1);
}
}
void Draw()
{
// ๋ฐฐ๊ฒฝ ์ง์ฐ๊ธฐ
float color[] = { 0.2f, 0.4f, 0.6f, 1.0f }; // red, green, blue ์์
context->ClearRenderTargetView(renderTargetView, color);
// ๊ทธ๋ฆฌ๊ธฐ
// ๋ฐ์ดํฐ/์
ฐ์ด๋ ์ค์
// ์์ ์๊ด ์์
// ์ ์ ์ฐ๊ฒฐํด์ ๋ฉด์ ๋ง๋ค ๋ ๊ธฐ์ค์ด๋๋ ๋ฐฉ์์ ์ง์ ํจ
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
static unsigned int stride = vertexByteWidth; // static์ ์ฌ์ฉํ๋ฉด ๋๋ก์ฐ ์ฝ ํ ๋ ๋ณ์๋ฅผ ํ ๋ฒ๋ง ์์ฑํด์ ๊ณต์ ํ๋ค.
static unsigned int offset = 0u;
// ์ ์ ๋ฒํผ ์ค์
context->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
context->IASetInputLayout(inputlayout);
// ์
ฐ์ด๋ ์ค์
context->VSSetShader(vertexShader, nullptr, 0);
context->PSSetShader(pixelShader, nullptr, 0);
// ๋๋ก์ฐ ์ฝ
context->Draw(vertexCount, 0);
swapChain->Present(1u, 0u); // 1์ ๋ฃ์ผ๋ฉด ๋ชจ๋ํฐ์ ํ๋ ์ ๋๊ธฐํ, 0์ ๋ฃ์ผ๋ฉด ๋ชจ๋ํฐ์ ํ๋ ์ ๋๊ธฐํ๋ฅผ ํ์ง ์์.
// BeginRender -> ๋ฐฐ๊ฒฝ ์ง์ฐ๊ธฐ
// Render -> ์ ๋ฉด ๊ทธ๋ฆฌ๊ธฐ
// EndRender -> ์ค์์ฒด์ธ ๊ตํ
}
// ์ฐฝ ๊ตฌํ
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY: // ์ฐฝ์ด ๋ซํ๋ ๊ฒฝ์ฐ ํ๋ก๊ทธ๋จ ์ข
๋ฃ
PostQuitMessage(0);
return 0;
case WM_PAINT: // ๊ทธ๋ฆฌ๋ ๊ธฐ๋ฅ์ ์ฌ์ฉ
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// All painting occurs here, between BeginPaint and EndPaint.
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
}
return 0;
case WM_KEYDOWN:
{
// ESC ํค๊ฐ ๋๋ฆฌ๋ฉด
if (wParam == VK_ESCAPE)
{
// ๋ฉ์์ง ์์ ๋์ฐ๊ธฐ
// ์/์๋์ ๋ฒํผ์ ์ ๊ณตํ๋ ๋ฉ์์ง ์์๋ฅผ ๋์ฐ๊ณ , "์"๋ฅผ ์ ํํ๋ฉด ์ฐฝ ์ญ์
if (MessageBox(nullptr, TEXT("Quit?"), TEXT("Quit Engine"), MB_YESNO/*๋์์ธ*/) == IDYES/*YES๋ฅผ ๋๋ฅด๋ฉด ์คํ*/)
{
// ์ฐฝ ํธ๋ค ์ญ์ -> ์ฐฝ ์ญ์
DestroyWindow(hwnd);
}
}
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
● 7์ 21์ผ DX ์์ 2์ผ์ฐจ
์ด๋์ฐ์ ๊ฒ์ ์ํ ๋ธ๋ก๊ทธ
https://blog.naver.com/destiny9720/221408760120
์์ : 13๋ฒ๊น์ง ์ฝ์ด๋ณด๊ธฐ
#์ํ๊ณต๊ฐ
#๋์ฐจ์ขํ๊ณ
# ์ ์ ๋ฒํผ
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=atom723&logNo=190302142
#๋ฒํ ์ค ์์ด๋, ํฝ์ ์์ด๋
◤ 2022๋ 7์ 13์ผ ์์์ผ
● ๋ฌด์จ ๋ถ๊ท ์ํ๋ฅผ ๋๋ฆฌ๊ฒ ๋ค๊ณ ์๋ก์ด ๊ณต๋ถ๋ฅผ ์์ํ๋ ๊ฑธ๊น? ใ ใ
◤ 2022๋ 7์ 10์ผ ์ผ์์ผ
● ๋จธ๋ฆฌ์นด๋ฝ ๊ฑฐ๋ฆ๋ง ๊ตฌ๋งค (17000์), ํ์ง๋ง 4600์์ผ๋ก ๋ ํ๋ณตํด์ง
ํ ์ฌ๋ฃธ ์คํ ์ธ๋ฆฌ์ค ์ธํธ๋ผ ์์กฐ ๋จธ๋ฆฌ์นด๋ฝ ๊ฑฐ๋ฆ๋ง ๊ตฌ๋งค
๋จธ๋ฆฌ์นด๋ฝ ๋๋ฌธ์ ์คํธ๋ ์ค ใ ใ
๋จธ๋ฆฌ ๊ฐ๊ณ ๋ ๋๋ง๋ค ์์กฐ์ ํ ์ ํผ์ฉ ๋น ์ ธ์ ์ ๊ฑธ๋ฌ์ค์ผ ํ๋๋ฐ ๊ธฐ์กด์ ์ฐ๋ ๊ฑด ์ ๋ณ๋ก๋ค.
๊ทธ๋์ ์ค๋ ์ฐ์ฐํ ๊ฒ์ํ๋ค๊ฐ ํ์ด ๋๋ฌด ์ข๊ธธ๋ ๊ตฌ๋งค๋ฅผ ํด๋ดค๋ค. ์ฟ ํก์์ 23880์ ํ๋๋ฐ (๋ญ๊ฐ ์ด๋ฆฌ ๋น์ธ๋ ใ ใ ์คํ ์ธ๋ ์ค ์ฌ์ง์๋ค๊ฐ ํนํ๊ถ์ด ์๋๋ณด๋ค ๋๊ฐ์ด ์๊ฒผ๋๋ฐ ์งํ 8000์์ง๋ฆฌ๋ ์ฌ์ง์ด ํ๋ผ์คํฑ์ด๋ผ๊ณ ํ๋ค ใ ใ ใ ใ ) ์๋ฉํ์์ 17000์(๋ฌด๋ฃ๋ฐฐ์ก) ํ์์ค๋ฌ์์ ๋ฐ๋ก ๊ตฌ๋งค!
| ์ผ๋จ ์ง๋ ์ ใ ใ |
| ์๊ฑด ์๊ธด ๊ฑด ๋น์ทํ๋ฐ ํ๋ผ์คํฑ์ด๋๋ค ใ |
์ฌ์ฉํด ๋ณด๋ ์ ๋ง ๋จธ๋ฆฌ์นด๋ฝ์ ์ ๊ฑธ๋ฌ์ค๋ค. ํ์ง๋ง ๋จ์ ์ด ์๋ค. ๋จธ๋ฆฌ์นด๋ฝ์ด ๋ง์ ๊ฑธ๋ฌ์ง๋ ๊ฑด ์ข์๋ฐ ๊ธด ๋จธ๋ฆฌ์นด๋ฝ๋ค์ด ์นญ์นญ ๊ฐ๊ฒจ ์๋ ๊ฑธ ํด์ง๋ก ๋ค์ ๋ฆ์ ๋ด๋ฏ์ด ์ง์ด ๋นผ์ผ ํ๋๋ฐ ๊ธ์ ์ฌ์ง์ด๋ผ ๋จ๋จํด์ ์คํ๋ ค ๋จธ๋ฆฌ์นด๋ฝ์ ํ์ณ ๋ด๊ธฐ๊ฐ ์ฝ์ง๋ ์๋ค.
์ด๊ฒ์ด ์ฌ์ง์ด ์ข ๋ง๋๋ง๋ํ๋ฉด ํด์ง๋ก ๊ฐ์ธ์ฅ๊ณ ๋จธ๋ฆฌ์นด๋ฝ์ ๊ธ์ด ๋ด๊ธฐ๊ฐ ๋ ์ฌ์ธํ ๋ฐ.. ๊ทธ ์๊ฐ์ผ๋ก ์ข ๋ ๊ฒ์์ ํด๋ณด๋.. ์ญ์๋ ๊ทธ๋ฐ ์ ํ๋ ์์๋ค. ํ ์ฌ๋ฃธ์ด๋ ๋ชจ์์ ์ด์ง ๋ค๋ฅด์ง๋ง ๊ทธ ๋ชจ์์๋ง ๋ด๋ ๋๋ต ํ ์ฌ๋ฃน๊ณผ ๊ฐ์ ์๋ฆฌ๋ก ์ฌ์ฉํ ์ ์๊ฒ ๋ค๋ ๋๋์ด ๋ฐ๋ก ๋ ๋ค.
๋๋์ด ๊ธด๊ธด ๋จธ๋ฆฌ์นด๋ฝ ๋๋ฌธ์ ํญ์ ์์กฐ ๋งํ๋ ์คํธ๋ ์ค์์ ํด๋ฐฉ์ด ๋์๋ค. ์ด๊ฒ ๋ญ๋ผ๊ณ ํ๋ณตํ๋ค๋ ใ ใ
#ํ ์ฌ๋ฃธ
#๋ฆฌ๋ฒ๊ทธ๋ฆฐ
#๋จธ๋ฆฌ์นด๋ฝ๊ฑฐ๋ฆ๋ง












































