응애맘마조

231006 강의 본문

공부/3D강의

231006 강의

TH.Wert 2023. 10. 6. 22:37

어제에 이어서 물을 표현하는 방법에 대해 강의했습니다.

#include "Common.hlsl"

cbuffer PS_Water : register(b10)
{
	float2 dir;
	float time;
	float padding1;
}

struct VertexInput
{
	float4 Position : POSITION0;
	float2 Uv : UV0;
	float3 Normal : NORMAL0;
	float3 Tangent : TANGENT0;
	//정점변환때만 쓰이는 멤버
	float4 Indices : INDICES0;
	float4 Weights : WEIGHTS0;
};
struct PixelInput
{
	float4 Position : SV_POSITION;
	float3 wPosition : POSITION0;
	float2 Uv : UV0;
	float3 Normal : NORMAL;
	float3 Tangent : TANGENT;
	float3 Binormal : BINORMAL;
};

PixelInput VS(VertexInput input)
{
	PixelInput output;
	output.Uv = input.Uv;
	
	Matrix world;
    [flatten]
	if (input.Weights.x)
		world = SkinWorld(input.Indices, input.Weights);
	else
		world = World;
		
	output.Position = mul(input.Position, world);
	output.wPosition = output.Position.xyz;
	output.Position = mul(output.Position, ViewProj);
	output.Normal = mul(input.Normal, (float3x3) world);
	output.Tangent = mul(input.Tangent, (float3x3) world);
	output.Binormal = cross(output.Normal.xyz, output.Tangent.xyz);
    
	return output;
}

float4 PS(PixelInput input) : SV_TARGET
{
	float2 Uv = input.Uv + dir * time;
	float4 BaseColor = DiffuseMapping(Uv);
	float3 MappingNormal = NormalMapping(input.Normal, input.Tangent, input.Binormal, Uv);
	float3 Normal = normalize(input.Normal);
	float3 SpecularMap = SpecularMapping(Uv);
	float4 Result = float4(DirLighting(BaseColor.rgb, SpecularMap,
    MappingNormal, input.wPosition),
    BaseColor.a);
	
	if (Result.a > Opacity)
		Result.a = Opacity;
	
	//광원 수만큼
	//반복

	for (int i = 0; i < lights[0].Size; i++)
	{
        [flatten]
		if (!lights[i].isActive)
			continue;
        
        [flatten]
		if (lights[i].Type == 0)
		{
			Result.rgb += PointLighting(BaseColor.rgb, SpecularMap,
			MappingNormal, input.wPosition, i);
		}
		else if (lights[i].Type == 1)
		{
			Result.rgb += SpotLighting(BaseColor.rgb, SpecularMap,
            MappingNormal, input.wPosition, i);
		}
	}
	
	//발광
	//Ambient
	Result.rgb += Ka.rgb * BaseColor.rgb;
    //Emissive
	Result.rgb += EmissiveMapping(BaseColor.rgb, Uv, MappingNormal, input.wPosition);
	//Environment
	
	float3 Envi;
	[flatten]
	if (environment != 0.0f)
	{
		float3 ViewDir = normalize(input.wPosition - ViewPos.xyz);
		float3 reflection = reflect(ViewDir, Normal);
		float3 normal = TextureN.Sample(SamplerN, Uv).rgb;
		normal = normal * 2.0f - 1.0f;
		reflection.xyz += MappingNormal * 0.01f;
		reflection = normalize(reflection);
		Envi = TextureBG.Sample(SamplerBG, reflection.xyz) * environment;
	}
	else
	{
		Envi = float3(0, 0, 0);
	}
	Result.rgb += Envi;
	BaseColor = Result;

	return BaseColor;

}

원래는 기존에 있던 쉐이더 코드에서 사용하려고 했는데 따로 하나를 만들어서 사용하게 되었습니다.

envi = new Environment(1024, 1024);

어제 실행 시 반사되는 부분이 화질이 떨어져서 나타나는 현상은 환경매핑 시 1024 픽셀로 높였습니다.

#pragma once

class Scene2 : public Scene
{
private:

	Sky*		sky;
	Grid*		grid;
	Camera*		cam;
	Terrain*	terrain;
    
	Actor*		actor;
	Actor*		water;

	struct WaterBuffer
	{
		Vector2 dir;
		float time;
		float padding;
	}waterBufferDesc;

	Environment* envi;
	ID3D11Buffer* waterBuffer;

public:
	Scene2();
	~Scene2();
	virtual void Init() override;
	virtual void Release() override;
	virtual void Update() override;
	virtual void LateUpdate() override;
	virtual void Render() override;
	virtual void PreRender() override;
	virtual void ResizeScreen() override;
};
#include "stdafx.h"
#include "Scene2.h"

Scene2::Scene2()
{
}

Scene2::~Scene2()
{
}

