• 티스토리 홈
  • 프로필사진
    유니얼
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
유니얼
  • 프로필사진
    유니얼
    • 분류 전체보기 (295)
      • Unity (17)
        • 게임 개발 (5)
      • Unreal (24)
        • 게임 개발 (20)
      • DirectX (36)
      • 코딩테스트 (91)
        • 프로그래머스 (25)
        • 백준 (66)
      • Google Workspace (1)
      • Programing (102)
        • C# (68)
        • C++ (24)
        • JavaScript (10)
      • 게임 서버 프로그래밍 (17)
      • Web (6)
        • 슈퍼코딩 (6)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
    등록된 댓글이 없습니다.
  • 최근 공지
    등록된 공지가 없습니다.
# Home
# 공지사항
#
# 태그
# 검색결과
# 방명록
  • [DirectX11] Normal Mapping
    2024년 03월 06일
    • 유니얼
    • 작성자
    • 2024.03.06.:56
    728x90

    DirectX 11로 게임 엔진 아키텍처 만들기

    게임 개발과 3D 그래픽스를 공부하는 과정에서, 우리는 다양한 시각적 기법을 통해 장면의 실감나는 표현을 추구합니다. 이 중 Normal Mapping은 3D 모델의 디테일을 향상시키면서도 성능을 최적화하는 효과적인 방법 중 하나입니다.

     

    Result

    참고강의 링크:

    https://www.inflearn.com/course/directx11-%EA%B2%8C%EC%9E%84%EA%B0%9C%EB%B0%9C-%EB%8F%84%EC%95%BD%EB%B0%98/dashboard

     

    [게임 프로그래머 도약반] DirectX11 입문 강의 - 인프런

    게임 프로그래머 공부에 있어서 필수적인 DirectX 11 지식을 초보자들의 눈높이에 맞춰 설명하는 강의입니다., [사진][사진] [사진] 게임 개발자는 Unreal, Unity만 사용할 줄 알면 되는 거 아닌가요? 엔

    www.inflearn.com

    Normal Mapping이란?

    Normal Mapping은 3D 모델의 표면 디테일을 높이기 위해 사용되는 기법입니다. 모델의 각 픽셀에 대한 노멀(표면의 방향) 정보를 텍스처로 저장하고, 이를 렌더링 시에 활용하여 빛의 반사를 계산합니다. 이 방법은 모델에 추가적인 다각형을 추가하지 않고도, 높은 디테일을 가진 표면을 시뮬레이션할 수 있게 해줍니다.

    기본 원리

    • 노멀 맵: RGB 이미지로, 각 채널은 각각의 방향(X, Y, Z)에 대한 노멀 벡터의 값을 가집니다. 이 값들은 표면의 방향 변화를 나타냅니다.
    • 렌더링 과정: 렌더링 시, 노멀 맵에서 추출한 노멀 벡터를 사용하여 빛의 반사를 계산합니다. 이는 표면의 미세한 높낮이 차이를 고려하여, 더욱 리얼리틱한 조명 효과를 생성합니다.

    Normal Mapping의 장점

    • 디테일 향상: 고해상도의 노멀 맵을 사용함으로써, 모델의 디테일을 크게 향상시킬 수 있습니다.
    • 성능 최적화: 추가적인 지오메트리를 사용하지 않으므로, 렌더링 성능에 미치는 영향이 적습니다.
    • 다양한 사용 사례: 거친 표면, 직물의 질감, 벽돌 벽과 같은 다양한 재질의 표현에 사용될 수 있습니다.

    NormalMapping

    #include "00. Global.fx" 
    #include "00. Light.fx"
    
    // 정점 쉐이더: 입력 정점을 처리하여 출력 정점을 생성합니다.
    MeshOutput VS(VertexTextureNormalTangent input)
    {
    	MeshOutput output; // 출력 정점 구조체
    	output.position = mul(input.position, W); // 정점 위치를 월드 좌표로 변환
    	output.worldPosition = input.position.xyz; // 월드 좌표로의 변환을 저장 (추후 조명 계산에 사용)
    	output.position = mul(output.position, VP);	// 뷰-프로젝션 행렬을 적용하여 최종적인 스크린 좌표를 계산
    	output.uv = input.uv; // 텍스처 좌표는 직접 전달
    	output.normal = mul(input.normal, (float3x3)W); // 정점의 법선 벡터를 월드 좌표로 변환
    	output.tangent = mul(input.tangent, (float3x3)W); // 정점의 탄젠트 벡터를 월드 좌표로 변환
    
    	return output; // 변환된 정점 데이터를 반환
    }
    
    // 픽셀 쉐이더: 변환된 정점 데이터를 기반으로 최종 픽셀 색상을 계산합니다.
    float4 PS(MeshOutput input) : SV_TARGET
    {
    	ComputeNormalMapping(input.normal, input.tangent, input.uv); // 정규 매핑을 계산하여 법선 벡터를 수정
    
    	float4 color = ComputeLight(input.normal, input.uv, input.worldPosition); // 수정된 법선과 다른 입력을 기반으로 조명을 계산
    
    	return color; // 최종 색상 반환
    }
    
    // 렌더링 기법 정의: 하나의 패스를 사용하여 정점 쉐이더와 픽셀 쉐이더를 지정
    technique11 T0
    {
    	PASS_VP(P0, VS, PS)
    };

    프로젝트 호출

    NormalMappingDemo.h

    #pragma once
    #include "IExecute.h"
    #include "Geometry.h"
    
    class NormalMappingDemo : public IExecute
    {
    public:
    	void Init() override;
    	void Update() override;
    	void Render() override;
    
    	shared_ptr<Shader> _shader;
    
    	shared_ptr<GameObject> _obj;
    	shared_ptr<GameObject> _obj2;
    	shared_ptr<GameObject> _camera;
    };

    NormalMappingDemo.cpp

    #include "pch.h"
    #include "18. NormalMappingDemo.h"
    #include "GeometryHelper.h"
    #include "Camera.h"
    #include "CameraScript.h"
    #include "Transform.h"
    #include "Texture.h"
    #include "ResourceBase.h"
    #include "MeshRenderer.h"
    #include "GameObject.h"
    //#include "RenderManager.h"
    #include "Material.h"
    
    void NormalMappingDemo::Init()
    {
    	RESOURCES->Init();
    	_shader = make_shared<Shader>(L"14. NormalMapping.fx");
    
    	//Material
    	{
    		shared_ptr<Material> material = make_shared<Material>();
    		{
    			material->SetShader(_shader);
    		} 
    		{
    			auto texture = RESOURCES->Load<Texture>(L"Leather", L"..\\Resources\\Texture\\Leather.jpg");
    			material->SetDiffuseMap(texture);
    		}
    		{
    			auto texture = RESOURCES->Load<Texture>(L"LeatherNormal", L"..\\Resources\\Texture\\Leather_Normal.jpg");
    			material->SetNormalMap(texture);
    		}
    
    		MaterialDesc& desc = material->GetMaterialDesc();
    		desc.ambient = Vec4(1.0f);
    		desc.diffuse = Vec4(1.0f);
    		desc.specular = Vec4(1.0f);
    		desc.emissive = Vec4(1.0f);
    
    		RESOURCES->Add(L"Leather", material);
    	}
    
    	// Camera
    	_camera = make_shared<GameObject>();
    	_camera->GetOrAddTransform()->SetWorldPosition(Vec3{ 0.f, 0.f, -10.f });
    	_camera->AddComponent(make_shared<Camera>());
    	_camera->AddComponent(make_shared<CameraScript>());
    
    	// Object
    	_obj = make_shared<GameObject>();
    	_obj->GetOrAddTransform();
    	_obj->AddComponent(make_shared<MeshRenderer>());
    	{
    		auto mesh = RESOURCES->Get<Mesh>(L"Sphere");
    		_obj->GetMeshRenderer()->SetMesh(mesh);
    	}
    	{
    		auto material = RESOURCES->Get<Material>(L"Leather");
    		_obj->GetMeshRenderer()->SetMaterial(material);
    	}
    
    	// Object2
    	_obj2 = make_shared<GameObject>();
    	_obj2->GetOrAddTransform()->SetWorldPosition(Vec3{ 0.5f, 0.f, 2.f });
    	_obj2->AddComponent(make_shared<MeshRenderer>());
    	{
    		auto mesh = RESOURCES->Get<Mesh>(L"Cube");
    		_obj2->GetMeshRenderer()->SetMesh(mesh);
    	}
    	{
    		auto material = RESOURCES->Get<Material>(L"Leather");
    		MaterialDesc& desc = material->GetMaterialDesc();
    
    		_obj2->GetMeshRenderer()->SetMaterial(material);
    	}
    
    	// Object
    	//RENDER->Init(_shader);
    }
    
    void NormalMappingDemo::Update()
    {
    	_camera->Update();
    	//RENDER->Update();
    	{
    		LightDesc lightDesc;
    		lightDesc.ambient = Vec4(0.f);
    		lightDesc.diffuse = Vec4(0.f);
    		lightDesc.specular = Vec4(0.f);
    		lightDesc.emissive = Vec4(1.f,0.0f,0.0f,1.0f);
    		lightDesc.direction = Vec3(1.f,0.0f,1.0f);
    		//RENDER->PushLightData(lightDesc);
    
    	}
    	{
    		MaterialDesc desc;
    		desc.ambient = Vec4(0.2f);
    		desc.diffuse = Vec4(1.0f);
    		desc.specular = Vec4(1.0f);
    		desc.emissive = Color(0.3f,0.f,0.f,0.5f);
    
    		//RENDER->PushMaterialData(desc);
    		_obj->Update();
    	}
    	{
    		MaterialDesc desc;
    		desc.ambient = Vec4(0.1f);
    		desc.diffuse = Vec4(1.0f);
    		//desc.specular = Vec4(1.0f);
    
    		//RENDER->PushMaterialData(desc);
    		_obj2->Update();
    	}
    }
    
    void NormalMappingDemo::Render()
    {
    
    }

    결론

    Normal Mapping은 DirectX11 게임 개발과 3D 그래픽스에서 중요한 기법 중 하나입니다. 이를 통해, 개발자와 아티스트는 성능 부담을 크게 늘리지 않으면서도, 높은 수준의 시각적 디테일을 달성할 수 있습니다. 

    반응형
    다음글
    다음 글이 없습니다.
    이전글
    이전 글이 없습니다.
    댓글
조회된 결과가 없습니다.
스킨 업데이트 안내
현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
목차
표시할 목차가 없습니다.
    • 안녕하세요
    • 감사해요
    • 잘있어요

    티스토리툴바