본문 바로가기

DirectX11 3D/기본 문법

<DirectX11 3D> 85 - Rain

 

필요한 개념


Billboard 만드는 거와 크게 차이가 없다. 그런데 정점을 어떻게 움직이느냐, 정점을 공간안에서 어떻게 순환시키는지에 있다.
입자를 움직이는 것을 통틀어서 파티클이라고 한다.
파티클 시스템도 입자를 어떻게 움직이느냐

파티클 시스템에 눈, 비 날씨를 포함하도록 프로그래밍 할 수도 있다. -> 엔진이 그렇게 되어있다.(그런데 우리는 어려우니 따로 한다.)


공간내에서 순환시킨다가 핵심
나머지는 Billboard와 같다.

Shader 중심 내용

input.Scale.y 비의 길이의 크기가 큰게 비가 빨리 떨어져야 한다.
이 밑에 구문을 빼버리면 x,z도 y만큼 빨리 떨어질 것이다.
x,z은 크기 만큼 비례해서 속도를 늦춘다.
만약 input.Scale.y가 작다면 크기에 비례해 x,z도 작은 값이 될 것이다.(비율로 만듬)
displace.xz /= input.Scale.y * 0.1f;
Time을 곱해서 displcae 값이 커진다.
displace *= Time;
    
나눈 나머지는 계속 순환하는 값이 되므로 해당 공간안에서만 움직이도록 구현할 수 있다.
계속 값이 커질 것이고 어느순간 Extent(비가 내릴 구역의 부피)를 넘어설 것이다.
넘어서면 계속 순환되도록 한다.
Extent+인 이유는 -값일 경우에 보정해줄려고 들어감
순환시킨 공간을 원래의 위치로 움직이게 하기 위해 +Origin을 수행
Origin 만큼 또 이동했으므로 그 공간내에서 다시한번 순환(그 공간안에 들어오도록)시킨다.(% Extent)
-(Extent * 0.5f) 다시 중심점을 잡아준다.(반만큼 빼줌)
순서 : 이동한 공간 내에서 순환되고 -1 ~ 1까지 옮겨져서 반에의해서 안에 들어감

순서 주의
1. 위치에다가 속도를 조정한 displace를 더해주고 공간내에서 순환시키기 위해 %Extent 부피만큼((+Extent) 더해줌
2. 다시한번 공간으로 가기위해 %Extent로 나눠주고 공간으로 가둬두고 위치를 Origin에다가 더해서 중심점으로 이동
3. 부피만큼 더해줘서 - (Extent * 0.5f)를 해줌(하는 이유는 Extent+(부피를) 1번에서 더해줘서 그럼)

정점의 위치에 다가 속도를 보정한 애를 더해줌 공간으로 나눈 나머지로 순환시킴
거기에 Extent더해줌, 다시 Extent로 나눈 나머지를 취함(그래야 Extent만큼 증가한 공간에서 순환이 일어남)
거기다 원점 위치를 더해서 원점으로 공간이동
(Extent * 0.5f) -> 반을 빼서 최종위치를 구함
input.Position.xyz = Origin + (Extent + (input.Position.xyz + displace) % Extent) % Extent - (Extent * 0.5f);

 

 

 

 

 

Rain.h


더보기
#pragma once

// 렌더링 할꺼니까 상속받음
class Rain : public Renderer
{
public:
	// 비가 내릴 범위, 개수(정점의 개수가 됨), 파일이름(비의 텍스쳐 파일)
	Rain(Vector3& extent, UINT count, wstring file);
	~Rain();

	void Update();
	void Render();

private:
	struct Desc
	{
		D3DXCOLOR Color = D3DXCOLOR(1, 1, 1, 1); // 비가 내릴 색

		// x방향으로 휘고, y방향으로 빠르게 내리도록 값을 주었다.
		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:
	// Cbuffer
	ConstantBuffer* buffer;
	ID3DX11EffectConstantBuffer* sBuffer;

	VertexRain* vertices;
	UINT* indices;

	Texture* texture;
	// 그릴 개수 : 기본 100개 or 생성자에서 받음
	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;
	// z거리가 0 ~ 1까지, 일부러 2배 늘림(좀더 이쁘게 보이도록)
	desc.DrawDistance = desc.Extent.z * 2.0f;

	texture = new Texture(file);
	// 따른 Shader에서 이 Shader를 사용하지 않으니깐 여기서 세팅다해줌
	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)
	{
		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;
	}


	// 이번에는 cpuWrite를 true로 하지 않는다. 생성자에서 다 만들어줘서 변경하지 않음
	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);
}

 

 

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;

	Billborad* billboard;

	CubeSky* sky;

	// Enum 정의시 Count 변수를 맨 뒤에 넣어두면
	// Count를 통해 enum 내의 변수의 개수를 편하게 가져올 수 있다.
	enum class WeatherType
	{
		None = 0, Rain, Snow, Count,
	} weatherType;

	Rain* rain;

	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);

	shader = new Shader(L"82_NormalMapping.fxo");

	sky = new CubeSky(L"Environment/GrassCube1024.dds");

	// 1e+4f = 10000 -> 부동소수점 읽는법 : 1 * 10000-> 10000
	rain = new Rain(Vector3(300, 100, 500), (UINT)1e+4f, L"Environment/Rain.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();
	rain->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;
	}
}

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;
	}
}

