diff --git a/engine/xe_descriptors.cpp b/engine/xe_descriptors.cpp index 367b26e..00e627a 100644 --- a/engine/xe_descriptors.cpp +++ b/engine/xe_descriptors.cpp @@ -10,9 +10,9 @@ DescriptorSetLayout::Builder &DescriptorSetLayout::Builder::addBinding( uint32_t binding, VkDescriptorType descriptorType, VkShaderStageFlags stageFlags, - VkSampler *sampler) { + VkSampler *sampler, + uint32_t count) { assert(bindings.count(binding) == 0 && "Binding already in use"); - uint32_t count = 1; VkDescriptorSetLayoutBinding layoutBinding{}; layoutBinding.binding = binding; layoutBinding.descriptorType = descriptorType; @@ -167,6 +167,24 @@ DescriptorWriter &DescriptorWriter::writeImage( return *this; } +DescriptorWriter &DescriptorWriter::writeImageArray( + uint32_t binding, std::vector *imageInfos) { + assert(setLayout.bindings.count(binding) == 1 && "Layout does not contain specified binding"); + + auto &bindingDescription = setLayout.bindings[binding]; + + VkWriteDescriptorSet write{}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.descriptorType = bindingDescription.descriptorType; + write.dstBinding = binding; + write.dstArrayElement = 0; + write.pImageInfo = imageInfos->data(); + write.descriptorCount = imageInfos->size(); + + writes.push_back(write); + return *this; +} + bool DescriptorWriter::build(VkDescriptorSet &set) { bool success = pool.allocateDescriptor(setLayout.getDescriptorSetLayout(), set); if (!success) { diff --git a/engine/xe_descriptors.hpp b/engine/xe_descriptors.hpp index ea635c5..7f5c159 100644 --- a/engine/xe_descriptors.hpp +++ b/engine/xe_descriptors.hpp @@ -19,7 +19,8 @@ class DescriptorSetLayout { uint32_t binding, VkDescriptorType descriptorType, VkShaderStageFlags stageFlags, - VkSampler *sampler); + VkSampler *sampler, + uint32_t count); std::unique_ptr build() const; private: @@ -90,6 +91,7 @@ class DescriptorWriter { DescriptorWriter &writeBuffer(uint32_t binding, VkDescriptorBufferInfo *bufferInfo); DescriptorWriter &writeImage(uint32_t binding, VkDescriptorImageInfo *imageInfo); + DescriptorWriter &writeImageArray(uint32_t binding, std::vector *imageInfos); bool build(VkDescriptorSet &set); void overwrite(VkDescriptorSet &set); diff --git a/engine/xe_render_system.cpp b/engine/xe_render_system.cpp index cdfe3cb..f2f0e43 100644 --- a/engine/xe_render_system.cpp +++ b/engine/xe_render_system.cpp @@ -8,6 +8,7 @@ RenderSystem::RenderSystem( std::string frag, std::map uniformBindings, std::map imageBindings, + std::map> imageArrayBindings, uint32_t pushCunstantDataSize, bool cullingEnabled, std::vector attributeDescptions, @@ -17,7 +18,8 @@ RenderSystem::RenderSystem( xeDescriptorPool{xeEngine.xeDescriptorPool}, pushCunstantDataSize{pushCunstantDataSize}, uniformBindings{uniformBindings}, - imageBindings{imageBindings} { + imageBindings{imageBindings}, + imageArrayBindings{imageArrayBindings} { createDescriptorSetLayout(); createUniformBuffers(); createDescriptorSets(); @@ -33,11 +35,15 @@ void RenderSystem::createDescriptorSetLayout() { DescriptorSetLayout::Builder builder{xeDevice}; for ( const auto &[binding, size]: uniformBindings) { - builder.addBinding(binding, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, nullptr); + builder.addBinding(binding, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, nullptr, 1); } for ( const auto &[binding, image]: imageBindings) { - builder.addBinding(binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &(image->textureSampler)); + builder.addBinding(binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &(image->textureSampler), 1); + } + + for ( const auto &[binding, images]: imageArrayBindings) { + builder.addBinding(binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0, images.size()); } xeDescriptorSetLayout = builder.build(); @@ -88,6 +94,18 @@ void RenderSystem::updateDescriptorSet(int frameIndex, bool allocate) { writer.writeImage(binding, &imageInfo); } + std::vector imageInfos{}; + for ( const auto &[binding, images]: imageArrayBindings) { + for( const auto &image: images) { + VkDescriptorImageInfo imageInfo{}; + imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageInfo.imageView = image->textureImageView; + imageInfo.sampler = image->textureSampler; + imageInfos.push_back(imageInfo); + } + writer.writeImageArray(binding, &imageInfos); + } + if (allocate) { writer.build(descriptorSets[frameIndex]); } else { @@ -183,6 +201,11 @@ void RenderSystem::loadTexture(uint32_t binding, Image *image) { updateDescriptorSet(xeRenderer.getFrameIndex(), false); } +void RenderSystem::loadTextureArray(uint32_t binding, std::vector& images) { + imageArrayBindings[binding] = images; + updateDescriptorSet(xeRenderer.getFrameIndex(), false); +} + void RenderSystem::render(GameObject &gameObject) { gameObject.model->bind(xeRenderer.getCurrentCommandBuffer()); diff --git a/engine/xe_render_system.hpp b/engine/xe_render_system.hpp index 045f6db..b82d6e7 100644 --- a/engine/xe_render_system.hpp +++ b/engine/xe_render_system.hpp @@ -54,19 +54,25 @@ class RenderSystem { return *this; } + Builder& addTextureArrayBinding(uint32_t binding, std::vector& image) { + imageArrayBindings[binding] = image; + return *this; + } + Builder& setCulling(bool enabled) { cullingEnabled = enabled; return *this; } std::unique_ptr build() { - return std::make_unique(xeEngine, std::move(vert), std::move(frag), std::move(uniformBindings), std::move(imageBindings), std::move(pushCunstantDataSize), std::move(cullingEnabled), std::move(attributeDescptions), std::move(vertexSize)); + return std::make_unique(xeEngine, std::move(vert), std::move(frag), std::move(uniformBindings), std::move(imageBindings), std::move(imageArrayBindings), std::move(pushCunstantDataSize), std::move(cullingEnabled), std::move(attributeDescptions), std::move(vertexSize)); } private: std::map uniformBindings{}; std::map imageBindings{}; + std::map> imageArrayBindings{}; uint32_t pushCunstantDataSize{0}; std::vector attributeDescptions{}; @@ -86,6 +92,7 @@ class RenderSystem { std::string frag, std::map uniformBindings, std::map imageBindings, + std::map> imageArrayBindings, uint32_t pushCunstantDataSize, bool cullingEnabled, std::vector attributeDescptions, @@ -101,6 +108,7 @@ class RenderSystem { void loadPushConstant(void *pushConstantData); void loadUniformObject(uint32_t binding, void *uniformBufferData); void loadTexture(uint32_t binding, Image *image); + void loadTextureArray(uint32_t binding, std::vector &images); void render(GameObject &gameObject); void stop(); @@ -123,6 +131,7 @@ class RenderSystem { std::map>> uboBuffers{}; std::map uniformBindings; std::map imageBindings; + std::map> imageArrayBindings{}; std::vector descriptorSets; uint32_t pushCunstantDataSize; diff --git a/res/image/blocks.png b/res/image/blocks.png deleted file mode 100644 index 24f734a..0000000 Binary files a/res/image/blocks.png and /dev/null differ diff --git a/res/image/grass.png b/res/image/grass.png new file mode 100644 index 0000000..48823f2 Binary files /dev/null and b/res/image/grass.png differ diff --git a/res/image/scaly.png b/res/image/scaly.png deleted file mode 100644 index cefdd5f..0000000 Binary files a/res/image/scaly.png and /dev/null differ diff --git a/res/image/texture.png b/res/image/texture.png deleted file mode 100644 index e1db6c1..0000000 Binary files a/res/image/texture.png and /dev/null differ diff --git a/res/shaders/simple_shader.frag b/res/shaders/simple_shader.frag index f3ae526..102ac22 100755 --- a/res/shaders/simple_shader.frag +++ b/res/shaders/simple_shader.frag @@ -2,6 +2,7 @@ layout (location = 0) in vec3 fragColor; layout (location = 1) in vec2 fragUv; +layout (location = 2) in float fragTex; layout (location = 0) out vec4 outColor; @@ -10,12 +11,7 @@ layout (binding = 0) uniform GlobalUbo { vec3 directionToLight; } ubo; -layout (binding = 2) uniform Deez { - mat4 projectionViewMatrix; - vec3 directionToLight; -} deez; - -layout (binding = 1) uniform sampler2D texSampler; +layout (binding = 1) uniform sampler2D texSampler[2]; layout(push_constant) uniform Push { mat4 transform; @@ -23,5 +19,5 @@ layout(push_constant) uniform Push { } push; void main() { - outColor = mix(texture(texSampler, fragUv), vec4(fragColor, 1.0), .1); + outColor = mix(texture(texSampler[int(fragTex)], fragUv), vec4(fragColor, 1.0), .1); } \ No newline at end of file diff --git a/res/shaders/simple_shader.vert b/res/shaders/simple_shader.vert index 30e7a79..8a28a59 100755 --- a/res/shaders/simple_shader.vert +++ b/res/shaders/simple_shader.vert @@ -3,20 +3,17 @@ layout (location = 0) in vec3 position; layout (location = 1) in vec3 normal; layout (location = 2) in vec2 uv; +layout (location = 3) in float tex; layout (location = 0) out vec3 fragColor; layout (location = 1) out vec2 fragUv; +layout (location = 2) out float fragTex; layout (binding = 0) uniform GlobalUbo { mat4 projectionViewMatrix; vec3 directionToLight; } ubo; -layout (binding = 2) uniform Deez { - mat4 projectionViewMatrix; - vec3 directionToLight; -} deez; - layout (push_constant) uniform Push { mat4 modelMatrix; mat4 normalMatrix; @@ -33,4 +30,5 @@ void main() { fragColor = lightIntensity * vec3(1); fragUv = uv; + fragTex = tex; } \ No newline at end of file diff --git a/src/chunk.cpp b/src/chunk.cpp index aa9ff3b..a674527 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -75,7 +75,7 @@ std::shared_ptr Chunk::getMesh() { delete chunkMesh.get(); xe::Model::Builder builder{}; builder.vertexData = vertexData; - builder.vertexSize = 32; + builder.vertexSize = 36; chunkMesh = std::make_shared(xe::Engine::getInstance()->getDevice(), builder); } return chunkMesh; @@ -129,6 +129,7 @@ void Chunk::addVerticies(uint8_t side, int32_t x, int32_t y, int32_t z) { vertexData.push_back(nm[side][2]); vertexData.push_back(uv[i][0]); vertexData.push_back(uv[i][1]); + vertexData.push_back(0.f); } } diff --git a/src/first_app.cpp b/src/first_app.cpp index 561b693..04272ba 100755 --- a/src/first_app.cpp +++ b/src/first_app.cpp @@ -11,9 +11,12 @@ FirstApp::~FirstApp() {} void FirstApp::run() { - std::shared_ptr image = xeEngine.loadImageFromFile("res/image/dirt.jpg"); + std::shared_ptr dirt = xeEngine.loadImageFromFile("res/image/dirt.jpg"); + std::shared_ptr grass = xeEngine.loadImageFromFile("res/image/grass.png"); - SimpleRenderer renderer{xeEngine, image.get()}; + std::vector images = {dirt.get(), grass.get()}; + + SimpleRenderer renderer{xeEngine, images}; xe::Sound sound{"res/sound/when_the_world_ends.wav"}; sound.setLooping(true); @@ -32,7 +35,7 @@ void FirstApp::run() { xeEngine.getCamera().setViewYXZ(viewerObject.transform.translation, viewerObject.transform.rotation); if(xeEngine.beginFrame()) { - renderer.render(gameObjects, xeEngine.getCamera(), image.get()); + renderer.render(gameObjects, xeEngine.getCamera()); xeEngine.endFrame(); } diff --git a/src/simple_renderer.cpp b/src/simple_renderer.cpp index 3efa9b8..c68f2ab 100644 --- a/src/simple_renderer.cpp +++ b/src/simple_renderer.cpp @@ -2,22 +2,23 @@ namespace app { -SimpleRenderer::SimpleRenderer(xe::Engine &xeEngine, xe::Image *xeImage) { +SimpleRenderer::SimpleRenderer(xe::Engine &xeEngine, std::vector &images) { xeRenderSystem = xe::RenderSystem::Builder(xeEngine, "res/shaders/simple_shader.vert.spv", "res/shaders/simple_shader.frag.spv") .addVertexBinding(0, 3, 0) // position .addVertexBinding(1, 3, 12) // normal .addVertexBinding(2, 2, 24) // uvs - .setVertexSize(32) + .addVertexBinding(3, 1, 32) // texture + .setVertexSize(36) .addPushConstant(sizeof(PushConstant)) .addUniformBinding(0, sizeof(UniformBuffer)) - .addTextureBinding(1, xeImage) + .addTextureArrayBinding(1, images) .setCulling(true) .build(); } -void SimpleRenderer::render(std::vector &gameObjects, xe::Camera &xeCamera, xe::Image *xeImage) { +void SimpleRenderer::render(std::vector &gameObjects, xe::Camera &xeCamera) { - xeRenderSystem->loadTexture(1, xeImage); + // xeRenderSystem->loadTexture(1, xeImage); xeRenderSystem->start(); diff --git a/src/simple_renderer.hpp b/src/simple_renderer.hpp index 7c08001..4db1446 100644 --- a/src/simple_renderer.hpp +++ b/src/simple_renderer.hpp @@ -20,14 +20,14 @@ class SimpleRenderer { public: - SimpleRenderer(xe::Engine &xeEngine, xe::Image *xeImage); + SimpleRenderer(xe::Engine &xeEngine, std::vector &images); ~SimpleRenderer() {}; SimpleRenderer(const SimpleRenderer&) = delete; SimpleRenderer operator=(const SimpleRenderer&) = delete; - void render(std::vector &gameObjects, xe::Camera &xeCamera, xe::Image *xeImage); + void render(std::vector &gameObjects, xe::Camera &xeCamera); private: std::unique_ptr xeRenderSystem;