Skip to content

Commit

Permalink
Got batch rendering textures working
Browse files Browse the repository at this point in the history
  • Loading branch information
tomheeleynz committed Jul 23, 2023
1 parent fb277f1 commit ee19b2b
Show file tree
Hide file tree
Showing 13 changed files with 180 additions and 14 deletions.
1 change: 1 addition & 0 deletions Arcane/src/Arcane/ECS/Component.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ namespace Arcane
struct SpriteRendererComponent
{
glm::vec3 color = {1.0f, 1.0f, 1.0f};
Texture* sprite = nullptr;
};

struct RigidBodyComponent
Expand Down
4 changes: 4 additions & 0 deletions Arcane/src/Arcane/Platform/OpenGL/OpenGLDescriptorSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ namespace Arcane

}

void OpenGLDescriptorSet::AddImageSamplerArray(std::vector<Texture*> textures, uint32_t setNum, uint32_t bindingNum)
{
}

void OpenGLDescriptorSet::BindTextures(uint32_t shaderID)
{
int textureCount = 0;
Expand Down
1 change: 1 addition & 0 deletions Arcane/src/Arcane/Platform/OpenGL/OpenGLDescriptorSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace Arcane
void AddImageSampler(Texture* texture, uint32_t setNum, uint32_t bindingNum) override;
void AddImageSampler(Framebuffer* framebuffer, uint32_t setNum, uint32_t bindingNum) override;
void AddUniformBuffer(UniformBuffer* buffer, uint32_t setNum, uint32_t bindingNum) override;
void AddImageSamplerArray(std::vector<Texture*> textures, uint32_t setNum, uint32_t bindingNum) override;

// OpenGL Specific Functions
void BindTextures(uint32_t shaderID);
Expand Down
2 changes: 1 addition & 1 deletion Arcane/src/Arcane/Platform/Vulkan/VulkanRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ namespace Arcane {
VulkanSet* vulkanSet = static_cast<VulkanSet*>(descriptorSets[j]);

// Bind Descriptor Sets
vkCmdBindDescriptorSets(swapChainBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, vulkanPipeline->GetLayout(), 0, 1, &vulkanSet->GetDescriptorSets()[i], 0, nullptr);
vkCmdBindDescriptorSets(swapChainBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, vulkanPipeline->GetLayout(), vulkanSet->GetSetNumber(), 1, &vulkanSet->GetDescriptorSets()[i], 0, nullptr);
}

// Bind Index Buffer
Expand Down
40 changes: 40 additions & 0 deletions Arcane/src/Arcane/Platform/Vulkan/VulkanSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,4 +250,44 @@ namespace Arcane
vkUpdateDescriptorSets(context->GetDevice().GetLogicalDevice(), 1, &descriptorWrite, 0, nullptr);
}
}

void VulkanSet::AddImageSamplerArray(std::vector<Texture*> textures, uint32_t setNum, uint32_t bindingNum)
{
Application& app = Application::Get();
VulkanContext* context = static_cast<VulkanContext*>(Application::Get().GetWindow().GetContext());
VulkanSwapChain& swapchain = context->GetSwapChain();
uint32_t imageCount = swapchain.GetSwapChainImagesSize();

std::vector<VkDescriptorImageInfo> imageInfos;

for (int i = 0; i < textures.size(); i++)
{
if (textures[i] == nullptr)
break;

VulkanTexture* vulkanTexture = static_cast<VulkanTexture*>(textures[i]);

VkDescriptorImageInfo imageInfo;
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = vulkanTexture->GetImageDescriptorInfo().imageView;
imageInfo.sampler = vulkanTexture->GetImageDescriptorInfo().sampler;

imageInfos.push_back(imageInfo);
}

for (int i = 0; i < imageCount; i++) {
// Create a descriptor write, then update descriptor set
VkWriteDescriptorSet descriptorWrite{};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = m_DescriptorSets[i];
descriptorWrite.dstBinding = bindingNum;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrite.descriptorCount = imageInfos.size();
descriptorWrite.pImageInfo = imageInfos.data();

// Update Descriptor Sets
vkUpdateDescriptorSets(context->GetDevice().GetLogicalDevice(), 1, &descriptorWrite, 0, nullptr);
}
}
}
1 change: 1 addition & 0 deletions Arcane/src/Arcane/Platform/Vulkan/VulkanSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace Arcane
void AddUniformBuffer(UniformBuffer* buffer, uint32_t setNumber, uint32_t bindingNumber) override;
void AddImageSampler(Texture* texture, uint32_t setNumber, uint32_t bindingNumber) override;
void AddImageSampler(Framebuffer* framebuffer, uint32_t setNumber, uint32_t bindingNumber) override;
void AddImageSamplerArray(std::vector<Texture*> textures, uint32_t setNum, uint32_t bindingNum) override;

