플레이어를 둘러싸는 큐브 또는 구를 만들고 물체 표면에 하늘 텍스쳐를 입힘
=>
밖에서는 어디든 하늘을 볼 수 있음
skybox에 의해 skybox 뒤에 있는 다른 물체들이 안보일 수 있음
카메라가 이동해도 항상 멀어보이도록 해야 함
1 => view space에서 항상 depth가 1이 되도록 함
2 =>
카메라가 view space에서 원점이기 때문에 skybox 또한 원점에 두고 움직이지 않도록 함
카메라의 방향에 따라 하늘의 각도가 바뀌긴 해야함
SRT에서 S와 T 사용하지 않음 => (x,y,z,0)
skybox로 큐브를 사용 시 보통 텍스쳐 타입을 바꿔주어야 함
void Texture::CreateView()
{
...
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = _image.GetMetadata().format;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
...
}
D3D12_SRV_DIMENSION_TEXTURE2D 타입이 아닌 D3D12_SRV_DIMENSION_TEXTURECUBE 사용
void Shader::Init(const wstring& path)
{
...
_pipelineDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
_pipelineDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
_pipelineDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
...
}
skybox를 만들기 위해 RasterizerState와 DepthStencilState 수정 필요
explicit CD3DX12_RASTERIZER_DESC(CD3DX12_DEFAULT)
{
FillMode = D3D12_FILL_MODE_SOLID;
CullMode = D3D12_CULL_MODE_BACK;
FrontCounterClockwise = FALSE;
DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
DepthClipEnable = TRUE;
MultisampleEnable = FALSE;
AntialiasedLineEnable = FALSE;
ForcedSampleCount = 0;
ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
}
typedef
enum D3D12_CULL_MODE
{
D3D12_CULL_MODE_NONE = 1,
D3D12_CULL_MODE_FRONT = 2,
D3D12_CULL_MODE_BACK = 3
} D3D12_CULL_MODE;
RasterizerState의 cull mode
cull mode => 스킵 모드
default는 back으로 메시의 뒷부분은 스킵한다는 뜻
FrontCounterClockwise는 메시의 정점 순서가 반시계 방향이냐 시계 방향이냐를 의미
카메라는 skybox 안에 존재하기 때문에 skybox 내부를 텍스쳐로 감싸야 함
shaer 클래스 수정
enum class RASTERIZER_TYPE
{
CULL_NONE,
CULL_FRONT,
CULL_BACK,
WIREFRAME,
};
enum class DEPTH_STENCIL_TYPE
{
LESS,
LESS_EQUAL,
GREATER,
GREATER_EQUAL,
};
struct ShaderInfo
{
RASTERIZER_TYPE rasterizerType = RASTERIZER_TYPE::CULL_BACK;
DEPTH_STENCIL_TYPE depthStencilType = DEPTH_STENCIL_TYPE::LESS;
};
기존 Depth Stencil Buffer를 구현할 때 버퍼의 초기 값을 1로 하도록 함
skybox의 depth가 1일 때 1은 1보다 작지 않아 그려지지 않기 때문에
1보다 더 작거나 같은 물체를 그리도록 해야함
=> 연산 방법을 less equal로 수정
void Shader::Init(const wstring& path, ShaderInfo info)
{
...
switch (info.rasterizerType)
{
case RASTERIZER_TYPE::CULL_BACK:
_pipelineDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
_pipelineDesc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK;
break;
case RASTERIZER_TYPE::CULL_FRONT:
_pipelineDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
_pipelineDesc.RasterizerState.CullMode = D3D12_CULL_MODE_FRONT;
break;
...
}
switch (info.depthStencilType)
{
case DEPTH_STENCIL_TYPE::LESS:
_pipelineDesc.DepthStencilState.DepthEnable = TRUE;
_pipelineDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
break;
case DEPTH_STENCIL_TYPE::LESS_EQUAL:
_pipelineDesc.DepthStencilState.DepthEnable = TRUE;
_pipelineDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
break;
...
}
...
}
ShaderInfo에 따라 RasterizerState와 DepthStencilState를 덮어쓰도록 함
VS_OUT VS_Main(VS_IN input)
{
...
float4 viewPos = mul(float4(input.localPos, 0), g_matView);
float4 clipSpacePos = mul(viewPos, g_matProjection);
output.pos = clipSpacePos.xyww;
output.uv = input.uv;
return output;
}
float4 PS_Main(VS_OUT input) : SV_Target
{
float4 color = g_tex_0.Sample(g_sam_0, input.uv);
return color;
}
skybox를 위한 쉐이더 파일을 구현
output.pos를 (x,y,w,w) 벡터를 사용하여 screen space로 투영 될 때,
w로 나눠지며 z값이 항상 1이 됨