응애맘마조

230712 강의 본문

공부/3D강의

230712 강의

TH.Wert 2023. 7. 12. 16:43

그동안 맵을 로드하고 노멀을 넣고 캐릭터가 움직이는 것들은 해왔지만 터레인에 대하여 맵을 에디트하고 수정하는 것들은 하나도 하지 않아서 오늘부터 들어가서 강의했습니다. 어제 과제로 조사한 컴퓨트 셰이더와 관련이 있습니다. 컴퓨트 셰이더에 관련된 게시글은 https://keisukeaso.tistory.com/222 여기를 참고해 주시면 됩니다.

//읽기용
struct InputDesc
{
    uint index;
    float3 v0;
    float3 v1;
    float3 v2;
};
StructuredBuffer<InputDesc> input; //srv

//읽기 쓰기용
struct OutputDesc
{
    int picked;
    float u;
    float v;
    float distance;
};
RWStructuredBuffer<OutputDesc> output; //uav

cbuffer Ray : register(b0)
{
    float3 position;
    float outputSize;

    float3 direction;
}

void IntersectTri(uint index)
{
    float3 A = input[index].v0;
    float3 B = input[index].v1;
    float3 C = input[index].v2;
    
    float3 e1 = B - A;
    float3 e2 = C - A;

    float3 P, T, Q;
    P = cross(direction, e2);

    float d = 1.0f / dot(e1, P);

    T = position - A;
    output[index].u = dot(T, P) * d;

    Q = cross(T, e1);
    output[index].v = dot(direction, Q) * d;
    output[index].distance = dot(e2, Q) * d;

    bool b = (output[index].u >= 0.0f) &&
        (output[index].v >= 0.0f) &&
        (output[index].u + output[index].v <= 1.0f) &&
        (output[index].distance >= 0.0f);

    output[index].picked = b ? (1 + input[index].index) : 0;
}

[numthreads(32, 32, 1)]
void CS(uint3 groupID : SV_GroupID,
    uint groupIndex : SV_GroupIndex)
{
    //내가 한스레드당 첫번쨰 삼각형부터 계산을했을때
    //내가 지금 접근한 삼각형의 인덱스
    uint index
    //                          0 ~ 1023
        = groupID.x * 32 * 32 + groupIndex;

    if (outputSize > index)
        IntersectTri(index);
}

hlsl파일입니다. 그전에 했었던 코드와는 다르게 common.hlsl이 없습니다. 말 그대로 읽고 쓰기만 하는 것이기 때문에 그렇습니다. 그동안 사용했던 레이도 상수버퍼로 취급하여 사용하게 됩니다. numthreads는 32로 뒀는데 32 X 32 = 1024라서 최대로 쓸 수 있는 만큼 사용하기 위해 가장 큰 값으로 뒀습니다. 이번에는 터레인도 따로 클래스화 했습니다.

#pragma once

class Terrain : public Actor
{
    struct InputDesc
    {
        UINT index;
        Vector3 v0, v1, v2;
    };
    
    struct OutputDesc
    {
        int picked;
        float u, v, distance;
    };
    
    struct RayDesc
    {
        Vector3 position;
        float size;
        Vector3 direction;
        float padding;
    };
    
    static ID3D11ComputeShader* computeShader;
public:
    static void		CreateStaticMember();
    static void		DeleteStaticMember();
    static Terrain* Create(string Name = "Terrain", int	terrainSize = 257, float uvScale = 1.0f);
private:
    //compute Input
    InputDesc* inputArray;
    ID3D11Resource* input;
    ID3D11ShaderResourceView* srv = nullptr;//읽기전용
    
    //compute Output
    OutputDesc* outputArray;
    ID3D11Resource* output;
    ID3D11UnorderedAccessView* uav;//읽기쓰기 둘다가능
    
    //copy용
    ID3D11Resource* result;
    //ray
    RayDesc                     ray;
    ID3D11Buffer*               rayBuffer;
    
public:
    Terrain(string Name);

    float                       uvScale;
    int                         triSize;