void WeatherDemo::Billboards()
{
	billboard = new Billborad(L"Terrain/grass_14.tga");
	
	for (UINT i = 0; i < 1200; i++)
	{
		Vector2 scale = Math::RandomVec2(1, 3);
		// 5(밑에 판 크기가 -5 ~ 5 -> 10) * 12(grid 크기) = 60
		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(1.0f, 1.0f, 1.0f, 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(1.0f, 1.0f, 1.0f, 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(1.0f, 1.0f, 1.0f, 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);
}

 

 

 

 

 

 

 

 

 

85_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;
    // input.Scale.y 비의 길이의 크기가 큰게 비가 빨리 떨어져야 한다.
    // 이 밑에 구문을 빼버리면 x,z도 y만큼 빨리 떨어질 것이다.
    // x,z은 크기 만큼 비례해서 속도를 늦춘다.
    // 만약 input.Scale.y가 작다면 크기에 비례해 x,z도 작은 값이 될 것이다.(비율로 만듬)
    displace.xz /= input.Scale.y * 0.1f;
    // Time을 곱해서 displcae 값이 커진다.
    displace *= Time;
    
    // 나눈 나머지는 계속 순환하는 값이 되므로 해당 공간안에서만 움직이도록 구현할 수 있다.
    // 계속 값이 커질 것이고 어느순간 Extent(비가 내릴 구역의 부피)를 넘어설 것이다.
    // 넘어서면 계속 순환되도록 한다.
    // Extent+인 이유는 -값일 경우에 보정해줄려고 들어감
    // 순환시킨 공간을 원래의 위치로 움직이게 하기 위해 +Origin을 수행
    // Origin 만큼 또 이동했으므로 그 공간내에서 다시한번 순환(그 공간안에 들어오도록)시킨다.(% Extent)
    // -(Extent * 0.5f) 다시 중심점을 잡아준다.(반만큼 빼줌)
    // 순서 : 이동한 공간 내에서 순환되고 -1 ~ 1까지 옮겨져서 반에의해서 안에 들어감
    input.Position.xyz = Origin + (Extent + (input.Position.xyz + displace) % Extent) % Extent - (Extent * 0.5f);
    
    float4 position = WorldPosition(input.Position);

    // float(0, 1, 0)을 써도 상관없는데 이거 좀 더 정확하니깐
    // Velocity(속도)를 뒤집는다.
    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;
    
    
    // View, Projection 변환
    output.Position = ViewProjection(position);
    output.Uv = input.Uv;
    
    // 거리에 따른 알파값 조절하기
    float4 view = mul(position, View);
    // Position을 W * V로 변환한 위치의 Z의 값은 원점과 카메라의 거리
    // 이 방법 외에도 ViewPosition()과 wPosition의 차로 계산해도 값은 같다.
    // DrawDistance : 그릴 범위
    // view.z / DrawDistance서 비율로 만든다음에 역수로 만들고(0 ~ 1)
    // 얘에서 카메라를 바라보는 값이어서 즉, 값이 뒤집여져 있는 것이다.'
    // 그래서 역수로 취한다.
    // * 0.5f 해줬을때 이쁘드라 해서 넣은것
    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);
//    
//    // 클리핑(Cliping)이란? 화면의 픽셀을 OM단께로 넘기지 않고 픽셀 쉐이더에서 파기해서
//    // 해당 픽셀을 그리지 않는 방식
//    // 0이하의 값은 나타나지 않음
//    // 디자이너가 알파값을 투명값으로 0으로 주는 경우도 있지만 오차값으로 주는 경우도 있어서
//    // 0.3이하일시 파기
//    // 1. clip(diffuse.a - 0.3);
//    
//    // 2. discard(만나면 파기)
//    if (diffuse.a < 0.3)
//        discard;
//    
//    // Vertex에서도 Vertex를 파기시키는 방법이 존재 -> Culling
//    
//    return diffuse;
//}

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)

    //P_VP(P0, VS, PS_Discard)
}

 

 

 

 

 

 

 

 

 

 

 

결과


 

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

<DirectX11 3D> 88 - Snow  (0) 2022.03.14
<DirectX11 3D> 86 - AlphaBlend  (0) 2022.03.14
<DirectX11 3D> 83 - Billboard  (0) 2022.03.14
<DirectX11 3D> 82 - NormalMapping  (0) 2022.03.10
<DirectX3D 11> 80 - SpotLighting  (0) 2022.03.09