응애맘마조
231006 강의 본문
어제에 이어서 물을 표현하는 방법에 대해 강의했습니다.
#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);
만약 물이 흐르는 방향을 바꾸고 싶으면 위의 코드의 벡터 값을 변경하면 됩니다.
읽어주셔서 감사합니다.
Comments