DevLog/D2D11 프로젝트

[Devlog-DX11] HOLLOW KNIGHT 모작 - Video - 블러 처리 시도

뽀또치즈맛 2024. 10. 19. 00:18

 
 
Blur 처리
 
박스 블러 코드는 적용했고,
일단 돌아는 가는데 박스 블러 효과를 볼 순 없었다.
그리고 무엇보다
가장 큰 단점으로는
pixel.size를 너무 크게 잡았기 때문인지,

원래는 vector4 하나만 받아서 처리하다가

pixel vector모든 부분에 대해서 동적 할당을 하다보니,

4897408개의 픽셀을 계산하게 되어
버벅거리는 현상이 짙다.
 
블러 이미지클래스를 만들어준 뒤
다음과 같은 코드를 추가해주었다.
결과적으로 렌더 함수는 돌고 있지만,
뭔가 그려주는 함수가 잘 작동하지 않는 것 같았다.
 
나중에 쉐이더책 보고 dx에 대한 내공좀 쌓은 뒤 다시 도전해야겠다.
 
 

 
 
 

#include "framework.h"

#include <omp.h>
#include <stb_image.h>
#include <stb_image_write.h>

ID3D11Buffer* BlurImage::vertexBuffer = nullptr;
ID3D11Buffer* BlurImage::uvBuffer = nullptr;

void BlurImage::CreateStaticMember()
{
    VertexPT* Vertex;

    Vertex = new VertexPT[4];
    //VertexCount = 4;
    //시계방향으로 정점찍기
  ...

    //CreateVertexBuffer
    {
        D3D11_BUFFER_DESC desc;
        desc = { 0 };
        desc.Usage = D3D11_USAGE_DEFAULT;//버퍼를 읽고 쓰는 방법
        desc.ByteWidth = sizeof(VertexPT) * 4; //버퍼 크기 (바이트)입니다.
        desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;//버퍼가 파이프 라인에 바인딩되는 방법을 식별하십시오

        D3D11_SUBRESOURCE_DATA data = { 0 };
        //하위 리소스를 초기화하기위한 데이터를 지정합니다.
        data.pSysMem = Vertex;
        //초기화 데이터의 포인터.

        //버퍼 만들기
        HRESULT hr = D3D->GetDevice()->CreateBuffer(&desc, &data, &vertexBuffer);
        assert(SUCCEEDED(hr));
    }

    delete[] Vertex;
    //CreateConstantBuffer
    {
        D3D11_BUFFER_DESC desc = { 0 };
        desc.ByteWidth = sizeof(Vector4);
        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, &uvBuffer);
        assert(SUCCEEDED(hr));
    }
    D3D->GetDC()->VSSetConstantBuffers(2, 1, &uvBuffer);
}

void BlurImage::DeleteStaticMember()
{
    vertexBuffer->Release();
    uvBuffer->Release();
}

BlurImage::BlurImage(wstring file)
{
    ...

    //텍스쳐 로드
    SRV = TEXTURE->LoadTexture(file);
    imageSize = TEXTURE->GetTextureSize(file);

    //           (최소좌표)   (최대좌표)
    uv = Vector4(0.0f, 0.0f, 1.0f, 1.0f);
    ScratchImage* image = TEXTURE->GetTexture(file).image;

    pixels.resize(imageSize.x * imageSize.y);

    unsigned char* img = image->GetPixels();

    for (long long i = 0; i < pixels.size(); i++) {
        pixels[i].x = img[i * 3] / 250.f;
        pixels[i].y = img[i * 3 + 1] / 255.0f;
        pixels[i].z = img[i * 3 + 2] / 255.0f;
        pixels[i].w = 0.5f;
    }

    animTime = 0.0f;
    animInterval = 0.0f;
    animXAxis = true;
    maxFrame = Int2(1, 1);
    frame = Int2(0, 0);
    reverseLR = false;
    this->file = file;

}

BlurImage::~BlurImage()
{
    sampler->Release();
}

Vector4& BlurImage::GetPixel(int i, int j)
{
    i = clamp(i, 0, imageSize.x - 1);
    j = clamp(j, 0, imageSize.y - 1);

    return this->pixels[i + imageSize.x * j];
}

