목차

     

     


     

     

    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

     

    [DirectX 12] 렌더링 파이프라인 - 2

    입력 조립기 단계(Input Assembler, IA) 입력 조립기 단계는 메모리에서 기하 자료(정점, 인덱스)를 읽어서 기본 도형(삼각형, 선분 등)을 조립한다. 정점(Vertex) 수학적으로, 한 삼각형의 정점은 두 변

    lipcoder.tistory.com

     

    https://designerd.tistory.com/entry/DirectX12-Matrix

     

    [게임수학] Matrix 행렬

    Matrix 행렬 행렬 곱셈 (앞 행렬의 행의 수) × (뒤 행렬의 열의 수) 즉, 앞 행렬이 m×n 크기이고 뒤 행렬이 n×r 크기인 경우 곱은 m×r 크기의 행렬이 된다. 행렬은 교환법칙 성립X, 결합법칙 성립O Digon

    designerd.tistory.com


     

     

     

    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