[DirectX11] 020~22 Normal Vector
목차
Normalize
A = V1 - V0
B = V2 - V0
Normal 방향 = Cross(A, B)
Normal = Normalize(cross(A, B))
Light Direction 내적
A ⊙ B = |A||B|cosθ
Normalize해서 1 x 1 x cosθ = cosθ
빛이 90도로 들어오면 0.
Normal Vector의 방향
Normal Vector 방향은 항상 World 변환하여야 한다. Normal의 방향이 바뀌었을때 Update가 되어야 하기 때문이다.
w의 활용
w = 1 일 때, 위치
w = 0 일 때, 방향
w는..
Vertex Shader(VS)에서는 위치와 방향을 표기하기 위하여 사용하고
Pixel Shader(PS)에서는 화면 비율에 활용하기 위해 사용한다.
https://lipcoder.tistory.com/114
https://designerd.tistory.com/entry/DirectX12-Matrix
Terrain & DebugLine.fx
Terrain.fx
더보기
matrix World;
matrix View;
matrix Projection;
float3 Direction;
struct VertexInput
{
float4 Position : Position;
float3 Normal : Normal;
};
struct VertexOutput
{
float4 Position : SV_Position;
float3 Normal : Normal;
};
VertexOutput VS(VertexInput input)
{
VertexOutput output;
output.Position = mul(input.Position, World);
output.Position = mul(output.Position, View);
output.Position = mul(output.Position, Projection);
output.Normal = mul(input.Normal, (float3x3) World);
return output;
}
float4 PS(VertexOutput input) : SV_Target
{
float3 normal = normalize(input.Normal);
float3 light = -Direction;
return float4(1, 1, 1, 1) * dot(light, normal);
}
RasterizerState FillMode_Wireframe
{
FillMode = Wireframe;
};
technique11 T0
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetPixelShader(CompileShader(ps_5_0, PS()));
}
pass P1
{
SetRasterizerState(FillMode_Wireframe);
SetVertexShader(CompileShader(vs_5_0, VS()));
SetPixelShader(CompileShader(ps_5_0, PS()));
}
}
DebugLine.fx
더보기
matrix World;
matrix View;
matrix Projection;
struct VertexInput
{
float4 Position : Position;
float4 Color : Color;
};
struct VertexOutput
{
float4 Position : SV_Position;
float4 Color : Color;
};
VertexOutput VS(VertexInput input)
{
VertexOutput output;
output.Position = mul(input.Position, World);
output.Position = mul(output.Position, View);
output.Position = mul(output.Position, Projection);
output.Color = input.Color;
return output;
}
float4 PS(VertexOutput input) : SV_Target
{
return input.Color;
}
technique11 T0
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetPixelShader(CompileShader(ps_5_0, PS()));
}
}
Terrain
Terrain.h
더보기
#pragma once
class Terrain
{
public:
typedef VertexNormal TerrainVertex;
public:
Terrain(Shader* shader, wstring heightFile);
~Terrain();
void Update();
void Render();
void Pass(UINT val) { pass = val; }
private:
void CreateVertexData();
void CreateIndexData();
void CreateNormalData();
void CreateBuffer();
private:
UINT pass = 0;
Shader* shader;
Texture* heightMap;
UINT width, height;
UINT vertexCount;
TerrainVertex* vertices;
ID3D11Buffer* vertexBuffer;
UINT indexCount;
UINT* indices;
ID3D11Buffer* indexBuffer;
};
Terrain.cpp
더보기
#include "Framework.h"
#include "Terrain.h"
Terrain::Terrain(Shader * shader, wstring heightFile)
: shader(shader)
{
heightMap = new Texture(heightFile);
CreateVertexData();
CreateIndexData();
CreateNormalData();
CreateBuffer();
}
Terrain::~Terrain()
{
SafeDelete(heightMap);
SafeDeleteArray(vertices);
SafeDeleteArray(indices);
SafeRelease(vertexBuffer);
SafeRelease(indexBuffer);
}
void Terrain::Update()
{
//빛의 방향
static Vector3 direction = Vector3(-1, -1, 1);
ImGui::SliderFloat3("Direction", direction, -1, 1);
shader->AsVector("Direction")->SetFloatVector(direction);
Matrix world;
D3DXMatrixIdentity(&world);
shader->AsMatrix("World")->SetMatrix(world);
shader->AsMatrix("View")->SetMatrix(Context::Get()->View());
shader->AsMatrix("Projection")->SetMatrix(Context::Get()->Projection());
}
void Terrain::Render()
{
//Normal Vector 그리기 /////////////////
for (int i = 0; i < vertexCount; i++)
{
Vector3 start = vertices[i].Position;
//start위치에서 vertices[i].Normal * 2 만큼 늘렸다
Vector3 end = vertices[i].Position + vertices[i].Normal * 2;
DebugLine::Get()->RenderLine(start, end, Color(0, 1, 0, 1));
}
////////////////////////////////////////
UINT stride = sizeof(TerrainVertex);
UINT offset = 0;
D3D::GetDC()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
D3D::GetDC()->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
D3D::GetDC()->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R32_UINT, 0);
shader->DrawIndexed(0, pass, indexCount);
}
void Terrain::CreateVertexData()
{
vector<Color> heights;
heightMap->ReadPixel(DXGI_FORMAT_R8G8B8A8_UNORM, &heights);
width = heightMap->GetWidth();
height = heightMap->GetHeight();
vertexCount = width * height;
vertices = new TerrainVertex[vertexCount];
for (UINT z = 0; z < height; z++)
{
for (UINT x = 0; x < width; x++)
{
UINT index = width * z + x;
UINT pixel = width * (height - 1 - z) + x;
vertices[index].Position.x = (float)x;
vertices[index].Position.y = heights[pixel].r * 255.0f / 10.0f;
vertices[index].Position.z = (float)z;
}
}
}
void Terrain::CreateIndexData()
{
indexCount = (width - 1) * (height - 1) * 6;
indices = new UINT[indexCount];
UINT index = 0;
for (UINT y = 0; y < height - 1; y++)
{
for (UINT x = 0; x < width - 1; x++)
{
indices[index + 0] = width * y + x;
indices[index + 1] = width * (y + 1) + x;
indices[index + 2] = width * y + x + 1;
indices[index + 3] = width * y + x + 1;
indices[index + 4] = width * (y + 1) + x;
indices[index + 5] = width * (y + 1) + x + 1;
index += 6;
}
}
}
void Terrain::CreateNormalData()
{
for (UINT i = 0; i < indexCount / 3; i++)
{
UINT index0 = indices[i * 3 + 0];
UINT index1 = indices[i * 3 + 1];
UINT index2 = indices[i * 3 + 2];
TerrainVertex v0 = vertices[index0];
TerrainVertex v1 = vertices[index1];
TerrainVertex v2 = vertices[index2];
Vector3 a = v1.Position - v0.Position;
Vector3 b = v2.Position - v0.Position;
Vector3 normal;
D3DXVec3Cross(&normal, &a, &b);
vertices[index0].Normal += normal;
vertices[index1].Normal += normal;
vertices[index2].Normal += normal;
}
for (UINT i = 0; i < vertexCount; i++)
D3DXVec3Normalize(&vertices[i].Normal, &vertices[i].Normal);
}
void Terrain::CreateBuffer()
{
//Create Vertex Buffer
{
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
desc.ByteWidth = sizeof(TerrainVertex) * vertexCount;
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
D3D11_SUBRESOURCE_DATA subResource = { 0 };
subResource.pSysMem = vertices;
Check(D3D::GetDevice()->CreateBuffer(&desc, &subResource, &vertexBuffer));
}
//Create Index Buffer
{
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
desc.ByteWidth = sizeof(UINT) * indexCount;
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
D3D11_SUBRESOURCE_DATA subResource = { 0 };
subResource.pSysMem = indices;
Check(D3D::GetDevice()->CreateBuffer(&desc, &subResource, &indexBuffer));
}
}
Normal Vector
NormalVectorDemo.h
더보기
#pragma once
#include "Systems/IExecute.h"
class NormalVectorDemo : public IExecute
{
public:
virtual void Initialize() override;
virtual void Ready() override {}
virtual void Destroy() override;
virtual void Update() override;
virtual void PreRender() override {}
virtual void Render() override;
virtual void PostRender() override {}
virtual void ResizeScreen() override {}
private:
Shader* shader;
Terrain* terrain;
};
NormalVectorDemo.cpp
더보기
#include "stdafx.h"
#include "NormalVectorDemo.h"
void NormalVectorDemo::Initialize()
{
Context::Get()->GetCamera()->RotationDegree(12, 0, 0);
Context::Get()->GetCamera()->Position(35, 10, -55);
shader = new Shader(L"19_Terrain.fx");
terrain = new Terrain(shader, L"Terrain/Gray256.png");
terrain->Pass(0);
}
void NormalVectorDemo::Destroy()
{
SafeDelete(shader);
SafeDelete(terrain);
}
void NormalVectorDemo::Update()
{
terrain->Update();
}
void NormalVectorDemo::Render()
{
terrain->Render();
DebugLine::Get()->RenderLine(0, 0, 0, 0, 100, 0, 1, 0, 0); //빨간색 기준선
DebugLine::Get()->RenderLine(1, 0, 0, 5, 10, 0, 0, 1, 0); //초록색 기준선
}
DebugLine
DebugLine.h
더보기
#pragma once
#define MAX_DEBUG_LINE 150000
class DebugLine
{
public:
friend class Window;
private:
static void Create();
static void Delete();
public:
static DebugLine* Get();
public:
void RenderLine(Vector3& start, Vector3& end);
void RenderLine(Vector3& start, Vector3& end, float r, float g, float b);
void RenderLine(Vector3& start, Vector3& end, Color& color);
void RenderLine(float x, float y, float z, float x2, float y2, float z2);
void RenderLine(float x, float y, float z, float x2, float y2, float z2, float r, float g, float b);
void RenderLine(float x, float y, float z, float x2, float y2, float z2, Color& color);
private:
void Update();
void Render();
private:
DebugLine();
~DebugLine();
private:
static DebugLine* instance;
private:
Shader* shader;
Matrix world;
ID3D11Buffer* vertexBuffer;
VertexColor* vertices;
UINT drawCount = 0;
};
DebugLine.cpp
더보기
#include "Framework.h"
#include "DebugLine.h"
DebugLine* DebugLine::instance = NULL;
void DebugLine::Create()
{
assert(instance == NULL);
instance = new DebugLine();
}
void DebugLine::Delete()
{
SafeDelete(instance);
}
DebugLine * DebugLine::Get()
{
assert(instance != NULL);
return instance;
}
void DebugLine::RenderLine(Vector3 & start, Vector3 & end)
{
RenderLine(start, end, Color(0, 1, 0, 1));
}
void DebugLine::RenderLine(Vector3 & start, Vector3 & end, float r, float g, float b)
{
RenderLine(start, end, Color(r, g, b, 1));
}
void DebugLine::RenderLine(float x, float y, float z, float x2, float y2, float z2)
{
RenderLine(Vector3(x, y, z), Vector3(x2, y2, z2), Color(0, 1, 0, 1));
}
void DebugLine::RenderLine(float x, float y, float z, float x2, float y2, float z2, float r, float g, float b)
{
RenderLine(Vector3(x, y, z), Vector3(x2, y2, z2), Color(r, g, b, 1));
}
void DebugLine::RenderLine(float x, float y, float z, float x2, float y2, float z2, Color & color)
{
RenderLine(Vector3(x, y, z), Vector3(x2, y2, z2), color);
}
void DebugLine::RenderLine(Vector3 & start, Vector3 & end, Color & color)
{
vertices[drawCount].Color = color;
vertices[drawCount++].Position = start;
vertices[drawCount].Color = color;
vertices[drawCount++].Position = end;
}
void DebugLine::Update()
{
Matrix world;
D3DXMatrixIdentity(&world);
shader->AsMatrix("World")->SetMatrix(world);
shader->AsMatrix("View")->SetMatrix(Context::Get()->View());
shader->AsMatrix("Projection")->SetMatrix(Context::Get()->Projection());
}
void DebugLine::Render()
{
if (drawCount < 1) return;
D3D::GetDC()->UpdateSubresource(vertexBuffer, 0, NULL, vertices, sizeof(VertexColor) * drawCount, 0);
UINT stride = sizeof(VertexColor);
UINT offset = 0;
D3D::GetDC()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
D3D::GetDC()->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
shader->Draw(0, 0, drawCount);
drawCount = 0;
ZeroMemory(vertices, sizeof(VertexColor) * MAX_DEBUG_LINE);
}
DebugLine::DebugLine()
{
shader = new Shader(L"20_DebugLine.fx");
vertices = new VertexColor[MAX_DEBUG_LINE];
ZeroMemory(vertices, sizeof(VertexColor) * MAX_DEBUG_LINE);
//Create Vertex Buffer
{
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
desc.ByteWidth = sizeof(VertexColor) * MAX_DEBUG_LINE;
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
D3D11_SUBRESOURCE_DATA subResource = { 0 };
subResource.pSysMem = vertices;
Check(D3D::GetDevice()->CreateBuffer(&desc, &subResource, &vertexBuffer));
}
D3DXMatrixIdentity(&world);
}
DebugLine::~DebugLine()
{
SafeDelete(shader);
SafeDeleteArray(vertices);
SafeRelease(vertexBuffer);
}
Window.cpp 수정
더보기
#include "Framework.h"
#include "Window.h"
#include "IExecute.h"
IExecute* Window::mainExecute = NULL;
WPARAM Window::Run(IExecute * main)
{
mainExecute = main;
Create();
D3DDesc desc = D3D::GetDesc();
D3D::Create();
Keyboard::Create();
Mouse::Create();
Time::Create();
Time::Get()->Start();
Gui::Create();
Context::Create();
DebugLine::Create();
mainExecute->Initialize();
MSG msg = { 0 };
while (true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
MainRender();
}
}
mainExecute->Destroy();
DebugLine::Delete();
Context::Delete();
Gui::Delete();
Time::Delete();
Mouse::Delete();
Keyboard::Delete();
D3D::Delete();
Destroy();
return msg.wParam;
}
void Window::Create()
{
D3DDesc desc = D3D::GetDesc();
WNDCLASSEX wndClass;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wndClass.hIconSm = wndClass.hIcon;
wndClass.hInstance = desc.Instance;
wndClass.lpfnWndProc = (WNDPROC)WndProc;
wndClass.lpszClassName = desc.AppName.c_str();
wndClass.lpszMenuName = NULL;
wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndClass.cbSize = sizeof(WNDCLASSEX);
WORD wHr = RegisterClassEx(&wndClass);
assert(wHr != 0);
if (desc.bFullScreen == true)
{
DEVMODE devMode = { 0 };
devMode.dmSize = sizeof(DEVMODE);
devMode.dmPelsWidth = (DWORD)desc.Width;
devMode.dmPelsHeight = (DWORD)desc.Height;
devMode.dmBitsPerPel = 32;
devMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
ChangeDisplaySettings(&devMode, CDS_FULLSCREEN);
}
desc.Handle = CreateWindowEx
(
WS_EX_APPWINDOW
, desc.AppName.c_str()
, desc.AppName.c_str()
, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, (HMENU)NULL
, desc.Instance
, NULL
);
assert(desc.Handle != NULL);
D3D::SetDesc(desc);
RECT rect = { 0, 0, (LONG)desc.Width, (LONG)desc.Height };
UINT centerX = (GetSystemMetrics(SM_CXSCREEN) - (UINT)desc.Width) / 2;
UINT centerY = (GetSystemMetrics(SM_CYSCREEN) - (UINT)desc.Height) / 2;
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
MoveWindow
(
desc.Handle
, centerX, centerY
, rect.right - rect.left, rect.bottom - rect.top
, TRUE
);
ShowWindow(desc.Handle, SW_SHOWNORMAL);
SetForegroundWindow(desc.Handle);
SetFocus(desc.Handle);
ShowCursor(true);
}
void Window::Destroy()
{
D3DDesc desc = D3D::GetDesc();
if (desc.bFullScreen == true)
ChangeDisplaySettings(NULL, 0);
DestroyWindow(desc.Handle);
UnregisterClass(desc.AppName.c_str(), desc.Instance);
}
LRESULT CALLBACK Window::WndProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{
Mouse::Get()->InputProc(message, wParam, lParam);
if (Gui::Get()->MsgProc(handle, message, wParam, lParam))
return true;
if (message == WM_SIZE)
{
if (mainExecute != NULL)
{
float width = (float)LOWORD(lParam);
float height = (float)HIWORD(lParam);
if (D3D::Get() != NULL)
D3D::Get()->ResizeScreen(width, height);
if (Context::Get() != NULL)
Context::Get()->ResizeScreen();
mainExecute->ResizeScreen();
}
}
if (message == WM_CLOSE || message == WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
return DefWindowProc(handle, message, wParam, lParam);
}
void Window::MainRender()
{
Time::Get()->Update();
if (ImGui::IsMouseHoveringAnyWindow() == false)
{
Keyboard::Get()->Update();
Mouse::Get()->Update();
}
Gui::Get()->Update();
Context::Get()->Update();
DebugLine::Get()->Update();
mainExecute->Update();
mainExecute->PreRender();
D3DDesc desc = D3D::GetDesc();
D3D::Get()->SetRenderTarget();
D3D::Get()->Clear(desc.Background);
{
Context::Get()->Render();
mainExecute->Render();
DebugLine::Get()->Render();
mainExecute->PostRender();
Gui::Get()->Render();
}
D3D::Get()->Present();
}
DebugLine 부분 추가
Normal Vector 실행화면
Normal Vector
빛의 방향
'⭐ DirectX > DirectX11 3D' 카테고리의 다른 글
[DirectX11] 024 Vertical Raycast (0) | 2023.01.20 |
---|---|
[DirectX11] 023 Get Height (0) | 2023.01.20 |
[DirectX11] 019 Heightmap (0) | 2023.01.16 |
[DirectX11] 018 Texture Sampler (0) | 2023.01.16 |
[DirectX11] 017 Texture Load (0) | 2023.01.14 |
댓글
이 글 공유하기
다른 글
-
[DirectX11] 024 Vertical Raycast
[DirectX11] 024 Vertical Raycast
2023.01.20 -
[DirectX11] 023 Get Height
[DirectX11] 023 Get Height
2023.01.20 -
[DirectX11] 019 Heightmap
[DirectX11] 019 Heightmap
2023.01.16 -
[DirectX11] 018 Texture Sampler
[DirectX11] 018 Texture Sampler
2023.01.16