void BlurImage::Render()
{
    if (!isVisible)return;
    GameObject::Render();
    imageShader->Set();
    PlayAnim();
    BoxBlur5();

    size_t bufferSize = pixels.size() * sizeof(Vector4);

    // D3D11 버퍼 설명 구조체 설정
    D3D11_BUFFER_DESC bufferDesc = {};
    bufferDesc.Usage = D3D11_USAGE_DYNAMIC;                   // 동적 사용 설정
    bufferDesc.ByteWidth = static_cast<UINT>(bufferSize);     // 버퍼 크기 설정 (픽셀 데이터의 전체 크기)
    bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;          // Vertex 버퍼로 사용할 경우, 필요한 경우 다른 용도로 설정 가능
    bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;       // CPU에서 쓰기 가능 설정
    bufferDesc.MiscFlags = 0;                                 // 추가 플래그 없음

    // uvBuffer 생성
    HRESULT hr = D3D->GetDevice()->CreateBuffer(&bufferDesc, nullptr, &uvBuffer);
    if (FAILED(hr)) {
        std::cerr << "Failed to create uvBuffer. HRESULT: " << hr << std::endl;
        return;  // 실패 시 예외 처리 또는 함수 종료
    }

    // 데이터를 GPU에 쓰기 위해 uvBuffer 매핑
    D3D11_MAPPED_SUBRESOURCE mappedResource;
    hr = D3D->GetDC()->Map(uvBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    if (FAILED(hr)) {
        std::cerr << "Failed to map uvBuffer. HRESULT: " << hr << std::endl;
        return;  // 실패 시 예외 처리 또는 함수 종료
    }

    // pixels의 데이터를 uvBuffer에 복사
    memcpy_s(mappedResource.pData, bufferSize, pixels.data(), bufferSize);

    // 매핑 해제
    D3D->GetDC()->Unmap(uvBuffer, 0);


    UINT stride = sizeof(VertexPT);
    UINT offset = 0;

    D3D->GetDC()->PSSetShaderResources(0, 1, &SRV);
    D3D->GetDC()->PSSetSamplers(0, 1, &sampler);
    D3D->GetDC()->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
    D3D->GetDC()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
    D3D->GetDC()->Draw(4, 0);
}

void BlurImage::ChangeAnim(ANIMSTATE anim, float interval, bool xAxis)
{
   ...
}

void BlurImage::ChangeSampler(D3D11_FILTER filter, D3D11_TEXTURE_ADDRESS_MODE addressU, D3D11_TEXTURE_ADDRESS_MODE addressV)
{
   ...
}

void BlurImage::BoxBlur5()
{
    std::vector<Vector4> pixelsBuffer(this->pixels.size());

    for (int j = 0; j < imageSize.y; j++)
    {
        for (int i = 0; i < imageSize.x; i++)
        {
            // 주변 픽셀들의 색을 평균내어서 (i, j)에 있는 픽셀의 색을 변경
            // this->pixels로부터 읽어온 값들을 평균내어서 pixelsBuffer의 값들을 바꾸기

            Color neighborColorSum{ 0.0f,0.0f,0.0f,0.5f };
            for (int si = 0; si < 5; si++)
            {
                Color neighborColor = this->GetPixel(i + si - 2, j);
                neighborColorSum.x += neighborColor.x;
                neighborColorSum.y += neighborColor.y;
                neighborColorSum.z += neighborColor.z;
            }

            pixelsBuffer[i + imageSize.x * j].x = neighborColorSum.x * 0.2f;
            pixelsBuffer[i + imageSize.x * j].y = neighborColorSum.y * 0.2f;
            pixelsBuffer[i + imageSize.x * j].z = neighborColorSum.z * 0.2f;
        }
    }
    std::swap(this->pixels, pixelsBuffer);

    for (int j = 0; j < imageSize.y; j++)
    {
        for (int i = 0; i < imageSize.x; i++)
        {
            // 주변 픽셀들의 색을 평균내어서 (i, j)에 있는 픽셀의 색을 변경
            // this->pixels로부터 읽어온 값들을 평균내어서 pixelsBuffer의 값들을 바꾸기
            Color neighborColorSum{ 0.0f,0.0f,0.0f,0.5f };
            for (int si = 0; si < 5; si++)
            {
                Color neighborColor = this->GetPixel(i, j + si - 2);
                neighborColorSum.x += neighborColor.x;
                neighborColorSum.y += neighborColor.y;
                neighborColorSum.z += neighborColor.z;
            }

            pixelsBuffer[i + imageSize.x * j].x = neighborColorSum.x * 0.2f;
            pixelsBuffer[i + imageSize.x * j].y = neighborColorSum.y * 0.2f;
            pixelsBuffer[i + imageSize.x * j].z = neighborColorSum.z * 0.2f;
        }
    }

    // Swap
    std::swap(this->pixels, pixelsBuffer);
}