응애맘마조

231017 강의 본문

공부/3D강의

231017 강의

TH.Wert 2023. 10. 17. 22:31

테셀레이션에 대해서 강의했습니다. 삼각형을 여러 개의 조각으로 나누었다고 볼 수 있으며 조각이 늘어났음에도 정점 개수는 그대로이기 때문에 FPS가 줄어들지 않고 많을수록 더 현실적인 그래픽으로 나타낼 수 있습니다. 이번 테셀레이션은 개념적으로만 설명하고 넘어간다고 했습니다.

#include "Common.hlsl"

struct VertexInput
{
    float4 Position : POSITION0;
};

struct CHullOutput
{
    float edgeTessFactor[3] : SV_TessFactor;
    float insideTessFactor : SV_InsideTessFactor;
};

struct HullOutput
{
    float4 Position : POSITION;
};

struct PixelInput
{
    float4 Position : SV_POSITION;
};

#define NUM_CONTROL_POINTS 3

cbuffer EdgeInfo : register(b10)
{
    float3 edges;
    float inside;
}

VertexInput VS(VertexInput input)
{
    return input;
}

CHullOutput CHS(InputPatch<VertexInput, NUM_CONTROL_POINTS> input)
{
    CHullOutput output;

    output.edgeTessFactor[0] = edges.x;
    output.edgeTessFactor[1] = edges.y;
    output.edgeTessFactor[2] = edges.z;
    output.insideTessFactor = inside;

    return output;
}

[domain("tri")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("CHS")]
HullOutput HS(InputPatch<VertexInput, NUM_CONTROL_POINTS> input,
	uint i : SV_OutputControlPointID)
{
    HullOutput output;

    output.Position = input[i].Position;

    return output;
}

[domain("tri")]
PixelInput DS(CHullOutput input, float3 uvw : SV_DomainLocation,
	const OutputPatch<HullOutput, NUM_CONTROL_POINTS> patch)
{
    PixelInput output;

    float4 pos = patch[0].Position * uvw.x + patch[1].Position * uvw.y + patch[2].Position * uvw.z;
    output.Position = float4(pos.xyz, 1.0f);

    return output;
}

float4 PS(PixelInput input) : SV_TARGET
{
    return float4(1, 1, 0, 1);
}

삼각형을 나타내기 위한 hlsl입니다.

#pragma once
class Scene1 : public Scene
{
private:
	Camera* cam;
	Mesh* mesh;
	Shader* shader;

	struct EdgeBuffer
	{
		Vector3 edges;
		float inside;
	}edgeBufferDesc;

	ID3D11Buffer* edgeBuffer;

public:
	Scene1();
	~Scene1();
	virtual void Init() override;
	virtual void Release() override;
	virtual void Update() override;
	virtual void LateUpdate() override;
	virtual void PreRender() override;
	virtual void Render() override;
	virtual void ResizeScreen() override;
};
#include "stdafx.h"

Scene1::Scene1()
{
    cam = Camera::Create();
    cam->LoadFile("Cam.xml");
    Camera::main = cam;

    shader = new Shader();
    shader->LoadFile("TessTri.hlsl");
    shader->LoadTessellation();

    int vertexCount = 3;
    VertexP* vertices = new VertexP[vertexCount];
    vertices[0] = Vector3(0, 0.9, 0);
    vertices[1] = Vector3(0.9, -0.9, 0);
    vertices[2] = Vector3(-0.9, -0.9, 0);

    int indexCount = 3;
    UINT* indices = new UINT[indexCount];
    indices[0] = 0;
    indices[1] = 1;
    indices[2] = 2;

    mesh = new Mesh(vertices, vertexCount, indices, indexCount, VertexType::P);
    mesh->primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST;

    edgeBufferDesc.edges.x = 1;
    edgeBufferDesc.edges.y = 1;
    edgeBufferDesc.edges.z = 1;
    edgeBufferDesc.inside = 1;

    {
        D3D11_BUFFER_DESC desc = { 0 };
        desc.ByteWidth = sizeof(EdgeBuffer);
        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, &edgeBuffer);
        assert(SUCCEEDED(hr));
    }
}

Scene1::~Scene1()
{
    cam->Release();
}

void Scene1::Init()
{
}

void Scene1::Release()
{
}

void Scene1::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();

    LIGHT->RenderDetail();
    ImGui::Text("FPS: %d", TIMER->GetFramePerSecond());
 
    ImGui::Begin("Hierarchy");  
    cam->RenderHierarchy();
    ImGui::End();
}

void Scene1::LateUpdate()
{
    ImGui::DragFloat("Edge0", &edgeBufferDesc.edges.x);
    ImGui::DragFloat("Edge1", &edgeBufferDesc.edges.y);
    ImGui::DragFloat("Edge2", &edgeBufferDesc.edges.z);
    ImGui::DragFloat("Inside0", &edgeBufferDesc.inside);
}

void Scene1::PreRender()
{
}

void Scene1::Render()
{
    LIGHT->Set();
    Camera::main->Set();
    RASTER->Set(D3D11_CULL_NONE, D3D11_FILL_WIREFRAME);
    {
        //상수버퍼
        D3D11_MAPPED_SUBRESOURCE mappedResource;
        D3D->GetDC()->Map(edgeBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
        memcpy_s(mappedResource.pData, sizeof(EdgeBuffer), &edgeBufferDesc, sizeof(EdgeBuffer));
        D3D->GetDC()->Unmap(edgeBuffer, 0);
        D3D->GetDC()->HSSetConstantBuffers(10, 1, &edgeBuffer);
    }
    shader->Set();
    mesh->Set();
    D3D->GetDC()->Draw(3, 0);
}

void Scene1::ResizeScreen()
{
    cam->width = App.GetWidth();
    cam->height = App.GetHeight();
    cam->viewport.width = App.GetWidth();
    cam->viewport.height = App.GetHeight();
}

메인에서 실행될 클래스입니다.

테셀레이션으로 조각으로 나누는 모습

내일 마저 끝낸다고 했고 테셀레이션에 대해 조금 더 한다고 했습니다.

읽어주셔서 감사합니다.

'공부 > 3D강의' 카테고리의 다른 글

231013 강의  (0) 2023.10.13
231012 강의  (0) 2023.10.12
231011 강의  (0) 2023.10.11
231010 강의  (0) 2023.10.11
231006 강의  (1) 2023.10.06
Comments