우선 float값의 데이터를 주고 받는게 아닌 텍스처를 주고 받는 형식의 TextureBuffer를 만들어보자
RawBuffer와 크게 다르지 않다.(input, output)#pragma once
class TextureBuffer
{
public:
TextureBuffer(ComPtr<ID3D11Texture2D> src);
~TextureBuffer();
public:
void CreateBuffer();
private:
void CreateSRV();
void CreateOutput();
void CreateUAV();
void CreateResult();
public:
uint32 GetWidth() { return _width; }
uint32 GetHeight() { return _height; }
uint32 GetArraySize() { return _arraySize; }
ComPtr<ID3D11Texture2D> GetOutput() { return (ID3D11Texture2D*)_output.Get(); }
ComPtr<ID3D11ShaderResourceView> GetOutputSRV() { return _outputSRV; }
public:
ComPtr<ID3D11ShaderResourceView> GetSRV() { return _srv; }
ComPtr<ID3D11UnorderedAccessView> GetUAV() { return _uav; }
private:
ComPtr<ID3D11Texture2D> _input;
ComPtr<ID3D11ShaderResourceView> _srv; // Input
ComPtr<ID3D11Texture2D> _output;
ComPtr<ID3D11UnorderedAccessView> _uav; // Output
// 이미지와 관련된 여러가지 정보들
private:
uint32 _width = 0;
uint32 _height = 0;
uint32 _arraySize = 0;
DXGI_FORMAT _format;
ComPtr<ID3D11ShaderResourceView> _outputSRV;
};
#include "pch.h"
#include "TextureBuffer.h"
TextureBuffer::TextureBuffer(ComPtr<ID3D11Texture2D> src)
{
D3D11_TEXTURE2D_DESC srcDesc;
src->GetDesc(&srcDesc);
_width = srcDesc.Width;
_height = srcDesc.Height;
_arraySize = srcDesc.ArraySize;
_format = srcDesc.Format;
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Width = _width;
desc.Height = _height;
desc.ArraySize = _arraySize;
desc.Format = _format;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.MipLevels = 1;
desc.SampleDesc.Count = 1;
CHECK(DEVICE->CreateTexture2D(&desc, NULL, _input.GetAddressOf()));
DC->CopyResource(_input.Get(), src.Get());
CreateBuffer();
}
TextureBuffer::~TextureBuffer() { }
void TextureBuffer::CreateBuffer()
{
CreateSRV();
CreateOutput();
CreateUAV();
CreateResult();
}
void TextureBuffer::CreateSRV()
{
D3D11_TEXTURE2D_DESC desc;
_input->GetDesc(&desc);
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
srvDesc.Format = desc.Format;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
srvDesc.Texture2DArray.MipLevels = 1;
srvDesc.Texture2DArray.ArraySize = _arraySize;
CHECK(DEVICE->CreateShaderResourceView(_input.Get(), &srvDesc, _srv.GetAddressOf()));
}
void TextureBuffer::CreateOutput()
{
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
desc.Width = _width;
desc.Height = _height;
desc.ArraySize = _arraySize;
desc.Format = _format;
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
desc.MipLevels = 1;
desc.SampleDesc.Count = 1;
CHECK(DEVICE->CreateTexture2D(&desc, nullptr, _output.GetAddressOf()));
}
void TextureBuffer::CreateUAV()
{
D3D11_TEXTURE2D_DESC desc;
_output->GetDesc(&desc);
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
ZeroMemory(&uavDesc, sizeof(D3D11_UNORDERED_ACCESS_VIEW_DESC));
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
uavDesc.Texture2DArray.ArraySize = _arraySize;
CHECK(DEVICE->CreateUnorderedAccessView(_output.Get(), &uavDesc, _uav.GetAddressOf()));
}
void TextureBuffer::CreateResult()
{
D3D11_TEXTURE2D_DESC desc;
_output->GetDesc(&desc);
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
srvDesc.Format = desc.Format;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
srvDesc.Texture2DArray.MipLevels = 1;
srvDesc.Texture2DArray.ArraySize = _arraySize;
CHECK(DEVICE->CreateShaderResourceView(_output.Get(), &srvDesc, _outputSRV.GetAddressOf()));
}
SetSRV()함수 추가class Texture : public ResourceBase
{
public:
ComPtr<ID3D11Texture2D> GetTexture2d();
void SetSRV(ComPtr<ID3D11ShaderResourceView> srv) { _shaderResourveView = srv; }
}
ComPtr<ID3D11Texture2D> Texture::GetTexture2d()
{
ComPtr<ID3D11Texture2D> texture;
_shaderResourveView->GetResource((ID3D11Resource**)texture.GetAddressOf());
return texture;
}
(32, 32, 1)로 설정Texture2DArray<float4> Input;
RWTexture2DArray<float4> Output;
[numthreads(32, 32, 1)] // 쓰레드의 개수를 의미 ( 10 x 8 x 3 = 240개)
void CS(uint3 id : SV_DispatchThreadID)
{
float4 color = Input.Load(int4(id, 0)); // 쓰레드 넘버링값에 해당하는 정보 추출
//Output[id] = color;
Output[id] = 1.0f - color; // 반전
//Output[id] = (color.r + color.g + color.b) / 3.0f; // 회색풍
}
technique11 T0
{
pass P0
{
SetVertexShader(NULL);
SetPixelShader(NULL);
SetComputeShader(CompileShader(cs_5_0, CS()));
}
};
(witdh or height + 쓰레드 수 -1) / 쓰레드 수로 처리해주자#include "pch.h"
#include "TextureBufferDemo.h"
#include "GeometryHelper.h"
#include "Camera.h"
#include "GameObject.h"
#include "CameraScript.h"
#include "MeshRenderer.h"
#include "Mesh.h"
#include "Material.h"
#include "Model.h"
#include "ModelRenderer.h"
#include "ModelAnimator.h"
#include "Mesh.h"
#include "Transform.h"
#include "VertexBuffer.h"
#include "IndexBuffer.h"
#include "Light.h"
#include "TextureBuffer.h"
void TextureBufferDemo::Init()
{
//RESOURCES->Init();
auto newSrv = MakeComputeShaderTexture();
_shader = make_shared<Shader>(L"23.RenderDemo.fx");
// Camera
{
auto camera = make_shared<GameObject>();
camera->GetOrAddTransform()->SetPosition(Vec3{ 0.f, 0.f, -5.f });
camera->AddComponent(make_shared<Camera>());
camera->AddComponent(make_shared<CameraScript>());
CUR_SCENE->Add(camera);
}
// Light
{
auto light = make_shared<GameObject>();
light->AddComponent(make_shared<Light>());
LightDesc lightDesc;
lightDesc.ambient = Vec4(0.4f);
lightDesc.diffuse = Vec4(1.f);
lightDesc.specular = Vec4(0.1f);
lightDesc.direction = Vec3(1.f, 0.f, 1.f);
light->GetLight()->SetLightDesc(lightDesc);
CUR_SCENE->Add(light);
}
// Mesh
// Material
{
shared_ptr<Material> material = make_shared<Material>();
material->SetShader(_shader);
auto texture = make_shared<Texture>();
texture->SetSRV(newSrv);
material->SetDiffuseMap(texture);
MaterialDesc& desc = material->GetMaterialDesc();
desc.ambient = Vec4(1.f);
desc.diffuse = Vec4(1.f);
desc.specular = Vec4(1.f);
RESOURCES->Add(L"Veigar", material);
}
for (int32 i = 0; i < 100; i++)
{
auto obj = make_shared<GameObject>();
obj->GetOrAddTransform()->SetLocalPosition(Vec3(rand() % 100, 0, rand() % 100));
obj->AddComponent(make_shared<MeshRenderer>());
{
obj->GetMeshRenderer()->SetMaterial(RESOURCES->Get<Material>(L"Veigar"));
}
{
auto mesh = RESOURCES->Get<Mesh>(L"Sphere");
obj->GetMeshRenderer()->SetMesh(mesh);
obj->GetMeshRenderer()->SetPass(0);
}
CUR_SCENE->Add(obj);
}
//RENDER->Init(_shader);
}
void TextureBufferDemo::Update()
{
}
void TextureBufferDemo::Render()
{
}
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> TextureBufferDemo::MakeComputeShaderTexture()
{
auto shader = make_shared<Shader>(L"26.TextureBufferDemo.fx");
auto texture = RESOURCES->Load<Texture>(L"Veigar", L"..\\Resources\\Textures\\veigar.jpg");
shared_ptr<TextureBuffer> textureBuffer = make_shared<TextureBuffer>(texture->GetTexture2d());
shader->GetSRV("Input")->SetResource(textureBuffer->GetSRV().Get());
shader->GetUAV("Output")->SetUnorderedAccessView(textureBuffer->GetUAV().Get());
uint32 width = textureBuffer->GetWidth();
uint32 height = textureBuffer->GetHeight();
uint32 arraySize = textureBuffer->GetArraySize();
uint32 x = max(1, (width + 31) / 32);
uint32 y = max(1, (height + 31) / 32);
shader->Dispatch(0, 0, x, y, arraySize);
return textureBuffer->GetOutputSRV();
}