void Scene2::Init()
{
    grid =  Grid::Create();
    sky = Sky::Create();

   cam = Camera::Create();
   cam->LoadFile("Cam.xml");
   Camera::main = cam;

   actor = Actor::Create();
   actor->LoadFile("test.xml");

   terrain = Terrain::Create();
   terrain->LoadFile("Terrain.xml");

   water = Actor::Create();
   water->LoadFile("water.xml");

   envi = new Environment(1024,1024);
   RESOURCE->shaders.Load("0.SkyCubeMap.hlsl")->LoadGeometry();
   RESOURCE->shaders.Load("4.CubeMap.hlsl")->LoadGeometry();
   RESOURCE->shaders.Load("5.CubeMap.hlsl")->LoadGeometry();

   {
       D3D11_BUFFER_DESC desc = { 0 };
       desc.ByteWidth = sizeof(WaterBuffer);
       desc.Usage = D3D11_USAGE_DYNAMIC;
       desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;//상수버퍼
       desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
       desc.MiscFlags = 0;
       desc.StructureByteStride = 0;
       HRESULT hr = D3D->GetDevice()->CreateBuffer(&desc, NULL, &waterBuffer);
       assert(SUCCEEDED(hr));
   }
}

void Scene2::Release()
{
}

void Scene2::Update()
{
    Camera::main->width = App.GetWidth();
    Camera::main->height = App.GetHeight();
    Camera::main->viewport.width = App.GetWidth();
    Camera::main->viewport.height = App.GetHeight();

    Camera::main->Update();
    Camera::ControlMainCam();

    //debug
    ImGui::Text("FPS: %d", TIMER->GetFramePerSecond());
    ImGui::SliderFloat(" App.deltaScale", &App.deltaScale,0.0f,10.0f);
    LIGHT->RenderDetail();

    //Hierarchy
    ImGui::Begin("Hierarchy");
    grid->RenderHierarchy();
    sky->RenderHierarchy();
    cam->RenderHierarchy();
    actor->RenderHierarchy();
    terrain->RenderHierarchy();
    water->RenderHierarchy();
   
    ImGui::End();
   
    grid->Update();
    sky->Update();
    actor->Update();
    terrain->Update();
    water->Update();
}

void Scene2::LateUpdate()
{
}

void Scene2::Render()
{
    Camera::main->Set();
    LIGHT->Set();

    grid->Render();
    sky->Render();
    actor->Render();
    terrain->Render();
    envi->SetRGBTexture(4);
    {
        waterBufferDesc.time = TIMER->GetWorldTime() / 5.0f;
        waterBufferDesc.dir = Vector2(-1, -1);

        //상수버퍼
        D3D11_MAPPED_SUBRESOURCE mappedResource;
        D3D->GetDC()->Map(waterBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
        memcpy_s(mappedResource.pData, sizeof(WaterBuffer), &waterBufferDesc, sizeof(WaterBuffer));
        D3D->GetDC()->Unmap(waterBuffer, 0);

        D3D->GetDC()->PSSetConstantBuffers(10, 1, &waterBuffer);
    }
    water->Render();
}

void Scene2::PreRender()
{
    Camera::main->Set();
    LIGHT->Set();
    
    {
        Vector3 Dir = water->GetWorldPos() - Camera::main->GetWorldPos();
        float Distance = Dir.Length();
        Dir.Normalize();
        Vector3 reflect = Vector3::Reflect(Dir, water->GetUp());
        envi->position = (water->GetWorldPos() - reflect * Distance);

    }
    envi->SetTarget(Color(0, 0, 0, 1));
    sky->Render(RESOURCE->shaders.Load("0.SkyCubeMap.hlsl"));
    actor->Render(RESOURCE->shaders.Load("4.CubeMap.hlsl"));
    terrain->Render(RESOURCE->shaders.Load("5.CubeMap.hlsl"));
}

void Scene2::ResizeScreen()
{
    Camera::main->width = App.GetWidth();
    Camera::main->height = App.GetHeight();
    Camera::main->viewport.width = App.GetWidth();
    Camera::main->viewport.height = App.GetHeight();
}

메인에서 실행한 코드입니다. 상수버퍼를 만들어서 물이 흐르는 것처럼 움직일 수 있도록 따로 만들었습니다.

waterBufferDesc.dir = Vector2(-1, -1);

만약 물이 흐르는 방향을 바꾸고 싶으면 위의 코드의 벡터 값을 변경하면 됩니다.

물이 흐르는 표현

읽어주셔서 감사합니다.

'공부 > 3D강의' 카테고리의 다른 글

231011 강의  (0) 2023.10.11
231010 강의  (0) 2023.10.11
231005 강의  (0) 2023.10.05
231004 강의  (0) 2023.10.05
230525 ~ 230526 강의  (0) 2023.09.26
Comments