전반적으로 DirectX11에서 기상 시스템을 생성하려면 예술적 비전과 기술의 조합이 필요하며 시뮬레이션하려는 기상 시스템의 물리 및 역학에 대한 깊은 이해가 필요하다. 올바른 도구와 전문 지식을 사용하면 멀티미디어 응용 프로그램의 전반적인 경험을 향상시킬 수 있는 매우 사실적이고 몰입감 있는 날씨 효과를 만들 수 있다.

 

목차

     


     

     

     

    Weather

     

    DirectX11에서 날씨 시스템을 생성하기 위한 첫 번째 단계는 시스템의 물리를 정의하는 것이다. 예를 들어 비를 시뮬레이트하려면 파티클의 속도와 방향, 떨어지는 속도, 환경과 상호 작용하는 방식(예: 표면에 튀거나 바람에 날리는 것)을 정의해야 한다.

    날씨 시스템의 물리학을 정의한 후에는 DirectX11을 사용하여 시각 효과를 만들 수 있다. 여기에는 일반적으로 비, 눈 또는 기타 대기 효과에 대한 입자 시스템 생성과 텍스처를 사용하여 구름 덮개 또는 기타 대규모 날씨 패턴을 생성하는 작업이 포함된다.

    DirectX11은 입자 크기, 모양 및 색상을 제어하는 ​​기능은 물론 입자가 서로 및 환경과 상호 작용하는 방식을 포함하여 입자 시스템을 만들고 애니메이션화하기 위한 다양한 도구를 제공한다. 또한 텍스처 해상도, 압축 및 필터링을 제어하는 ​​기능을 포함하여 텍스처를 만들고 조작하기 위한 다양한 도구를 제공한다.

     

     

     

    Shaders
      Global.fx
    Rain.fx 생성
    Snow.fx 생성
    Framework
      Environment
      Rain.h .cpp 생성
    Snow.h .cpp 생성
    UnitTest
      Terrain
      WeatherDemo.h. cpp 생성

     


     

    Global.fx

     

    Global.fx - 코드 추가

    더보기
    BlendState OpaqueBlend
    {
        BlendEnable[0] = true;
        SrcBlend[0] = One;
        DestBlend[0] = Zero;
        BlendOp[0] = ADD;
        
        SrcBlendAlpha[0] = One;
        DestBlendAlpha[0] = Zero;
        BlendOpAlpha[0] = Add;
        
        RenderTargetWriteMask[0] = 15; //Ox0F
    };
    
    BlendState AlphaBlend
    {
        AlphaToCoverageEnable = false;
        
        BlendEnable[0] = true;
        SrcBlend[0] = SRC_ALPHA;
        DestBlend[0] = INV_SRC_ALPHA;
        BlendOp[0] = ADD;
        
        SrcBlendAlpha[0] = One;
        DestBlendAlpha[0] = Zero;
        BlendOpAlpha[0] = Add;
        
        RenderTargetWriteMask[0] = 15; //Ox0F
    };
    
    BlendState AlphaBlend_AlphaToCoverageEnable
    {
        AlphaToCoverageEnable = true;
        
        BlendEnable[0] = true;
        SrcBlend[0] = SRC_ALPHA;
        DestBlend[0] = INV_SRC_ALPHA;
        BlendOp[0] = ADD;
        
        SrcBlendAlpha[0] = One;
        DestBlendAlpha[0] = Zero;
        BlendOpAlpha[0] = Add;
        
        RenderTargetWriteMask[0] = 15; //Ox0F
    };
    
    BlendState AdditiveBlend
    {
        AlphaToCoverageEnable = false;
        
        BlendEnable[0] = true;
        SrcBlend[0] = One;
        DestBlend[0] = One;
        BlendOp[0] = ADD;
        
        SrcBlendAlpha[0] = One;
        DestBlendAlpha[0] = Zero;
        BlendOpAlpha[0] = Add;
        
        RenderTargetWriteMask[0] = 15; //Ox0F
    };
    
    BlendState AdditiveBlend_Particle
    {
        AlphaToCoverageEnable = false;
        
        BlendEnable[0] = true;
        SrcBlend[0] = SRC_ALPHA;
        DestBlend[0] = One;
        BlendOp[0] = ADD;
        
        SrcBlendAlpha[0] = One;
        DestBlendAlpha[0] = Zero;
        BlendOpAlpha[0] = Add;
        
        RenderTargetWriteMask[0] = 15; //Ox0F
    };
    
    BlendState AdditiveBlend_AlphaToCoverageEnable
    {
        AlphaToCoverageEnable = true;
        
        BlendEnable[0] = true;
        SrcBlend[0] = One;
        DestBlend[0] = One;
        BlendOp[0] = ADD;
        
        SrcBlendAlpha[0] = One;
        DestBlendAlpha[0] = Zero;
        BlendOpAlpha[0] = Add;
        
        RenderTargetWriteMask[0] = 15; //Ox0F
    };
    
    DepthStencilState DepthRead_Particle
    {
        DepthEnable = true;
        DepthFunc = Less_Equal;
        DepthWriteMask = 0;
    };

    코드 추가

    • BlendState AlphaBlend
    • BlendState AlphaBlend_AlphaToCoverageEnable
    • BlendState AdditiveBlend
      • 색을 더 진하게 만드는 효과
    • BlendState AdditiveBlend_AlphaToCoverageEnable

     

     

    SRC = SRC-Alpha

    Dest = Inv  SRC-Alpha

     

    (SrcColor * SRC) + (DestColor * Dest) = 뒷색과 자신의 색이 섞인다.

     

    Alpha Blending을 그릴 때는 불투명을 먼저 그린다. 그 후에 반투명을 그린다.

     


     

     

    Rain.fx

     

    Rain.fx

    더보기
    #include "00_Global.fx"
    #include "00_Light.fx"
    
    cbuffer CB_Rain
    {
        float4 Color;
    
        float3 Velocity;
        float DrawDistance;
    
        float3 Origin;
        float CB_Rain_Padding;
    
        float3 Extent;
    };
    
    struct VertexInput
    {
        float4 Position : Position;
        float2 Uv : Uv;
        float2 Scale : Scale;
    };
    
    struct VertexOutput
    {
        float4 Position : SV_Position;
        float2 Uv : Uv;
        float Alpha : Alpha;
    };
    
    VertexOutput VS(VertexInput input)
    {
        VertexOutput output;
        
        float3 displace = Velocity;
        displace.xz /= input.Scale.y * 0.1f; //xz은 시간에 따라 증가. input.Scale.y로 나누어서 비 크기만큼 비례해서 속도를 늦추어 준다.
        displace *= Time;
    
        //Origin(=공간의 이동)에서 Extent 범위 내에서의 순환값
        input.Position.xyz = Origin + (Extent + (input.Position.xyz + displace) % Extent) % Extent - (Extent * 0.5f); 
    
        float4 position = WorldPosition(input.Position);
        
        float3 up = normalize(-Velocity);
        float3 forward = position.xyz - ViewPosition();
        float3 right = normalize(cross(up, forward));
        
        position.xyz += (input.Uv.x - 0.5f) * right * input.Scale.x;
        position.xyz += (1.0f - input.Uv.y - 0.5f) * up * input.Scale.y;
        position.w = 1.0f;
        
        output.Position = ViewProjection(position);
        output.Uv = input.Uv;
        
        float4 view = mul(position, View);
        output.Alpha = saturate(1 - view.z / DrawDistance) * 0.5f;
    
        return output;
    }
    
    //float4 PS_Discard(VertexOutput input) : SV_Target
    //{
    //    float4 diffuse = DiffuseMap.Sample(LinearSampler, input.Uv);
        
    //    if (diffuse.a < 0.3)
    //        discard;
        
    //    return diffuse;
    //}
    
    float4 PS(VertexOutput input) : SV_Target
    {
        float4 diffuse = DiffuseMap.Sample(LinearSampler, input.Uv);
        
        diffuse.rgb = Color.rgb * input.Alpha * 2.0f; //rgb값 반영
        diffuse.a = diffuse.a * input.Alpha * 1.5f; //alpha값 반영
        
        return diffuse;
    }
    
    technique11 T0
    {
        P_BS_VP(P0, AlphaBlend, VS, PS) //Global.fx 사용
        P_BS_VP(P1, AlphaBlend_AlphaToCoverageEnable, VS, PS)
    
        P_BS_VP(P2, AdditiveBlend, VS, PS)
        P_BS_VP(P3, AdditiveBlend_AlphaToCoverageEnable, VS, PS)
    
        //P_VP(P0, VS, PS_Discard)
    }

     

    핵심코

    VertexOutput VS(VertexInput input)
    {
        VertexOutput output;
        
        float3 displace = Velocity;
        displace.xz /= input.Scale.y * 0.1f; //xz은 시간에 따라 증가. input.Scale.y로 나누어서 비 크기만큼 비례해서 속도를 늦추어 준다.
        displace *= Time;
    
        //Origin(=공간의 이동)에서 Extent 범위 내에서의 순환값
        input.Position.xyz = Origin + (Extent + (input.Position.xyz + displace) % Extent) % Extent - (Extent * 0.5f); 
    
        float4 position = WorldPosition(input.Position);
        
        float3 up = normalize(-Velocity);
        float3 forward = position.xyz - ViewPosition();
        float3 right = normalize(cross(up, forward));
        
        position.xyz += (input.Uv.x - 0.5f) * right * input.Scale.x;
        position.xyz += (1.0f - input.Uv.y - 0.5f) * up * input.Scale.y;
        position.w = 1.0f;
        
        output.Position = ViewProjection(position);
        output.Uv = input.Uv;
        
        float4 view = mul(position, View);
        output.Alpha = saturate(1 - view.z / DrawDistance) * 0.5f;
    
        return output;
    }

     


     

    Snow.fx

     

    Snow.fx

    더보기
    #include "00_Global.fx"
    #include "00_Light.fx"
    
    cbuffer CB_Snow
    {
        float4 Color;
    
        float3 Velocity;
        float DrawDistance;
    
        float3 Origin;
        float Turblence; //눈이 바람에 의해서 흔들리는 정도
    
        float3 Extent;
    };
    
    struct VertexInput
    {
        float4 Position : Position;
        float2 Uv : Uv;
        float Scale : Scale;
        float2 Random : Random; //눈이 바람에 흔들리는 값 랜덤으로 처리하기 위한 변수
    };
    
    struct VertexOutput
    {
        float4 Position : SV_Position;
        float2 Uv : Uv;
        float Alpha : Alpha;
    };
    
    VertexOutput VS(VertexInput input)
    {
        VertexOutput output;
        
        float3 displace = Velocity * Time; //시간에 따라 속도가 증가되게 설정
        
        input.Position.y = Origin.y + Extent.y - (input.Position.y - displace.y) % Extent.y;
        input.Position.x += cos(Time - input.Random.x) * Turblence;
        input.Position.z += cos(Time - input.Random.y) * Turblence;
        
        input.Position.xyz = Origin + (Extent + (input.Position.xyz + displace) % Extent) % Extent - (Extent * 0.5f);
        
        
        float4 position = WorldPosition(input.Position);
        
        float3 up = normalize(-Velocity);
        float3 forward = position.xyz - ViewPosition();
        float3 right = normalize(cross(up, forward));
        
        position.xyz += (input.Uv.x - 0.5f) * right * input.Scale;
        position.xyz += (1.0f - input.Uv.y - 0.5f) * up * input.Scale;
        position.w = 1.0f;
        
        output.Position = ViewProjection(position);
        output.Uv = input.Uv;
        
        float4 view = mul(position, View);
        output.Alpha = saturate(1 - view.z / DrawDistance) * 0.5f;
    
        return output;
    }
    
    float4 PS(VertexOutput input) : SV_Target
    {
        float4 diffuse = DiffuseMap.Sample(LinearSampler, input.Uv);
        
        diffuse.rgb = Color.rgb * input.Alpha * 2.0f;
        diffuse.a = diffuse.a * input.Alpha * 1.5f;
        
        return diffuse;
    }
    
    technique11 T0
    {
        P_BS_VP(P0, AlphaBlend, VS, PS)
        P_BS_VP(P1, AlphaBlend_AlphaToCoverageEnable, VS, PS)
    
        P_BS_VP(P2, AdditiveBlend, VS, PS)
        P_BS_VP(P3, AdditiveBlend_AlphaToCoverageEnable, VS, PS)
    }

     

     


     

     

    Rain

     

    Rain.h

    더보기
    #pragma once
    
    class Rain : public Renderer
    {
    public:
    	Rain(Vector3& extent, UINT count, wstring file);//비가 내릴 구역의 부피, 정점이 그려질 개수, 비의 texture 파일
    	~Rain();
    
    	void Update();
    	void Render();
    
    private:
    	struct Desc
    	{
    		D3DXCOLOR Color = D3DXCOLOR(1, 1, 1, 1); //비 색깔
    
    		Vector3 Velocity = Vector3(-10, -100, 0); //비 방향
    		float DrawDistance = 0; //비의 그려질 거리
    
    		Vector3 Origin = Vector3(0, 0, 0); //비의 중심점
    		float Padding;
    
    		Vector3 Extent = Vector3(0, 0, 0); //비가 내릴 구역의 부피
    		float Padding2;
    	} desc;
    
    private:
    	struct VertexRain
    	{
    		Vector3 Position;
    		Vector2 Uv;
    		Vector2 Scale;
    	};
    
    private:
    	ConstantBuffer* buffer;
    	ID3DX11EffectConstantBuffer* sBuffer;
    
    	VertexRain* vertices;
    	UINT* indices;
    
    	Texture* texture;
    	UINT drawCount = 100;
    };

     

     

    Rain.cpp

    더보기
    #include "Framework.h"
    #include "Rain.h"
    
    Rain::Rain(Vector3 & extent, UINT count, wstring file)
    	: Renderer(L"85_Rain.fxo"), drawCount(count)
    {
    	desc.Extent = extent;
    	desc.DrawDistance = desc.Extent.z * 2.0f;
    
    	texture = new Texture(file);
    	shader->AsSRV("DiffuseMap")->SetResource(texture->SRV());
    
    	buffer = new ConstantBuffer(&desc, sizeof(Desc));
    	sBuffer = shader->AsConstantBuffer("CB_Rain");
    
    
    	vertices = new VertexRain[drawCount * 4]; //정점 개수
    	for (UINT i = 0; i < drawCount * 4; i += 4) //i += 4로 만들어 i를 4씩 증가
    	{
    		Vector2 scale;
    		scale.x = Math::Random(0.1f, 0.4f);
    		scale.y = Math::Random(2.0f, 6.0f);
    
    		Vector3 position;
    		position.x = Math::Random(-desc.Extent.x, desc.Extent.x);
    		position.y = Math::Random(-desc.Extent.y, desc.Extent.y);
    		position.z = Math::Random(-desc.Extent.z, desc.Extent.z);
    
    		
    		vertices[i + 0].Position = position;
    		vertices[i + 1].Position = position;
    		vertices[i + 2].Position = position;
    		vertices[i + 3].Position = position;
    
    		vertices[i + 0].Uv = Vector2(0, 1);
    		vertices[i + 1].Uv = Vector2(0, 0);
    		vertices[i + 2].Uv = Vector2(1, 1);
    		vertices[i + 3].Uv = Vector2(1, 0);
    
    		vertices[i + 0].Scale = scale;
    		vertices[i + 1].Scale = scale;
    		vertices[i + 2].Scale = scale;
    		vertices[i + 3].Scale = scale;
    	}
    
    	indices = new UINT[drawCount * 6];
    	for (UINT i = 0; i < drawCount; i++)
    	{
    		indices[i * 6 + 0] = i * 4 + 0;
    		indices[i * 6 + 1] = i * 4 + 1;
    		indices[i * 6 + 2] = i * 4 + 2;
    		indices[i * 6 + 3] = i * 4 + 2;
    		indices[i * 6 + 4] = i * 4 + 1;
    		indices[i * 6 + 5] = i * 4 + 3;
    	}
    
    	vertexBuffer = new VertexBuffer(vertices, drawCount * 4, sizeof(VertexRain));
    	indexBuffer = new IndexBuffer(indices, drawCount * 6);
    
    	//ID3D11BlendState
    	//D3D11_BLEND_DESC;
    }
    
    Rain::~Rain()
    {
    	SafeDelete(buffer);
    
    	SafeDeleteArray(vertices);
    	SafeDeleteArray(indices);
    
    	SafeDelete(texture);
    }
    
    void Rain::Update()
    {
    	Super::Update();
    
    	Context::Get()->GetCamera()->Position(&desc.Origin);
    	//ImGui::SliderFloat3("Origin", desc.Origin, 0, 200); //원점
    
    	ImGui::SliderFloat3("Velocity", desc.Velocity, -200, 200); //속도
    	ImGui::ColorEdit3("Color", desc.Color); //색상
    	ImGui::SliderFloat("Distance", &desc.DrawDistance, 0, desc.Extent.z * 2.0f); //거리
    }
    
    void Rain::Render()
    {
    	Super::Render();
    
    	buffer->Render();
    	sBuffer->SetConstantBuffer(buffer->Buffer());
    
    
    	static UINT pass = 0;
    	ImGui::InputInt("Rain Pass", (int *)&pass);
    	pass %= 4;
    	
    	shader->DrawIndexed(0, pass, drawCount * 6); //부모 pass 사용
    }

     

     

     


     

     

    Snow

     

    Snow.h

    더보기
    #pragma once
    
    class Snow : public Renderer
    {
    public:
    	Snow(Vector3& extent, UINT count, wstring file);
    	~Snow();
    
    	void Update();
    	void Render();
    
    private:
    	struct Desc
    	{
    		D3DXCOLOR Color = D3DXCOLOR(1, 1, 1, 1);
    
    		Vector3 Velocity = Vector3(0, -5, 0);
    		float DrawDistance = 0;
    
    		Vector3 Origin = Vector3(0, 0, 0);
    		float Turbulence = 5; //눈이 바람에 의해서 흔들리는 정도
    
    		Vector3 Extent = Vector3(0, 0, 0);
    		float Padding2;
    	} desc;
    
    private:
    	struct VertexSnow
    	{
    		Vector3 Position;
    		Vector2 Uv;
    		float Scale;
    		Vector2 Random;
    	};
    
    private:
    	ConstantBuffer* buffer;
    	ID3DX11EffectConstantBuffer* sBuffer;
    
    	VertexSnow* vertices;
    	UINT* indices;
    
    	Texture* texture;
    	UINT drawCount = 100;
    };

     

     

    Snow.cpp

    더보기
    #include "Framework.h"
    #include "Snow.h"
    
    Snow::Snow(Vector3 & extent, UINT count, wstring file)
    	: Renderer(L"85_Snow.fxo"), drawCount(count)
    {
    	desc.Extent = extent;
    	desc.DrawDistance = desc.Extent.z * 2.0f;
    
    	texture = new Texture(file);
    	shader->AsSRV("DiffuseMap")->SetResource(texture->SRV());
    
    	buffer = new ConstantBuffer(&desc, sizeof(Desc));
    	sBuffer = shader->AsConstantBuffer("CB_Snow");
    
    
    	vertices = new VertexSnow[drawCount * 4];
    	for (UINT i = 0; i < drawCount * 4; i += 4)
    	{
    		float scale;
    		scale = Math::Random(0.1f, 0.4f);
    
    		Vector3 position;
    		position.x = Math::Random(-desc.Extent.x, desc.Extent.x);
    		position.y = Math::Random(-desc.Extent.y, desc.Extent.y);
    		position.z = Math::Random(-desc.Extent.z, desc.Extent.z);
    
    		Vector2 random = Math::RandomVec2(0.0f, 1.0f);
    
    		
    		vertices[i + 0].Position = position;
    		vertices[i + 1].Position = position;
    		vertices[i + 2].Position = position;
    		vertices[i + 3].Position = position;
    
    		vertices[i + 0].Uv = Vector2(0, 1);
    		vertices[i + 1].Uv = Vector2(0, 0);
    		vertices[i + 2].Uv = Vector2(1, 1);
    		vertices[i + 3].Uv = Vector2(1, 0);
    
    		vertices[i + 0].Scale = scale;
    		vertices[i + 1].Scale = scale;
    		vertices[i + 2].Scale = scale;
    		vertices[i + 3].Scale = scale;
    
    		vertices[i + 0].Random = random;
    		vertices[i + 1].Random = random;
    		vertices[i + 2].Random = random;
    		vertices[i + 3].Random = random;
    	}
    
    	indices = new UINT[drawCount * 6];
    	for (UINT i = 0; i < drawCount; i++)
    	{
    		indices[i * 6 + 0] = i * 4 + 0;
    		indices[i * 6 + 1] = i * 4 + 1;
    		indices[i * 6 + 2] = i * 4 + 2;
    		indices[i * 6 + 3] = i * 4 + 2;
    		indices[i * 6 + 4] = i * 4 + 1;
    		indices[i * 6 + 5] = i * 4 + 3;
    	}
    
    	vertexBuffer = new VertexBuffer(vertices, drawCount * 4, sizeof(VertexSnow));
    	indexBuffer = new IndexBuffer(indices, drawCount * 6);
    
    	//ID3D11BlendState
    	//D3D11_BLEND_DESC;
    }
    
    Snow::~Snow()
    {
    	SafeDelete(buffer);
    
    	SafeDeleteArray(vertices);
    	SafeDeleteArray(indices);
    
    	SafeDelete(texture);
    }
    
    void Snow::Update()
    {
    	Super::Update();
    
    	Context::Get()->GetCamera()->Position(&desc.Origin);
    	//ImGui::SliderFloat3("Origin", desc.Origin, 0, 200);
    
    	ImGui::SliderFloat3("Velocity", desc.Velocity, -200, 200);
    	ImGui::ColorEdit3("Color", desc.Color);
    	ImGui::SliderFloat("Distance", &desc.DrawDistance, 0, desc.Extent.z * 2.0f);
    	ImGui::InputFloat("Turbulence", &desc.Turbulence, 0.1f);
    }
    
    void Snow::Render()
    {
    	Super::Render();
    
    	buffer->Render();
    	sBuffer->SetConstantBuffer(buffer->Buffer());
    
    
    	static UINT pass = 0;
    	ImGui::InputInt("Snow Pass", (int *)&pass);
    	pass %= 4;
    	
    	shader->DrawIndexed(0, pass, drawCount * 6);
    }

     

     

    WeatherDemo

     

    WeatherDemo.h

    더보기
    #pragma once
    #include "Systems/IExecute.h"
    
    class WeatherDemo : 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:
    	void Billboards();
    	void Mesh();
    	void Airplane();
    	void Kachujin();
    	void KachujinCollider();
    	void KachujinWeapon();
    	void PointLighting();
    	void SpotLighting();
    
    	void Pass(UINT mesh, UINT model, UINT anim);
    
    private:
    	Shader* shader;
    
    	Billboard* billboard;
    
    	CubeSky* sky;
    
    
    	enum class WeatherType
    	{
    		None = 0, Rain, Snow, Count,
    	} weatherType;
    
    	Rain* rain;
    	Snow* snow;
    
    	Material* floor;
    	Material* stone;
    	Material* brick;
    	Material* wall;
    
    	MeshRender* cube;
    	MeshRender* cylinder;
    	MeshRender* sphere;
    	MeshRender* grid;
    
    	ModelRender* airplane = NULL;
    
    
    	ModelAnimator* kachujin = NULL;
    	Transform* colliderInitTransforms;
    	ColliderObject** colliders;
    
    	ModelRender* weapon = NULL;
    	Transform* weaponInitTransform;
    
    	vector<MeshRender *> meshes;
    	vector<ModelRender *> models;
    	vector<ModelAnimator *> animators;
    };

     

     

    WeatherDemo.cpp

    더보기
    #include "stdafx.h"
    #include "WeatherDemo.h"
    
    void WeatherDemo::Initialize()
    {
    	Context::Get()->GetCamera()->RotationDegree(20, 0, 0);
    	Context::Get()->GetCamera()->Position(1, 36, -85);
    	((Freedom *)Context::Get()->GetCamera())->Speed(50, 2);
    
    
    	shader = new Shader(L"82_NormalMapping.fxo");
    
    	sky = new CubeSky(L"Environment/GrassCube1024.dds");
    	
    	rain = new Rain(Vector3(300, 100, 500), (UINT)1e+4f, L"Environment/Rain.png");
    	snow = new Snow(Vector3(300, 100, 500), (UINT)1e+5f, L"Environment/Snow.png");
    	
    	Billboards();
    
    	Mesh();
    	Airplane();
    	
    	Kachujin();
    	KachujinCollider();
    	KachujinWeapon();
    
    	PointLighting();
    	SpotLighting();
    }
    
    void WeatherDemo::Update()
    {
    	sky->Update();
    
    	cube->Update();
    	grid->Update();
    	cylinder->Update();
    	sphere->Update();
    
    	airplane->Update();
    	kachujin->Update();
    
    	Matrix worlds[MAX_MODEL_TRANSFORMS];
    	for (UINT i = 0; i < kachujin->GetTransformCount(); i++)
    	{
    		kachujin->GetAttachTransform(i, worlds);
    		weapon->GetTransform(i)->World(weaponInitTransform->World() * worlds[40]);
    	}
    
    	weapon->UpdateTransforms();
    	weapon->Update();
    
    	billboard->Update();
    
    
    
    	UINT WeatherSelected = (UINT)weatherType;
    
    	ImGui::Separator();
    	ImGui::InputInt("Weather Type", (int *)&WeatherSelected);
    	WeatherSelected %= (UINT)WeatherType::Count;
    	weatherType = (WeatherType)WeatherSelected;
    
    	switch (weatherType)
    	{
    		case WeatherType::Rain: rain->Update(); break;
    		case WeatherType::Snow: snow->Update(); break;
    	}
    }
    
    void WeatherDemo::Render()
    {
    	sky->Render();
    
    	
    	Pass(0, 1, 2);
    
    	wall->Render();
    	sphere->Render();
    
    	brick->Render();
    	cylinder->Render();
    
    	stone->Render();
    	cube->Render();
    
    	floor->Render();
    	grid->Render();
    
    	airplane->Render();
    	
    	kachujin->Render();
    	weapon->Render();
    
    	billboard->Render();
    	
    	switch (weatherType)
    	{
    	case WeatherType::Rain: rain->Render(); break;
    	case WeatherType::Snow: snow->Render(); break;
    	}
    }
    
    void WeatherDemo::Billboards()
    {
    	billboard = new Billboard(L"Terrain/grass_14.tga");
    
    	for (UINT i = 0; i < 1200; i++)
    	{
    		Vector2 scale = Math::RandomVec2(1, 3);
    		Vector2 position = Math::RandomVec2(-60, 60);
    
    		billboard->Add(Vector3(position.x, scale.y * 0.5f, position.y), scale);
    	}
    }
    
    void WeatherDemo::Mesh()
    {
    	//Create Material
    	{
    		floor = new Material(shader);
    		floor->DiffuseMap("Floor.png");
    		floor->Specular(1, 1, 1, 20);
    		floor->SpecularMap("Floor_Specular.png");
    		floor->NormalMap("Floor_Normal.png");
    		
    		stone = new Material(shader);
    		stone->DiffuseMap("Stones.png");
    		stone->Specular(1, 1, 1, 20);
    		stone->SpecularMap("Stones_Specular.png");
    		stone->Emissive(0.15f, 0.15f, 0.15f, 0.3f);
    		stone->NormalMap("Stones_Normal.png");
    
    		
    		brick = new Material(shader);
    		brick->DiffuseMap("Bricks.png");
    		brick->Specular(1, 0.3f, 0.3f, 20);
    		brick->SpecularMap("Bricks_Specular.png");
    		brick->Emissive(0.15f, 0.15f, 0.15f, 0.3f);
    		brick->NormalMap("Bricks_Normal.png");
    
    		wall = new Material(shader);
    		wall->DiffuseMap("Wall.png");
    		wall->Specular(1, 1, 1, 20);
    		wall->SpecularMap("Wall_Specular.png");
    		wall->Emissive(0.15f, 0.15f, 0.15f, 0.3f);
    		wall->NormalMap("Wall_Normal.png");
    	}
    
    	//Create Mesh
    	{
    		Transform* transform = NULL;
    
    		cube = new MeshRender(shader, new MeshCube());
    		transform = cube->AddTransform();
    		transform->Position(0, 5, 0);
    		transform->Scale(20, 10, 20);
    
    		grid = new MeshRender(shader, new MeshGrid(5, 5));
    		transform = grid->AddTransform();
    		transform->Position(0, 0, 0);
    		transform->Scale(12, 1, 12);
    
    		cylinder = new MeshRender(shader, new MeshCylinder(0.5f, 3.0f, 20, 20));
    		sphere = new MeshRender(shader, new MeshSphere(0.5f, 20, 20));
    		for (UINT i = 0; i < 5; i++)
    		{
    			transform = cylinder->AddTransform();
    			transform->Position(-30, 6, -15.0f + (float)i * 15.0f);
    			transform->Scale(5, 5, 5);
    
    			transform = cylinder->AddTransform();
    			transform->Position(30, 6, -15.0f + (float)i * 15.0f);
    			transform->Scale(5, 5, 5);
    
    
    			transform = sphere->AddTransform();
    			transform->Position(-30, 15.5f, -15.0f + (float)i * 15.0f);
    			transform->Scale(5, 5, 5);
    
    			transform = sphere->AddTransform();
    			transform->Position(30, 15.5f, -15.0f + (float)i * 15.0f);
    			transform->Scale(5, 5, 5);
    		}
    	}
    
    	sphere->UpdateTransforms();
    	cylinder->UpdateTransforms();
    	cube->UpdateTransforms();
    	grid->UpdateTransforms();
    
    	meshes.push_back(sphere);
    	meshes.push_back(cylinder);
    	meshes.push_back(cube);
    	meshes.push_back(grid);
    }
    
    void WeatherDemo::Airplane()
    {
    	airplane = new ModelRender(shader);
    	airplane->ReadMesh(L"B787/Airplane");
    	airplane->ReadMaterial(L"B787/Airplane");
    
    	Transform* transform = airplane->AddTransform();
    	transform->Position(2.0f, 9.91f, 2.0f);
    	transform->Scale(0.004f, 0.004f, 0.004f);
    	airplane->UpdateTransforms();
    
    	models.push_back(airplane);
    }
    
    void WeatherDemo::Kachujin()
    {
    	kachujin = new ModelAnimator(shader);
    	kachujin->ReadMesh(L"Kachujin/Mesh");
    	kachujin->ReadMaterial(L"Kachujin/Mesh");
    	kachujin->ReadClip(L"Kachujin/Sword And Shield Idle");
    	kachujin->ReadClip(L"Kachujin/Sword And Shield Walk");
    	kachujin->ReadClip(L"Kachujin/Sword And Shield Run");
    	kachujin->ReadClip(L"Kachujin/Sword And Shield Slash");
    	kachujin->ReadClip(L"Kachujin/Salsa Dancing");
    
    
    	Transform* transform = NULL;
    
    	transform = kachujin->AddTransform();
    	transform->Position(0, 0, -30);
    	transform->Scale(0.075f, 0.075f, 0.075f);
    	kachujin->PlayTweenMode(0, 0, 1.0f);
    
    	transform = kachujin->AddTransform();
    	transform->Position(-15, 0, -30);
    	transform->Scale(0.075f, 0.075f, 0.075f);
    	kachujin->PlayTweenMode(1, 1, 1.0f);
    
    	transform = kachujin->AddTransform();
    	transform->Position(-30, 0, -30);
    	transform->Scale(0.075f, 0.075f, 0.075f);
    	kachujin->PlayTweenMode(2, 2, 0.75f);
    
    	transform = kachujin->AddTransform();
    	transform->Position(15, 0, -30);
    	transform->Scale(0.075f, 0.075f, 0.075f);
    	kachujin->PlayBlendMode(3, 0, 1, 2);
    	kachujin->SetBlendAlpha(3, 1.5f);
    
    	transform = kachujin->AddTransform();
    	transform->Position(30, 0, -32.5f);
    	transform->Scale(0.075f, 0.075f, 0.075f);
    	kachujin->PlayTweenMode(4, 4, 0.75f);
    
    	kachujin->UpdateTransforms();
    
    	animators.push_back(kachujin);
    }
    
    void WeatherDemo::KachujinCollider()
    {
    	UINT count = kachujin->GetTransformCount();
    	colliders = new  ColliderObject*[count];
    
    	colliderInitTransforms = new Transform();
    	colliderInitTransforms->Position(-2.9f, 1.45f, -50.0f);
    	colliderInitTransforms->Scale(5, 5, 75);
    
    	for (UINT i = 0; i < count; i++)
    	{
    		colliders[i] = new ColliderObject();
    
    		//colliders[i]->Init = new Transform();
    		//colliders[i]->Init->Position(0, 0, 0);
    		//colliders[i]->Init->Scale(10, 30, 10);
    
    		colliders[i]->Transform = new Transform();
    		//colliders[i]->Collider = new Collider(colliders[i]->Transform, colliders[i]->Init);
    		colliders[i]->Collider = new Collider(colliders[i]->Transform, colliderInitTransforms);
    	}
    }
    
    void WeatherDemo::KachujinWeapon()
    {
    	weapon = new ModelRender(shader);
    	weapon->ReadMesh(L"Weapon/Sword");
    	weapon->ReadMaterial(L"Weapon/Sword");
    
    	UINT count = kachujin->GetTransformCount();
    	for (UINT i = 0; i < count; i++)
    		weapon->AddTransform();
    
    	weapon->UpdateTransforms();
    	models.push_back(weapon);
    
    	
    	weaponInitTransform = new Transform();
    	weaponInitTransform->Position(-2.9f, 1.45f, -6.45f);
    	weaponInitTransform->Scale(0.5f, 0.5f, 0.75f);
    	weaponInitTransform->Rotation(0, 0, 1);
    }
    
    void WeatherDemo::PointLighting()
    {
    	PointLight light;
    	light =
    	{
    		Color(0.0f, 0.0f, 0.0f, 1.0f), //Ambient
    		Color(0.0f, 0.0f, 1.0f, 1.0f), //Diffuse
    		Color(0.0f, 0.0f, 0.7f, 1.0f), //Specular
    		Color(0.0f, 0.0f, 0.7f, 1.0f), //Emissive
    		Vector3(-30, 10, -30), 5.0f, 0.9f
    	};
    	Lighting::Get()->AddPointLight(light);
    
    	light =
    	{
    		Color(0.0f, 0.0f, 0.0f, 1.0f),
    		Color(1.0f, 0.0f, 0.0f, 1.0f),
    		Color(0.6f, 0.2f, 0.0f, 1.0f),
    		Color(0.6f, 0.3f, 0.0f, 1.0f),
    		Vector3(15, 10, -30), 10.0f, 0.3f
    	};
    	Lighting::Get()->AddPointLight(light);
    
    	light =
    	{
    		Color(0.0f, 0.0f, 0.0f, 1.0f), //Ambient
    		Color(0.0f, 1.0f, 0.0f, 1.0f), //Diffuse
    		Color(0.0f, 0.7f, 0.0f, 1.0f), //Specular
    		Color(0.0f, 0.7f, 0.0f, 1.0f), //Emissive
    		Vector3(-5, 1, -17.5f), 5.0f, 0.9f
    	};
    	Lighting::Get()->AddPointLight(light);
    
    	light =
    	{
    		Color(0.0f, 0.0f, 0.0f, 1.0f),
    		Color(0.0f, 0.0f, 1.0f, 1.0f),
    		Color(0.0f, 0.0f, 0.7f, 1.0f),
    		Color(0.0f, 0.0f, 0.7f, 1.0f),
    		Vector3(-10, 1, -17.5f), 5.0f, 0.9f
    	};
    	Lighting::Get()->AddPointLight(light);
    }
    
    void WeatherDemo::SpotLighting()
    {
    	SpotLight light;
    	light =
    	{
    		Color(0.3f, 1.0f, 0.0f, 1.0f),
    		Color(0.7f, 1.0f, 0.0f, 1.0f),
    		Color(0.3f, 1.0f, 0.0f, 1.0f),
    		Color(0.3f, 1.0f, 0.0f, 1.0f),
    		Vector3(-15, 20, -30), 25.0f,
    		Vector3(0, -1, 0), 30.0f, 0.4f
    	};
    	Lighting::Get()->AddSpotLight(light);
    
    	light =
    	{
    		Color(1.0f, 0.2f, 0.9f, 1.0f),
    		Color(1.0f, 0.2f, 0.9f, 1.0f),
    		Color(1.0f, 0.2f, 0.9f, 1.0f),
    		Color(1.0f, 0.2f, 0.9f, 1.0f),
    		Vector3(0, 20, -30), 30.0f,
    		Vector3(0, -1, 0), 40.0f, 0.55f
    	};
    	Lighting::Get()->AddSpotLight(light);
    }
    
    void WeatherDemo::Pass(UINT mesh, UINT model, UINT anim)
    {
    	for (MeshRender* temp : meshes)
    		temp->Pass(mesh);
    
    	for (ModelRender* temp : models)
    		temp->Pass(model);
    
    	for (ModelAnimator* temp : animators)
    		temp->Pass(anim);
    }

     

     

     


     

     

    실행화면

     

     

    '⭐ DirectX > DirectX11 3D' 카테고리의 다른 글

    [DirectX11] 095 Particle Editor  (0) 2023.04.12
    [DirectX11] 089~94 Particle System  (0) 2023.04.04
    [DirectX11] 083~84 Billboard  (0) 2023.03.28
    [DirectX11] 081~82 Normal Mapping  (0) 2023.03.27
    [DirectX11] 080 Spot Lighting  (0) 2023.03.26