본문 바로가기

DirectX11 3D/기본 문법

<DirectX11 3D> 88 - Snow

 

필요한 개념


비의 구현과 눈의 구현은 Turbulence를 제외하고는 크게 다르지 않다.
움직이는 부분만 차이가 날뿐이다.

Turbulence :  눈이 바람에 의해 흩날릴것이다. 흩날리는 정도(바람의 정도)
float Scale : float 1개인 이유가 눈은 동글동글 해서(가로 세로 같음)

결과를 보면
Additive는 알파 연산이 없기 때문에 사각형 그대로 나온다.

* 대형맵의 경우
눈이나 비는 항상 카메라를 따라다니게 해서 대형 맵 같은 곳에서도 사용할 수 있도록 수정
-> 그런데 움직임이 조금은 어색해짐

 

 

 

 

 

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.h 추가된 내용


더보기
class WeatherDemo : public IExecute
{
	...
private:
	Snow* snow;
}

 

 

 

 

 

 

 

WeatherDemo.cpp 추가된 내용


더보기
...
void WeatherDemo::Initialize()
{
	...
	snow = new Snow(Vector3(300, 100, 500), (UINT)1e+4f, L"Environment/Snow.png");
}

void WeatherDemo::Update()
{
	...
	switch (weatherType)
	{
	case WeatherType::Rain: rain->Update(); break;
	case WeatherType::Snow: snow->Update(); break;
	}
}

void WeatherDemo::Render()
{	
	...
	// 반투명 될 것을 맨 뒤에 그림(불투명 먼저 그려져야함)
	// -> 불투명 색으로 반투명이 그려지므로
	switch (weatherType)
	{
	case WeatherType::Rain: rain->Render(); break;
	case WeatherType::Snow: snow->Render(); break;
	}
}

 

 

 

 

 

 

 

 

 

85_Snow.fx


더보기
#include "00_Global.fx"
#include "00_Light.fx"

cbuffer CB_Snow
{
    float4 Color;
    
    float3 Velocity;
    float DrawDistance;
    
    float3 Origin;
    float Turbulence; // 바람에 흩날리는 정도
    
    float3 Extent;
};

struct VertexInput
{
    float4 Position : Position;
    float2 Uv : Uv;
    float Scale : Scale; // float 1개인 이유가 눈은 동글동글 해서(가로 세로 같음)
    float2 Random : Random; // 정점마다 바람에 흩날리는 정도가 다르도록 랜덤으로
};

struct VertexOutput
{
    float4 Position : SV_Position;
    float2 Uv : Uv;
    float Alpha : Alpha;
};

VertexOutput VS(VertexInput input)
{
    VertexOutput output;
    
    // 시간에 따라 속도 증가하도록 *Time
    float3 displace = Velocity * Time;
    
    input.Position.y = Origin.y + Extent.y - (input.Position.y - displace.y) % Extent.y;
    // cos() -> 어떤 값이든 -1 ~ 1까지 나옴
    // -1 ~ 1까지의 영역으로 바꿔서 Tubluence 만큼 이동
    input.Position.x += cos(Time - input.Random.x) * Turbulence;
    input.Position.z += cos(Time - input.Random.y) * Turbulence;
    
    // 갇히도록
    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);
    
    // * 2.0f 요정도 해줬을때 이쁘드라
    diffuse.rgb *= Color.rgb * input.Alpha * 2.0f;
    // 요것도 특별한 의미를 지닌값이 아님(1.5f는)
    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, Snow 결과

0번 : None

1번 : Rain

2번 : Snow

 

0번 : AlphaBlend

1번 : AlphaBlend_AlphaToCoverageEnable

2번 : AdditiveBlend

3번 : AdditiveBlend_AlphaToCoverageEnable

 

 

'DirectX11 3D > 기본 문법' 카테고리의 다른 글

<DirectX11 3D> 96 - GS(Geometry Shader)  (0) 2022.03.16
<DirectX11 3D> 89 - ParticleSystem  (0) 2022.03.16
<DirectX11 3D> 86 - AlphaBlend  (0) 2022.03.14
<DirectX11 3D> 85 - Rain  (0) 2022.03.14
<DirectX11 3D> 83 - Billboard  (0) 2022.03.14