// Get Descriptor Set Layout
VkDescriptorSetLayout GetLayout() { return m_DescriptorSetLayout; }
Expand Down
18 changes: 18 additions & 0 deletions Arcane/src/Arcane/Platform/Vulkan/VulkanVertexDescriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ namespace Arcane {
{
switch (element)
{
case VertexType::integer:
{
stride += sizeof(int);
break;
}
case VertexType::float1:
{
stride += sizeof(float);
Expand Down Expand Up @@ -98,6 +103,19 @@ namespace Arcane {
m_AttributeDescriptions.push_back(attribDesc);
break;
}
case VertexType::integer:
{
VkVertexInputAttributeDescription attribDesc;
attribDesc.binding = 0;
attribDesc.location = location;
attribDesc.format = VK_FORMAT_R32_SINT;
attribDesc.offset = offset;

location++;
offset += sizeof(int);
m_AttributeDescriptions.push_back(attribDesc);
break;
}
default:
break;
}
Expand Down
1 change: 1 addition & 0 deletions Arcane/src/Arcane/Renderer/DescriptorSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace Arcane
public:
virtual void AddImageSampler(Texture* texture, uint32_t setNum, uint32_t bindingNum) = 0;
virtual void AddImageSampler(Framebuffer* framebuffer, uint32_t setNum, uint32_t bindingNum) = 0;
virtual void AddImageSamplerArray(std::vector<Texture*> textures, uint32_t setNum, uint32_t bindingNum) = 0;
virtual void AddUniformBuffer(UniformBuffer* buffer, uint32_t setNum, uint32_t bindingNum) = 0;

static DescriptorSet* Create(DescriptorSetSpecs& setSpecs, std::initializer_list<DescriptorLayoutSpecs> layoutSpecs);
Expand Down
77 changes: 70 additions & 7 deletions Arcane/src/Arcane/Renderer/SceneRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ namespace Arcane
{
glm::vec3 position;
glm::vec3 color;
glm::vec2 texCoord;
int texId;
};

enum class BatchTextureType
{
BASE,
ASSET
};

struct SceneRendererData
Expand Down Expand Up @@ -100,6 +108,10 @@ namespace Arcane
QuadVertex* quadVertices;
Shader* SpriteShader;
Pipeline* QuadPipeline;
DescriptorSet* QuadDescriptorSet;
Texture* QuadBaseTexture;
std::vector<Texture*> SpriteTextures;
std::vector<BatchTextureType> SpriteTextureTypes;
};

static SceneRendererData s_Data;
Expand Down Expand Up @@ -260,7 +272,7 @@ namespace Arcane

// Create per pass Descriptor
DescriptorSetSpecs compositeSetSpecs;
compositeSetSpecs.SetNumber = 1;
compositeSetSpecs.SetNumber = 0;
s_Data.CompositeDescriptorSet = DescriptorSet::Create(compositeSetSpecs, {
{0, 1, DescriptorType::SAMPLER, "Geo Framebuffer Texture", DescriptorLocation::FRAGMENT}
});
Expand Down Expand Up @@ -300,22 +312,41 @@ namespace Arcane

s_Data.QuadVertexDescriptor = VertexDescriptor::Create({
VertexType::float3,
VertexType::float3
VertexType::float3,
VertexType::float2,
VertexType::integer
});

s_Data.QuadVertexBuffer = VertexBuffer::Create(s_Data.quadVertices, s_Data.maxQuadVertices * sizeof(QuadVertex));
s_Data.QuadIndexBuffer = IndexBuffer::Create(s_Data.quadIndices, s_Data.maxQuads * 6);
s_Data.QuadVertexBuffer->AddIndexBuffer(s_Data.QuadIndexBuffer);

s_Data.SpriteShader = ShaderLibrary::GetShader("Sprite-Default");
s_Data.QuadBaseTexture = Texture::Create(255.0f, 255.0f, 255.0f, 255.0f);

s_Data.SpriteTextures.resize(32);
s_Data.SpriteTextureTypes.resize(32);

for (int i = 0; i < s_Data.SpriteTextures.size(); i++)
{
s_Data.SpriteTextures[i] = s_Data.QuadBaseTexture;
s_Data.SpriteTextureTypes[i] = BatchTextureType::BASE;
}

DescriptorSetSpecs quadSetSpecs;
quadSetSpecs.SetNumber = 1;
s_Data.QuadDescriptorSet = DescriptorSet::Create(quadSetSpecs, {
{0, 32, DescriptorType::SAMPLER, "sprites", DescriptorLocation::FRAGMENT}
});

s_Data.QuadDescriptorSet->AddImageSampler(s_Data.QuadBaseTexture, 1, 0);

PipelineSpecification quadPipelineSpecs;
quadPipelineSpecs.shader = s_Data.SpriteShader;
quadPipelineSpecs.renderPass = s_Data.GeometryRenderPass;
quadPipelineSpecs.descriptor = s_Data.QuadVertexDescriptor;
quadPipelineSpecs.DescriptorSets = { s_Data.GlobalDescriptorSet };
quadPipelineSpecs.DescriptorSets = { s_Data.GlobalDescriptorSet, s_Data.QuadDescriptorSet };
s_Data.QuadPipeline = Pipeline::Create(quadPipelineSpecs);

}

Framebuffer* SceneRenderer::GetFinalRenderFramebuffer()
Expand Down Expand Up @@ -372,15 +403,16 @@ namespace Arcane
});
}
}
if (m_RenderGrid)
Renderer::RenderQuad(s_Data.GridVertexBuffer, s_Data.GridPipleine, { s_Data.GlobalDescriptorSet });
/*if (m_RenderGrid)
Renderer::RenderQuad(s_Data.GridVertexBuffer, s_Data.GridPipleine, { s_Data.GlobalDescriptorSet });*/
}

