texture arrays

This commit is contained in:
Tyler Murphy 2022-09-26 18:03:07 -04:00
parent 7332c3e56a
commit 873ca38c0d
14 changed files with 81 additions and 30 deletions

View file

@ -10,9 +10,9 @@ DescriptorSetLayout::Builder &DescriptorSetLayout::Builder::addBinding(
uint32_t binding, uint32_t binding,
VkDescriptorType descriptorType, VkDescriptorType descriptorType,
VkShaderStageFlags stageFlags, VkShaderStageFlags stageFlags,
VkSampler *sampler) { VkSampler *sampler,
uint32_t count) {
assert(bindings.count(binding) == 0 && "Binding already in use"); assert(bindings.count(binding) == 0 && "Binding already in use");
uint32_t count = 1;
VkDescriptorSetLayoutBinding layoutBinding{}; VkDescriptorSetLayoutBinding layoutBinding{};
layoutBinding.binding = binding; layoutBinding.binding = binding;
layoutBinding.descriptorType = descriptorType; layoutBinding.descriptorType = descriptorType;
@ -167,6 +167,24 @@ DescriptorWriter &DescriptorWriter::writeImage(
return *this; return *this;
} }
DescriptorWriter &DescriptorWriter::writeImageArray(
uint32_t binding, std::vector<VkDescriptorImageInfo> *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 DescriptorWriter::build(VkDescriptorSet &set) {
bool success = pool.allocateDescriptor(setLayout.getDescriptorSetLayout(), set); bool success = pool.allocateDescriptor(setLayout.getDescriptorSetLayout(), set);
if (!success) { if (!success) {

View file

@ -19,7 +19,8 @@ class DescriptorSetLayout {
uint32_t binding, uint32_t binding,
VkDescriptorType descriptorType, VkDescriptorType descriptorType,
VkShaderStageFlags stageFlags, VkShaderStageFlags stageFlags,
VkSampler *sampler); VkSampler *sampler,
uint32_t count);
std::unique_ptr<DescriptorSetLayout> build() const; std::unique_ptr<DescriptorSetLayout> build() const;
private: private:
@ -90,6 +91,7 @@ class DescriptorWriter {
DescriptorWriter &writeBuffer(uint32_t binding, VkDescriptorBufferInfo *bufferInfo); DescriptorWriter &writeBuffer(uint32_t binding, VkDescriptorBufferInfo *bufferInfo);
DescriptorWriter &writeImage(uint32_t binding, VkDescriptorImageInfo *imageInfo); DescriptorWriter &writeImage(uint32_t binding, VkDescriptorImageInfo *imageInfo);
DescriptorWriter &writeImageArray(uint32_t binding, std::vector<VkDescriptorImageInfo> *imageInfos);
bool build(VkDescriptorSet &set); bool build(VkDescriptorSet &set);
void overwrite(VkDescriptorSet &set); void overwrite(VkDescriptorSet &set);

View file

@ -8,6 +8,7 @@ RenderSystem::RenderSystem(
std::string frag, std::string frag,
std::map<uint32_t, uint32_t> uniformBindings, std::map<uint32_t, uint32_t> uniformBindings,
std::map<uint32_t, Image*> imageBindings, std::map<uint32_t, Image*> imageBindings,
std::map<uint32_t, std::vector<Image*>> imageArrayBindings,
uint32_t pushCunstantDataSize, uint32_t pushCunstantDataSize,
bool cullingEnabled, bool cullingEnabled,
std::vector<VkVertexInputAttributeDescription> attributeDescptions, std::vector<VkVertexInputAttributeDescription> attributeDescptions,
@ -17,7 +18,8 @@ RenderSystem::RenderSystem(
xeDescriptorPool{xeEngine.xeDescriptorPool}, xeDescriptorPool{xeEngine.xeDescriptorPool},
pushCunstantDataSize{pushCunstantDataSize}, pushCunstantDataSize{pushCunstantDataSize},
uniformBindings{uniformBindings}, uniformBindings{uniformBindings},
imageBindings{imageBindings} { imageBindings{imageBindings},
imageArrayBindings{imageArrayBindings} {
createDescriptorSetLayout(); createDescriptorSetLayout();
createUniformBuffers(); createUniformBuffers();
createDescriptorSets(); createDescriptorSets();
@ -33,11 +35,15 @@ void RenderSystem::createDescriptorSetLayout() {
DescriptorSetLayout::Builder builder{xeDevice}; DescriptorSetLayout::Builder builder{xeDevice};
for ( const auto &[binding, size]: uniformBindings) { 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) { 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(); xeDescriptorSetLayout = builder.build();
@ -88,6 +94,18 @@ void RenderSystem::updateDescriptorSet(int frameIndex, bool allocate) {
writer.writeImage(binding, &imageInfo); writer.writeImage(binding, &imageInfo);
} }
std::vector<VkDescriptorImageInfo> 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) { if (allocate) {
writer.build(descriptorSets[frameIndex]); writer.build(descriptorSets[frameIndex]);
} else { } else {
@ -183,6 +201,11 @@ void RenderSystem::loadTexture(uint32_t binding, Image *image) {
updateDescriptorSet(xeRenderer.getFrameIndex(), false); updateDescriptorSet(xeRenderer.getFrameIndex(), false);
} }
void RenderSystem::loadTextureArray(uint32_t binding, std::vector<Image*>& images) {
imageArrayBindings[binding] = images;
updateDescriptorSet(xeRenderer.getFrameIndex(), false);
}
void RenderSystem::render(GameObject &gameObject) { void RenderSystem::render(GameObject &gameObject) {
gameObject.model->bind(xeRenderer.getCurrentCommandBuffer()); gameObject.model->bind(xeRenderer.getCurrentCommandBuffer());

View file

@ -54,19 +54,25 @@ class RenderSystem {
return *this; return *this;
} }
Builder& addTextureArrayBinding(uint32_t binding, std::vector<Image*>& image) {
imageArrayBindings[binding] = image;
return *this;
}
Builder& setCulling(bool enabled) { Builder& setCulling(bool enabled) {
cullingEnabled = enabled; cullingEnabled = enabled;
return *this; return *this;
} }
std::unique_ptr<RenderSystem> build() { std::unique_ptr<RenderSystem> build() {
return std::make_unique<RenderSystem>(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<RenderSystem>(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: private:
std::map<uint32_t, uint32_t> uniformBindings{}; std::map<uint32_t, uint32_t> uniformBindings{};
std::map<uint32_t, Image*> imageBindings{}; std::map<uint32_t, Image*> imageBindings{};
std::map<uint32_t, std::vector<Image*>> imageArrayBindings{};
uint32_t pushCunstantDataSize{0}; uint32_t pushCunstantDataSize{0};
std::vector<VkVertexInputAttributeDescription> attributeDescptions{}; std::vector<VkVertexInputAttributeDescription> attributeDescptions{};
@ -86,6 +92,7 @@ class RenderSystem {
std::string frag, std::string frag,
std::map<uint32_t, uint32_t> uniformBindings, std::map<uint32_t, uint32_t> uniformBindings,
std::map<uint32_t, Image*> imageBindings, std::map<uint32_t, Image*> imageBindings,
std::map<uint32_t, std::vector<Image*>> imageArrayBindings,
uint32_t pushCunstantDataSize, uint32_t pushCunstantDataSize,
bool cullingEnabled, bool cullingEnabled,
std::vector<VkVertexInputAttributeDescription> attributeDescptions, std::vector<VkVertexInputAttributeDescription> attributeDescptions,
@ -101,6 +108,7 @@ class RenderSystem {
void loadPushConstant(void *pushConstantData); void loadPushConstant(void *pushConstantData);
void loadUniformObject(uint32_t binding, void *uniformBufferData); void loadUniformObject(uint32_t binding, void *uniformBufferData);
void loadTexture(uint32_t binding, Image *image); void loadTexture(uint32_t binding, Image *image);
void loadTextureArray(uint32_t binding, std::vector<Image*> &images);
void render(GameObject &gameObject); void render(GameObject &gameObject);
void stop(); void stop();
@ -123,6 +131,7 @@ class RenderSystem {
std::map<uint32_t, std::vector<std::unique_ptr<Buffer>>> uboBuffers{}; std::map<uint32_t, std::vector<std::unique_ptr<Buffer>>> uboBuffers{};
std::map<uint32_t, uint32_t> uniformBindings; std::map<uint32_t, uint32_t> uniformBindings;
std::map<uint32_t, Image*> imageBindings; std::map<uint32_t, Image*> imageBindings;
std::map<uint32_t, std::vector<Image*>> imageArrayBindings{};
std::vector<VkDescriptorSet> descriptorSets; std::vector<VkDescriptorSet> descriptorSets;
uint32_t pushCunstantDataSize; uint32_t pushCunstantDataSize;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

BIN
res/image/grass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

View file

@ -2,6 +2,7 @@
layout (location = 0) in vec3 fragColor; layout (location = 0) in vec3 fragColor;
layout (location = 1) in vec2 fragUv; layout (location = 1) in vec2 fragUv;
layout (location = 2) in float fragTex;
layout (location = 0) out vec4 outColor; layout (location = 0) out vec4 outColor;
@ -10,12 +11,7 @@ layout (binding = 0) uniform GlobalUbo {
vec3 directionToLight; vec3 directionToLight;
} ubo; } ubo;
layout (binding = 2) uniform Deez { layout (binding = 1) uniform sampler2D texSampler[2];
mat4 projectionViewMatrix;
vec3 directionToLight;
} deez;
layout (binding = 1) uniform sampler2D texSampler;
layout(push_constant) uniform Push { layout(push_constant) uniform Push {
mat4 transform; mat4 transform;
@ -23,5 +19,5 @@ layout(push_constant) uniform Push {
} push; } push;
void main() { void main() {
outColor = mix(texture(texSampler, fragUv), vec4(fragColor, 1.0), .1); outColor = mix(texture(texSampler[int(fragTex)], fragUv), vec4(fragColor, 1.0), .1);
} }

View file

@ -3,20 +3,17 @@
layout (location = 0) in vec3 position; layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal; layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 uv; layout (location = 2) in vec2 uv;
layout (location = 3) in float tex;
layout (location = 0) out vec3 fragColor; layout (location = 0) out vec3 fragColor;
layout (location = 1) out vec2 fragUv; layout (location = 1) out vec2 fragUv;
layout (location = 2) out float fragTex;
layout (binding = 0) uniform GlobalUbo { layout (binding = 0) uniform GlobalUbo {
mat4 projectionViewMatrix; mat4 projectionViewMatrix;
vec3 directionToLight; vec3 directionToLight;
} ubo; } ubo;
layout (binding = 2) uniform Deez {
mat4 projectionViewMatrix;
vec3 directionToLight;
} deez;
layout (push_constant) uniform Push { layout (push_constant) uniform Push {
mat4 modelMatrix; mat4 modelMatrix;
mat4 normalMatrix; mat4 normalMatrix;
@ -33,4 +30,5 @@ void main() {
fragColor = lightIntensity * vec3(1); fragColor = lightIntensity * vec3(1);
fragUv = uv; fragUv = uv;
fragTex = tex;
} }

View file

@ -75,7 +75,7 @@ std::shared_ptr<xe::Model> Chunk::getMesh() {
delete chunkMesh.get(); delete chunkMesh.get();
xe::Model::Builder builder{}; xe::Model::Builder builder{};
builder.vertexData = vertexData; builder.vertexData = vertexData;
builder.vertexSize = 32; builder.vertexSize = 36;
chunkMesh = std::make_shared<xe::Model>(xe::Engine::getInstance()->getDevice(), builder); chunkMesh = std::make_shared<xe::Model>(xe::Engine::getInstance()->getDevice(), builder);
} }
return chunkMesh; 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(nm[side][2]);
vertexData.push_back(uv[i][0]); vertexData.push_back(uv[i][0]);
vertexData.push_back(uv[i][1]); vertexData.push_back(uv[i][1]);
vertexData.push_back(0.f);
} }
} }

View file

@ -11,9 +11,12 @@ FirstApp::~FirstApp() {}
void FirstApp::run() { void FirstApp::run() {
std::shared_ptr<xe::Image> image = xeEngine.loadImageFromFile("res/image/dirt.jpg"); std::shared_ptr<xe::Image> dirt = xeEngine.loadImageFromFile("res/image/dirt.jpg");
std::shared_ptr<xe::Image> grass = xeEngine.loadImageFromFile("res/image/grass.png");
SimpleRenderer renderer{xeEngine, image.get()}; std::vector<xe::Image*> images = {dirt.get(), grass.get()};
SimpleRenderer renderer{xeEngine, images};
xe::Sound sound{"res/sound/when_the_world_ends.wav"}; xe::Sound sound{"res/sound/when_the_world_ends.wav"};
sound.setLooping(true); sound.setLooping(true);
@ -32,7 +35,7 @@ void FirstApp::run() {
xeEngine.getCamera().setViewYXZ(viewerObject.transform.translation, viewerObject.transform.rotation); xeEngine.getCamera().setViewYXZ(viewerObject.transform.translation, viewerObject.transform.rotation);
if(xeEngine.beginFrame()) { if(xeEngine.beginFrame()) {
renderer.render(gameObjects, xeEngine.getCamera(), image.get()); renderer.render(gameObjects, xeEngine.getCamera());
xeEngine.endFrame(); xeEngine.endFrame();
} }

View file

@ -2,22 +2,23 @@
namespace app { namespace app {
SimpleRenderer::SimpleRenderer(xe::Engine &xeEngine, xe::Image *xeImage) { SimpleRenderer::SimpleRenderer(xe::Engine &xeEngine, std::vector<xe::Image*> &images) {
xeRenderSystem = xe::RenderSystem::Builder(xeEngine, "res/shaders/simple_shader.vert.spv", "res/shaders/simple_shader.frag.spv") xeRenderSystem = xe::RenderSystem::Builder(xeEngine, "res/shaders/simple_shader.vert.spv", "res/shaders/simple_shader.frag.spv")
.addVertexBinding(0, 3, 0) // position .addVertexBinding(0, 3, 0) // position
.addVertexBinding(1, 3, 12) // normal .addVertexBinding(1, 3, 12) // normal
.addVertexBinding(2, 2, 24) // uvs .addVertexBinding(2, 2, 24) // uvs
.setVertexSize(32) .addVertexBinding(3, 1, 32) // texture
.setVertexSize(36)
.addPushConstant(sizeof(PushConstant)) .addPushConstant(sizeof(PushConstant))
.addUniformBinding(0, sizeof(UniformBuffer)) .addUniformBinding(0, sizeof(UniformBuffer))
.addTextureBinding(1, xeImage) .addTextureArrayBinding(1, images)
.setCulling(true) .setCulling(true)
.build(); .build();
} }
void SimpleRenderer::render(std::vector<xe::GameObject> &gameObjects, xe::Camera &xeCamera, xe::Image *xeImage) { void SimpleRenderer::render(std::vector<xe::GameObject> &gameObjects, xe::Camera &xeCamera) {
xeRenderSystem->loadTexture(1, xeImage); // xeRenderSystem->loadTexture(1, xeImage);
xeRenderSystem->start(); xeRenderSystem->start();

View file

@ -20,14 +20,14 @@ class SimpleRenderer {
public: public:
SimpleRenderer(xe::Engine &xeEngine, xe::Image *xeImage); SimpleRenderer(xe::Engine &xeEngine, std::vector<xe::Image*> &images);
~SimpleRenderer() {}; ~SimpleRenderer() {};
SimpleRenderer(const SimpleRenderer&) = delete; SimpleRenderer(const SimpleRenderer&) = delete;
SimpleRenderer operator=(const SimpleRenderer&) = delete; SimpleRenderer operator=(const SimpleRenderer&) = delete;
void render(std::vector<xe::GameObject> &gameObjects, xe::Camera &xeCamera, xe::Image *xeImage); void render(std::vector<xe::GameObject> &gameObjects, xe::Camera &xeCamera);
private: private:
std::unique_ptr<xe::RenderSystem> xeRenderSystem; std::unique_ptr<xe::RenderSystem> xeRenderSystem;