필요한 개념
Projector라고도 하고 Projection Texture라고도 한다.
View,Projection 영역에서 Texture를 바른다고 해서 그럼
Projector라고 하는 이유가 빔프로젝터 비추면 비추는 공간안에서 이미지가 발라지니까 이렇게 말함
정식 명칭은 Projection Texture가 맞다.
Y축은 제거하고 절두체를 그려보면(그림 8-1 이됨)
요걸 이용
이 공간안에다가 텍스쳐를 바름
Viwe, Projection이 끝나면 RS로 넘거간다 이 사이는 NDC공간이다.
NDC공간이므로 x방향이 -1 ~ +1까지이다.
이렇게 만들어진 좌표로 UV를 만들겠다는 얘기
화면 공간을 UV로 써서 화면 공간안에 텍스쳐를 발라서 이 공간안에만 발라진다.
NDC는 시스템에서 SV_Position이 NDC로 만들어줌
PixelShader에서 그래서 SV_Position을 가져다 쓰면 안된다.(시스템의 좌표니깐)
ViewProjection을 별도로 보내서 Position으로 넘긴다. 절두체의 ViewProejction으로 연산한다.
이때 worldPosition을 View와 Projection으로 변환해서 저장해둠
float4 x,y,z,w를 갖는다. w는 정점셰이더에서는 뱡향과 위치의 마킹이다.
PixelShader에서는 x,y,z에 대한 NDC 비율(동차) 이다.
이 동차로 x,y,z을 나누게 되면 (쿼터니언도 w가 x,y,z에 대해 얼마만큼 회전할지에 대한 비율이다. 예를 들어 x : 1, y : 0.5, z : 0.2, w : 0.5라면
x : 0.5만큼 x축 회전, y : 0.25만큼 y축 회전, z : 0.1만큼 z축 회전이 된다.)
그것 처럼 w가 동차여서 x,y,z를 나눠주면 정규화된 좌표가 나온다.
(x,y = -1 ~ 1이 되고, z(깊이) = 0 ~ 1의 값이 된다.(NDC 좌표가 됨))
-> 즉 NDC 공간의 좌표를 0 ~ 1까지의 UV좌표로 바꿔 텍스쳐를 샘플링하겠다는 것
- 화면 공간을 이미지 공간으로 해서 렌더링
다른데에도 쓰니깐
00_Light영역 밑에다 추가함
MeshOutput에 wvpPosition왜 이거 추가하나?
Position도 WVP 변환후에 써도 되지만, SV_Position은 PS에서 Rasterizer용이어서 PS에서 가져다 쓸수 없다. 쓸라면 쓸 수 있지만, 잘 쓰지 않는다.(NDC된 공간이므로)
시스템에 의해 바뀌는 값(SV)이 된다.
그래서 바뀌지 않는 원본 값을 추가한 것이다.
창문에 비친 효과(큐브에다가)도 많이 쓴다. 그렇게 되면 절두체 부분에 텍스쳐 발라진게 큐브에 다가 창문에 비친 텍스쳐를 겹칠 수 있다.
어느지역에서 고정으로 비출 카메라를 만든다. Fixity.h를 만듬
Projector 클래스도 만든다.
결과를 보면 텍스쳐가 화면 공간에서 엄청 크게 그려짐
Far가 100일때 grid 끝에 다다르면 멈춤 이유는, 그 다음은 하늘이니까 안그려짐
Position을 옮기면 카메라 위치가 바뀐다.
결과가 View Projection(Perspective) 영역으로 들어가는 것을 확인할 수 있다.
Perspective에서 width를 넓이면 AspectRatio가 넓어지니까 양옆이 넓어짐
Near를 줄이거면 하면 땡길 수 있다.
Far를 줄이거면 하면 앞으로 땡길 수 있다.(거리가 짧아짐)
Fov 이용해서 시야각도 넓힐 수 있다.
원하는 텍스쳐 넣어서 겹치게 할 수 있다.
근데 실제로 이렇게 잘 안씀(Perspective)
각을 90도로 주고 마법진 넣어주면 마법 효과가 들어간것으로 보인다.
그런데 Perspective는 거리에 따라 원근 투영이 일어나므로 크기가 높이에 따라 변한다.(즉 높이가 높아질 수록 크기가 변함)
그래서 원하는 크기로 마법진을 맞추기가 굉장히 힘듬
그래서 Orthograph를 사용한다.(정점하나랑 정확히 매핑됨, Orthograph은 직교투영이어서 크기가 변하지 않는다.)
그래서 마법진 같은거는 Projector를 쓸때, Orthograph를 사용한다.
width, height를 외부에서 크기 1으로 줘서 vertex 한칸의 크기와 동일해진다.
시야각에 의해서 projection 변환에서 RS에서 나오면 거리에 따라 달라지지만
Orthographic은 변할게 없다.(크기가 변하지 않음, 우리가 원하는 크기와 동일해짐)
Orthographic로 하면 크기가 딱 1로 잡힌다.(WireFrame모드로 보면 정점한칸의 크기와 동일하다.)
이전 Perspective에 비해 크기가 딱 1로 잡혀서 크기가 확실히 작아짐
마법진 같은거 그릴때 UV 2D로 그리는 경우도 있지만 Projector로 그려주는게 편하다.
클릭 같은거 할때 어느위치에서 그릴때 편함
Fixity.h
#pragma once
#include "Camera.h"
// 한쪽을 비추는 고정 카메라
class Fixity : public Camera
{
public:
Fixity();
~Fixity();
void Update() override;
// view Matrix주면 그쪽으로 비추기 위해
void SetView(Matrix& view) { mat_view = view; }
private:
};
Fixity.cpp
#include "Framework.h"
#include "Fixity.h"
Fixity::Fixity()
{
Rotation();
Move();
}
Fixity::~Fixity()
{
}
void Fixity::Update()
{
}
Projector.h
#pragma once
class Projector
{
public:
Projector(Shader* shader, wstring mapFile, UINT width, UINT height);
~Projector();
void Update();
void Render();
Camera* GetCamera() { return (Camera*)camera; }
private:
struct Desc
{
Matrix View;
Matrix Projection;
Color Color = D3DXCOLOR(1, 1, 1, 1); // 색상
} desc;
private:
Shader* shader;
UINT width, height; // 카메라 영역에 대한 넓이, 높이
Fixity* camera;
Projection* projection;
Texture* map; // 텍스쳐
ID3DX11EffectShaderResourceVariable* sMap;
ConstantBuffer* buffer; // cbuffer
ID3DX11EffectConstantBuffer* sBuffer;
};
Projector.cpp
#include "Framework.h"
#include "Projector.h"
Projector::Projector(Shader* shader, wstring mapFile, UINT width, UINT height)
: shader(shader), width(width), height(height)
{
// 보정용 카메라 세팅
camera = new Fixity();
//camera->Position(0, 0, -20.0f);
// 이것에 의해 aspectRatio가 결정된다.
// 위에서 아래로 비추도록
camera->RotationDegree(90, 0, 0);
camera->Position(0, 30, 0);
//projection = new Perspective((float)width, (float)height, 1, 100, Math::PI * 0.25f);
// width, height를 외부에서 크기 1으로 줘서 vertex 한칸의 크기와 동일해진다.
// 시야각에 의해서 projection 변환에서 RS에서 나오면 거리에 따라 달라지지만
// Orthographic은 변할게 없다.(크기가 변하지 않음, 우리가 원하는 크기와 동일해짐)
projection = new Orthographic((float)width, (float)height);
map = new Texture(mapFile);
buffer = new ConstantBuffer(&desc, sizeof(Desc));
sMap = shader->AsSRV("ProjectorMap");
sMap->SetResource(map->SRV());
sBuffer = shader->AsConstantBuffer("CB_Projector");
}
Projector::~Projector()
{
SafeDelete(camera);
SafeDelete(projection);
SafeDelete(map);
SafeDelete(buffer);
}
void Projector::Update()
{
Vector3 position;
camera->Position(&position);
ImGui::SliderFloat3("Position", position, -100, 100);
camera->Position(position);
ImGui::ColorEdit3("Color", desc.Color);
//Perspective
//{
// static float width = this->width, height = this->height;
// static float n = 1.0f, f = 100.0f;
// static float fov = 0.25f;
// ImGui::SliderFloat("Width", &width, 0, 100);
// ImGui::SliderFloat("Height", &height, 0, 100);
// ImGui::SliderFloat("Near", &n, 0, 200);
// ImGui::SliderFloat("Far", &f, 0, 200);
// ImGui::SliderFloat("Fov", &fov, 0, Math::PI * 2.0f);
// ((Perspective *)projection)->Set(width, height, n, f, Math::PI * fov);
//}
//Orthographic
{
static float width = this->width, height = this->height;
static float n = 1.0f, f = 100.0f;
ImGui::SliderFloat("Width", &width, 0, 100);
ImGui::SliderFloat("Height", &height, 0, 100);
ImGui::SliderFloat("Near", &n, 0, 200);
ImGui::SliderFloat("Far", &f, 0, 200);
((Orthographic*)projection)->Set(width, height, n, f);
}
// 카메라, projecton 얻어서 desc에 세팅
camera->GetMatrix(&desc.View);
projection->GetMatrix(&desc.Projection);
}
void Projector::Render()
{
// shader에 밀어주기 위해
buffer->Render();
sBuffer->SetConstantBuffer(buffer->Buffer());
}
ProjectorDemo.h
#pragma once
#include "Systems/IExecute.h"
class ProjectorDemo : 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 Mesh();
void Airplane();
void Kachujin();
void KachujinCollider();
void KachujinWeapon();
void PointLighting();
void SpotLighting();
void Pass(UINT mesh, UINT model, UINT anim);
private:
Shader* shader;
Projector* projector;
CubeSky* sky;
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;
};
ProjectorDemo.cpp
#include "stdafx.h"
#include "ProjectorDemo.h"
void ProjectorDemo::Initialize()
{
Context::Get()->GetCamera()->RotationDegree(20, 0, 0);
Context::Get()->GetCamera()->Position(1, 36, -85);
shader = new Shader(L"111_Projector.fxo");
// 1, 1로 줄 시 정비율로 됨
projector = new Projector(shader, L"Environment/MagicCircle.png", 1, 1);
sky = new CubeSky(L"Environment/GrassCube1024.dds");
Mesh();
Airplane();
Kachujin();
KachujinCollider();
KachujinWeapon();
PointLighting();
SpotLighting();
}
void ProjectorDemo::Update()
{
projector->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();
}
void ProjectorDemo::PreRender()
{
}
void ProjectorDemo::Render()
{
// 연산할 수 있도록 준비
projector->Render();
sky->Pass(0);
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();
}
void ProjectorDemo::PostRender()
{
}
void ProjectorDemo::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 ProjectorDemo::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 ProjectorDemo::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 ProjectorDemo::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 ProjectorDemo::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 ProjectorDemo::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 ProjectorDemo::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 ProjectorDemo::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);
}
111_Projector.fx
#include "00_Global.fx"
#include "00_Light.fx"
#include "00_Render.fx"
MeshOutput VS_Mesh_Projector(VertexMesh input)
{
// wvp 계산이 될것이다.
MeshOutput output = VS_Mesh(input);
// input.Position에 따라 projector용 WVP 변환
VS_Projector(output.wvpPosition_Sub, input.Position);
return output;
}
MeshOutput VS_Model_Projector(VertexModel input)
{
MeshOutput output = VS_Model(input);
VS_Projector(output.wvpPosition_Sub, input.Position);
return output;
}
MeshOutput VS_Animation_Projector(VertexModel input)
{
MeshOutput output = VS_Animation(input);
VS_Projector(output.wvpPosition_Sub, input.Position);
return output;
}
float4 PS(MeshOutput input) : SV_Target
{
float4 color = PS_AllLight(input);
// PS는 프로젝터용 셰이더로 쓸 것이다.
// input.wvpPosition_Sub에다가 VertesShader에서 프로젝션용 WVP를 계산해줬기 때문에
PS_Projector(color, input.wvpPosition_Sub);
return color;
}
technique11 T0
{
//Render
P_VP(P1, VS_Mesh_Projector, PS)
P_VP(P2, VS_Model_Projector, PS)
P_VP(P3, VS_Animation_Projector, PS)
}
00_Global.fx 수정된 내용
...
struct MeshOutput
{
float4 Position : SV_Position0;
float3 oPosition : Position1;
float3 wPosition : Position2;
float4 wvpPosition : Position3; // 메인 카메라용
float4 wvpPosition_Sub : Position4; // 보조(위에랑 같은 값이 들어갈 수도 있고, 아닐 수도 있다.)
float3 Normal : Normal;
float3 Tangent : Tangent;
float2 Uv : Uv;
float4 Color : Color;
};
00_Light.fx 추가된 내용
...
////////////////////////////////////////////////////////////////////////////
Texture2D ProjectorMap; // 공간에 바를 텍스쳐
struct ProjectorDesc
{
matrix View;
matrix Projection;
float4 Color; // 나중에 마법진 할때 설명
};
cbuffer CB_Projector
{
ProjectorDesc Projector;
};
// 1 : wvp 공간으로 계산된것을 리턴해줌, 2 : 오리지널 포지션
void VS_Projector(inout float4 wvp, float4 oPosition)
{
wvp = WorldPosition(oPosition);
// 이쪽에 view, Projection 공간으로 변환이 됨
wvp = mul(wvp, Projector.View);
wvp = mul(wvp, Projector.Projection);
}
void PS_Projector(inout float4 color, float4 wvp)
{
// uv의 w
float3 uvw = 0;
// NDC안에 들어온다면 -1 ~ 1까지 떨어진다.
// 화면에 들어오지 않는 공간이라 하면 -1을 넘어서는 값이 된다. +1을 넘어서는 값이 된다.
// 즉, 절두체에 벗어난 공간이라면 넘어서는 값이 됨
// 애초에 NDC공간안에 들어오지 않는 것은 그리지 않는다.
// 우리는 uv로 써야하니까 -1 ~ 1 공간을 0 ~ 1까지의 UV로 바꾼다.
uvw.x = wvp.x / wvp.w * 0.5f + 0.5f;
// 3D 공간을 2D로 바꿔야하니까 뒤집어준다.
uvw.y = -wvp.y / wvp.w * 0.5f + 0.5f;
uvw.z = wvp.z / wvp.w;
// saturate는 0 ~ 1값이 나온다. 근데 uvw값이 이 값을 넘어선다면 영역안에 들어와있지 않다는것
// 전부 다 같다면 영역안에 들어와 있는 것이다.(들어와있는 애들만 그림)
[flatten]
if (saturate(uvw.x) == uvw.x && saturate(uvw.y) == uvw.y && saturate(uvw.z) == uvw.z)
{
// 화면 공간에서 uv가 된게 화면공간에서 그려진다.
float4 map = ProjectorMap.Sample(LinearSampler, uvw.xy);
// 원색에다가 색을 곱해서 마법진이나 이런거 쓰려고 하는 것이다.
map.rgb *= Projector.Color.rgb;
color = lerp(color, map, map.a);
}
}
결과
Orthographic 활용(위에서 90도로 고정 카메라 내려보는 모습)
'DirectX11 3D > 기본 문법' 카테고리의 다른 글
<DirectX11 3D> 113 - Shadow (0) | 2022.03.28 |
---|---|
<DirectX11 3D> 107 - Dynamic Cube Map (0) | 2022.03.22 |
<DirectX11 3D> 106 - Bloom (0) | 2022.03.22 |
<DirectX11 3D> 105 - GaussianBlur (0) | 2022.03.22 |
<DirectX11 3D> 104 - Blur (0) | 2022.03.22 |