// 2D Batch Render
{
if (s_Data.quadCount > 0) {
s_Data.QuadDescriptorSet->AddImageSamplerArray(s_Data.SpriteTextures, 1, 0);
s_Data.QuadVertexBuffer->SetData(s_Data.quadVertices, s_Data.quadCount * 4 * sizeof(QuadVertex));
Renderer::RenderQuad(s_Data.QuadVertexBuffer, s_Data.QuadPipeline, {s_Data.GlobalDescriptorSet});
Renderer::RenderQuad(s_Data.QuadVertexBuffer, s_Data.QuadPipeline, {s_Data.GlobalDescriptorSet, s_Data.QuadDescriptorSet});
}
}
Renderer::EndRenderPass(s_Data.GeometryRenderPass);
Expand Down Expand Up @@ -442,10 +474,41 @@ namespace Arcane
{1.0f, 1.0f}
};

int textureId = -1;
int lastBaseIndex = 0;

for (int i = 1; i < s_Data.SpriteTextures.size(); i++) {
if (spriteRendererComponent.sprite == nullptr) {
textureId = 0;
break;
}
else {
if (spriteRendererComponent.sprite->GetID() == s_Data.SpriteTextures[i]->GetID() && s_Data.SpriteTextureTypes[i] == BatchTextureType::ASSET)
{
textureId = i;
break;
}
else if (s_Data.SpriteTextureTypes[i] == BatchTextureType::BASE) {
lastBaseIndex = i;
break;
}
}
}