    void            CreateMesh(int Size = 257);
    //CS
    void            CreateStructuredBuffer();
    void            DeleteStructuredBuffer();

    bool            ComPutePicking(Ray WRay, OUT Vector3& HitPoint);
    void            Render() override;
};
#include "framework.h"

ID3D11ComputeShader* Terrain::computeShader = nullptr;

void Terrain::CreateStaticMember()
{
    ID3D10Blob* CsBlob;

    wstring path = L"../Shaders/ComputeShader.hlsl";

    DWORD flags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_DEBUG;

    D3DCompileFromFile(path.c_str(), nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
        "CS", "cs_5_0", flags, 0, &CsBlob, nullptr);

    D3D->GetDevice()->CreateComputeShader(CsBlob->GetBufferPointer(), CsBlob->GetBufferSize(),
        nullptr, &computeShader);
}

void Terrain::DeleteStaticMember()
{
    SafeRelease(computeShader);
}

Terrain* Terrain::Create(string Name, int terrainSize, float uvScale)
{
    return nullptr;
}

Terrain::Terrain(string Name)
{
}

void Terrain::CreateMesh(int Size)
{
}

void Terrain::CreateStructuredBuffer()
{
}

void Terrain::DeleteStructuredBuffer()
{
}

bool Terrain::ComPutePicking(Ray WRay, OUT Vector3& HitPoint)
{
    //쉐이더부터 준비
    D3D->GetDC()->CSSetShader(computeShader, 0, 0);

    //raybuffer binding
    ray.position = WRay.position;
    ray.direction = WRay.direction;
    ray.size = (float)triSize;//삼각형갯수
    Matrix inverse = W.Invert();
    ray.direction = Vector3::TransformNormal(ray.direction, inverse);
    ray.direction.Normalize();
    ray.position = Vector3::Transform(ray.position, inverse);

    //트랜스폼한 Ray를 상수버퍼로 바인딩
    D3D->GetDC()->UpdateSubresource(rayBuffer, 0, NULL, &ray, 0, 0);

    D3D->GetDC()->CSSetConstantBuffers(0, 1, &rayBuffer);

    //input binding
    D3D->GetDC()->CSSetShaderResources(0, 1, &srv);
    //output binding
    D3D->GetDC()->CSSetUnorderedAccessViews(0, 1, &uav, nullptr);

    //멀티스레딩
    //shader 실행
    //올림
    UINT x = (UINT)ceil((float)triSize / 1024.0f);
    D3D->GetDC()->Dispatch(x, 1, 1);

    //동기화

    //gpu -> cpu 복사
    D3D->GetDC()->CopyResource(result, output);

    D3D11_MAPPED_SUBRESOURCE subResource;

    D3D->GetDC()->Map(result, 0, D3D11_MAP_READ, 0, &subResource);
    memcpy(outputArray, subResource.pData, sizeof(OutputDesc) * triSize);
    D3D->GetDC()->Unmap(result, 0);

    float minDistance = FLT_MAX;
    int minIndex = -1;
    
    for (int i = 0; i < triSize; i++)
    {
        OutputDesc temp = outputArray[i];
        if (temp.picked)
        {
            if (minDistance > temp.distance)
            {
                minDistance = temp.distance;
                minIndex = i;
            }
        }
    }
    
    if (minIndex >= 0)
    {
        HitPoint = ray.position + ray.direction
            * minDistance;
        HitPoint = Vector3::Transform(HitPoint, W);
        return true;
    }
    return false;
}

void Terrain::Render()
{
}

현재까지 진행한 터레인의 헤더와 cpp 파일입니다. 아직 완성되지 않아 내일 완성될 것 같습니다. CPU와 GPU의 사이에서 메모리를 할당받고 읽기 전에 접근하지 못하도록 하는 방식으로 진행하게 될 것 같습니다.

 

읽어주셔서 감사합니다.

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

230714 강의  (0) 2023.07.14
230713 강의  (0) 2023.07.13
230711 강의  (0) 2023.07.11
230710 강의  (0) 2023.07.10
230707 강의  (0) 2023.07.07