if (textureId == -1)
{
s_Data.SpriteTextures[lastBaseIndex] = spriteRendererComponent.sprite;
s_Data.SpriteTextureTypes[lastBaseIndex] = BatchTextureType::ASSET;
textureId = lastBaseIndex;
}


for (int i = 0; i < quadSize; i++) {
QuadVertex v;
v.position = translation * rotation * scale * s_Data.quadBase[i];
v.color = spriteRendererComponent.color;
v.texCoord = textureCoords[i];
v.texId = textureId;
s_Data.quadVertices[(s_Data.quadCount * 4) + i] = v;
}

Expand Down
3 changes: 2 additions & 1 deletion Arcane/src/Arcane/Renderer/VertexDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ namespace Arcane {
float1,
float2,
float3,
float4
float4,
integer
};


Expand Down
17 changes: 14 additions & 3 deletions EnchantingTable/src/EditorAssets/Shaders/Sprite.arcaneshader
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
layout (location = 3) in int aTexId;

layout (location = 0) out vec3 fragColor;

layout (location = 1) out vec2 fragTexCoord;
layout (location = 2) out flat int fragTexId;

// Global Frame data
layout (set = 0, binding = 0) uniform Camera {
mat4 proj;
Expand All @@ -16,16 +20,23 @@ layout (set = 0, binding = 0) uniform Camera {
void main() {
gl_Position = camera.proj * camera.view * vec4(aPos, 1.0);
fragColor = aColor;
fragTexCoord = aTexCoord;
fragTexId = aTexId;
}

#shader fragment
#version 450

layout(location = 0) in vec3 fragColor;
layout (location = 0) in vec3 fragColor;
layout (location = 1) in vec2 fragTexCoord;
layout (location = 2) in flat int fragTexId;

layout(location = 0) out vec4 Color;

layout(set = 1, binding = 0) uniform sampler2D sprites[32];

void main() {
// Final Color
Color = vec4(fragColor, 1.0);
Color = texture(sprites[fragTexId], fragTexCoord) * vec4(fragColor, 1.0);
}

2 changes: 1 addition & 1 deletion EnchantingTable/src/EditorLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void EditorLayer::OnAttach()
// Setup Camera Controller
if (dimensionType == Arcane::DimensionType::TwoD)
m_EditorCameraController = new OrthographicController();
else
else
//m_EditorCameraController = new OrthographicController();
m_EditorCameraController = new PerspectiveController();

Expand Down
27 changes: 26 additions & 1 deletion EnchantingTable/src/Panels/EntityPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,32 @@ void EntityPanel::DrawComponents(Arcane::Entity& entity)
});

DrawComponent<SpriteRendererComponent>("Sprite Renderer", entity, [this](auto& component, auto& entity) {
ImGui::ColorPicker3("Color", glm::value_ptr(entity.GetComponent<SpriteRendererComponent>().color));
ImGui::ColorPicker3("Color", glm::value_ptr(component.color));
ImGui::Text("Sprite");

if (component.sprite == nullptr) {
ImGui::Text("No Sprite");
}
else {
Arcane::UI::Image(component.sprite);
}

if (ImGui::BeginDragDropTarget())
{
const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("CURRENT_SELECTED_ASSET");

if (payload != nullptr) {
AssetInfo assetInfo = *static_cast<AssetInfo*>(payload->Data);
Asset* asset = Arcane::Application::Get().GetAssetDatabase().GetAsset(assetInfo.id);

if (asset != nullptr && asset->GetAssetType() == AssetType::TEXTURE)
{
Texture* texture = static_cast<Texture*>(asset);
component.sprite = texture;
}
}
ImGui::EndDragDropTarget();
}
});

DrawComponent<RigidBodyComponent>("Rigid Body", entity, [this](auto& component, auto& entity) {
Expand Down

0 comments on commit ee19b2b

Please sign in to comment.