vertex buffer is not a byte vector, multi texture loading

This commit is contained in:
tylermurphy534 2022-09-26 20:57:53 -04:00
parent 873ca38c0d
commit 5a08c9c8e2
19 changed files with 140 additions and 249944 deletions

View file

@ -36,9 +36,9 @@ std::shared_ptr<Model> Engine::loadModelFromFile(const std::string &filename) {
return Model::createModelFromFile(xeDevice, filename); return Model::createModelFromFile(xeDevice, filename);
} }
std::shared_ptr<Model> Engine::loadModelFromData(std::vector<float> vertexData, uint32_t vertexSize, std::vector<uint32_t> indices) { std::shared_ptr<Model> Engine::loadModelFromData(std::vector<unsigned char> vertexData, uint32_t vertexSize, std::vector<uint32_t> indices) {
Model::Builder builder{}; Model::Builder builder{};
builder.vertexData = vertexData; builder.vertexData.data = vertexData;
builder.vertexSize = vertexSize; builder.vertexSize = vertexSize;
if(indices.size() > 0) { if(indices.size() > 0) {
builder.indices = indices; builder.indices = indices;
@ -46,8 +46,8 @@ std::shared_ptr<Model> Engine::loadModelFromData(std::vector<float> vertexData,
return std::make_shared<Model>(xeDevice, builder); return std::make_shared<Model>(xeDevice, builder);
} }
std::shared_ptr<Image> Engine::loadImageFromFile(const std::string &filename) { Image* Engine::loadImageFromFile(const std::string &filename) {
return std::make_shared<Image>(xeDevice, filename); return new Image(xeDevice, filename);
} }
bool Engine::poll() { bool Engine::poll() {

View file

@ -32,8 +32,8 @@ class Engine {
Device& getDevice() {return xeDevice;} Device& getDevice() {return xeDevice;}
std::shared_ptr<Model> loadModelFromFile(const std::string &filename); std::shared_ptr<Model> loadModelFromFile(const std::string &filename);
std::shared_ptr<Model> loadModelFromData(std::vector<float> vertexData, uint32_t vertexSize, std::vector<uint32_t> indices); std::shared_ptr<Model> loadModelFromData(std::vector<unsigned char> vertexData, uint32_t vertexSize, std::vector<uint32_t> indices);
std::shared_ptr<Image> loadImageFromFile(const std::string &filename); Image* loadImageFromFile(const std::string &filename);
bool beginFrame() { return xeRenderer.beginFrame(); } bool beginFrame() { return xeRenderer.beginFrame(); }
void endFrame() { xeRenderer.endFrame(); } void endFrame() { xeRenderer.endFrame(); }

View file

@ -221,8 +221,8 @@ void Image::createTextureSampler() {
VkSamplerCreateInfo samplerInfo{}; VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_LINEAR; samplerInfo.magFilter = VK_FILTER_NEAREST;
samplerInfo.minFilter = VK_FILTER_LINEAR; samplerInfo.minFilter = VK_FILTER_NEAREST;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;

View file

@ -14,7 +14,7 @@
namespace xe { namespace xe {
Model::Model(Device &device, const Model::Builder &builder) : xeDevice{device} { Model::Model(Device &device, const Model::Builder &builder) : xeDevice{device} {
createVertexBuffers(builder.vertexData, builder.vertexSize); createVertexBuffers(builder.vertexData.data, builder.vertexSize);
createIndexBuffers(builder.indices); createIndexBuffers(builder.indices);
} }
@ -26,10 +26,10 @@ std::unique_ptr<Model> Model::createModelFromFile(Device &device, const std::str
return std::make_unique<Model>(device, builder); return std::make_unique<Model>(device, builder);
} }
void Model::createVertexBuffers(const std::vector<float> &vertexData, uint32_t vertexSize) { void Model::createVertexBuffers(const std::vector<unsigned char> &vertexData, uint32_t vertexSize) {
vertexCount = static_cast<uint32_t>(vertexData.size()) / (vertexSize / 4); vertexCount = static_cast<uint32_t>(vertexData.size()) / vertexSize;
assert(vertexCount >= 3 && "Vertex count must be atleast 3"); assert(vertexCount >= 3 && "Vertex count must be atleast 3");
VkDeviceSize bufferSize = vertexData.size() * 4; VkDeviceSize bufferSize = vertexData.size();
Buffer stagingBuffer { Buffer stagingBuffer {
xeDevice, xeDevice,
@ -113,7 +113,7 @@ void Model::Builder::loadModel(const std::string &filepath) {
throw std::runtime_error(warn + err); throw std::runtime_error(warn + err);
} }
vertexData.clear(); vertexData.data.clear();
indices.clear(); indices.clear();
vertexSize = 0; vertexSize = 0;
@ -123,22 +123,22 @@ void Model::Builder::loadModel(const std::string &filepath) {
for (const auto &index : shape.mesh.indices) { for (const auto &index : shape.mesh.indices) {
if(index.vertex_index >= 0) { if(index.vertex_index >= 0) {
vertexData.push_back(attrib.vertices[3 * index.vertex_index + 0]); vertexData.write<float>(attrib.vertices[3 * index.vertex_index + 0]);
vertexData.push_back(attrib.vertices[3 * index.vertex_index + 1]); vertexData.write<float>(attrib.vertices[3 * index.vertex_index + 1]);
vertexData.push_back(attrib.vertices[3 * index.vertex_index + 2]); vertexData.write<float>(attrib.vertices[3 * index.vertex_index + 2]);
vertex = true; vertex = true;
} }
if(index.normal_index >= 0) { if(index.normal_index >= 0) {
vertexData.push_back(attrib.normals[3 * index.normal_index + 0]); vertexData.write<float>(attrib.normals[3 * index.normal_index + 0]);
vertexData.push_back(attrib.normals[3 * index.normal_index + 1]); vertexData.write<float>(attrib.normals[3 * index.normal_index + 1]);
vertexData.push_back(attrib.normals[3 * index.normal_index + 2]); vertexData.write<float>(attrib.normals[3 * index.normal_index + 2]);
normal = true; normal = true;
} }
if(index.texcoord_index >= 0) { if(index.texcoord_index >= 0) {
vertexData.push_back(attrib.texcoords[2 * index.texcoord_index + 0]); vertexData.write<float>(attrib.texcoords[2 * index.texcoord_index + 0]);
vertexData.push_back(attrib.texcoords[2 * index.texcoord_index + 1]); vertexData.write<float>(attrib.texcoords[2 * index.texcoord_index + 1]);
uvs = true; uvs = true;
} }

View file

@ -14,8 +14,19 @@ namespace xe {
class Model { class Model {
public: public:
struct Data {
std::vector<unsigned char> data{};
template <typename T>
void write(T d) {
unsigned char const * p = reinterpret_cast<unsigned char const *>(&d);
for(std::size_t i = 0; i < sizeof(T); i++){
data.push_back(p[i]);
}
}
};
struct Builder { struct Builder {
std::vector<float> vertexData{}; Model::Data vertexData{};
uint32_t vertexSize; uint32_t vertexSize;
std::vector<uint32_t> indices{}; std::vector<uint32_t> indices{};
@ -35,7 +46,7 @@ class Model {
void draw(VkCommandBuffer commandBuffer); void draw(VkCommandBuffer commandBuffer);
private: private:
void createVertexBuffers(const std::vector<float> &vertexData, uint32_t vertexSize); void createVertexBuffers(const std::vector<unsigned char> &vertexData, uint32_t vertexSize);
void createIndexBuffers(const std::vector<uint32_t> &indexData); void createIndexBuffers(const std::vector<uint32_t> &indexData);
Device &xeDevice; Device &xeDevice;

View file

@ -24,7 +24,7 @@ class RenderSystem {
public: public:
Builder(Engine &xeEngine, std::string vert, std::string frag) : xeEngine{xeEngine}, vert{vert}, frag{frag} {} Builder(Engine &xeEngine, std::string vert, std::string frag) : xeEngine{xeEngine}, vert{vert}, frag{frag} {}
Builder& addVertexBinding(uint32_t binding, uint32_t dimension, uint32_t offset){ Builder& addVertexBindingf(uint32_t binding, uint32_t dimension, uint32_t offset){
if(dimension == 1) if(dimension == 1)
attributeDescptions.push_back({binding, 0, VK_FORMAT_R32_SFLOAT, offset}); attributeDescptions.push_back({binding, 0, VK_FORMAT_R32_SFLOAT, offset});
if(dimension == 2) if(dimension == 2)
@ -34,6 +34,16 @@ class RenderSystem {
return *this; return *this;
} }
Builder& addVertexBindingi(uint32_t binding, uint32_t dimension, uint32_t offset){
if(dimension == 1)
attributeDescptions.push_back({binding, 0, VK_FORMAT_R32_SINT, offset});
if(dimension == 2)
attributeDescptions.push_back({binding, 0, VK_FORMAT_R32G32_SINT, offset});
if(dimension == 3)
attributeDescptions.push_back({binding, 0, VK_FORMAT_R32G32B32_SINT, offset});
return *this;
}
Builder& setVertexSize(uint32_t size) { Builder& setVertexSize(uint32_t size) {
vertexSize = size; vertexSize = size;
return *this; return *this;

View file

View file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

BIN
res/image/dirt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 916 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6 KiB

After

Width:  |  Height:  |  Size: 1,003 B

BIN
res/image/grass_top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because it is too large Load diff

View file

@ -2,7 +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 = 2) in flat int fragTex;
layout (location = 0) out vec4 outColor; layout (location = 0) out vec4 outColor;
@ -11,7 +11,7 @@ layout (binding = 0) uniform GlobalUbo {
vec3 directionToLight; vec3 directionToLight;
} ubo; } ubo;
layout (binding = 1) uniform sampler2D texSampler[2]; layout (binding = 1) uniform sampler2D texSampler[3];
layout(push_constant) uniform Push { layout(push_constant) uniform Push {
mat4 transform; mat4 transform;
@ -19,5 +19,5 @@ layout(push_constant) uniform Push {
} push; } push;
void main() { void main() {
outColor = mix(texture(texSampler[int(fragTex)], fragUv), vec4(fragColor, 1.0), .1); outColor = mix(texture(texSampler[fragTex], fragUv), vec4(fragColor, 1.0), .1);
} }

View file

@ -3,11 +3,11 @@
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 = 3) in int 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 (location = 2) out int fragTex;
layout (binding = 0) uniform GlobalUbo { layout (binding = 0) uniform GlobalUbo {
mat4 projectionViewMatrix; mat4 projectionViewMatrix;

View file

@ -1,6 +1,4 @@
#include "chunk.hpp" #include "chunk.hpp"
#include "xe_engine.hpp"
namespace app { namespace app {
static std::map<std::pair<int32_t, int32_t>, Chunk*> chunks{}; static std::map<std::pair<int32_t, int32_t>, Chunk*> chunks{};
@ -46,28 +44,58 @@ uint8_t Chunk::getBlock(int32_t x, int32_t y, int32_t z) {
z = (z+16)%16; z = (z+16)%16;
if(chunkX == gridX && chunkZ == gridZ) { if(chunkX == gridX && chunkZ == gridZ) {
int index = x + (z * 16) + (y * 256); int index = x + (z * 16) + (y * 256);
return blocks[index]; return cubes[index];
} else { } else {
Chunk* chunk = getChunk(chunkX, chunkZ); Chunk* chunk = getChunk(chunkX, chunkZ);
if(chunk == NULL) { if(chunk == NULL) {
return INVALID; return INVALID;
} else { } else {
int index = x + (z * 16) + (y * 256); int index = x + (z * 16) + (y * 256);
return chunk->blocks[index]; return chunk->cubes[index];
} }
} }
} }
void Chunk::setBlock(int32_t x, int32_t y, int32_t z, uint8_t block) { static std::map<uint8_t, Block> blocks{};
int index = x + (z * 16) + (y * 256); static std::map<std::string, uint32_t> texturesIds{};
blocks[index] = block; static std::vector<xe::Image*> textures{};
void loadTexture(const std::string& filePath) {
xe::Image* image = xe::Engine::getInstance()->loadImageFromFile(filePath);
texturesIds[filePath] = static_cast<uint32_t>(textures.size());
textures.push_back(image);
} }
void Chunk::reset() { uint32_t getTexture(const std::string& filePath) {
return texturesIds[filePath];
}
std::vector<xe::Image*>& Chunk::getTextures() {
return textures;
}
void Chunk::load() {
loadTexture(DIRT_TEXTURE);
loadTexture(GRASS_TEXTURE);
loadTexture(GRASS_TOP_TEXTURE);
blocks[DIRT] = {{getTexture(DIRT_TEXTURE), getTexture(DIRT_TEXTURE), getTexture(DIRT_TEXTURE), getTexture(DIRT_TEXTURE), getTexture(DIRT_TEXTURE), getTexture(DIRT_TEXTURE)}};
blocks[GRASS] = {{getTexture(GRASS_TEXTURE), getTexture(GRASS_TEXTURE), getTexture(GRASS_TOP_TEXTURE), getTexture(DIRT_TEXTURE), getTexture(GRASS_TEXTURE), getTexture(GRASS_TEXTURE)}};
}
void Chunk::unload() {
for(const auto &image: textures) {
delete image;
}
for(const auto &[key, chunk]: chunks) { for(const auto &[key, chunk]: chunks) {
delete chunk; delete chunk;
} }
chunks.clear(); chunks.clear();
textures.clear();
}
void Chunk::setBlock(int32_t x, int32_t y, int32_t z, uint8_t block) {
int index = x + (z * 16) + (y * 256);
cubes[index] = block;
} }
std::shared_ptr<xe::Model> Chunk::getMesh() { std::shared_ptr<xe::Model> Chunk::getMesh() {
@ -88,29 +116,29 @@ void Chunk::createMeshAsync() {
void Chunk::createMesh() { void Chunk::createMesh() {
working = true; working = true;
vertexData.clear(); vertexData.data.clear();
for(int32_t x=0;x<16;x++) { for(int32_t x=0;x<16;x++) {
for(int32_t y=0; y<256; y++) { for(int32_t y=0; y<256; y++) {
for(int32_t z=0; z<16; z++) { for(int32_t z=0; z<16; z++) {
uint8_t block = getBlock(x,y,z); uint8_t block = getBlock(x,y,z);
if(block == AIR) continue; if(block == AIR) continue;
if(getBlock(x+1,y,z) == AIR) { if(getBlock(x+1,y,z) == AIR) {
addVerticies(0, x, y, z); addVerticies(0, x, y, z, block);
} }
if(getBlock(x-1,y,z) == AIR) { if(getBlock(x-1,y,z) == AIR) {
addVerticies(1, x, y, z); addVerticies(1, x, y, z, block);
} }
if(getBlock(x,y+1,z) == AIR) { if(getBlock(x,y+1,z) == AIR) {
addVerticies(2, x, y, z); addVerticies(2, x, y, z, block);
} }
if(getBlock(x,y-1,z) == AIR) { if(getBlock(x,y-1,z) == AIR) {
addVerticies(3, x, y, z); addVerticies(3, x, y, z, block);
} }
if(getBlock(x,y,z+1) == AIR) { if(getBlock(x,y,z+1) == AIR) {
addVerticies(4, x, y, z); addVerticies(4, x, y, z, block);
} }
if(getBlock(x,y,z-1) == AIR) { if(getBlock(x,y,z-1) == AIR) {
addVerticies(5, x, y, z); addVerticies(5, x, y, z, block);
} }
} }
} }
@ -119,22 +147,22 @@ void Chunk::createMesh() {
reloadRequired = true; reloadRequired = true;
} }
void Chunk::addVerticies(uint8_t side, int32_t x, int32_t y, int32_t z) { void Chunk::addVerticies(uint8_t side, int32_t x, int32_t y, int32_t z, uint8_t block) {
for(int i = 0; i < 6; i ++) { for(int i = 0; i < 6; i ++) {
vertexData.push_back(px[side * 6 + i][0] + x); vertexData.write<float>(px[side * 6 + i][0] + x);
vertexData.push_back(px[side * 6 + i][1] + y); vertexData.write<float>(px[side * 6 + i][1] + y);
vertexData.push_back(px[side * 6 + i][2] + z); vertexData.write<float>(px[side * 6 + i][2] + z);
vertexData.push_back(nm[side][0]); vertexData.write<float>(nm[side][0]);
vertexData.push_back(nm[side][1]); vertexData.write<float>(nm[side][1]);
vertexData.push_back(nm[side][2]); vertexData.write<float>(nm[side][2]);
vertexData.push_back(uv[i][0]); vertexData.write<float>(uv[i][0]);
vertexData.push_back(uv[i][1]); vertexData.write<float>(uv[i][1]);
vertexData.push_back(0.f); vertexData.write<uint32_t>(static_cast<uint32_t>(blocks[block].textures[side]));
} }
} }
void Chunk::generate() { void Chunk::generate() {
blocks.resize(16*16*256); cubes.resize(16*16*256);
const PerlinNoise perlin{world_seed}; const PerlinNoise perlin{world_seed};
@ -142,7 +170,9 @@ void Chunk::generate() {
for(int z = 0; z < 16; z++) { for(int z = 0; z < 16; z++) {
int height = perlin.octave2D_01((( x + gridX * 16) * 0.01), ((z + gridZ * 16) * 0.01), 4) * 10; int height = perlin.octave2D_01((( x + gridX * 16) * 0.01), ((z + gridZ * 16) * 0.01), 4) * 10;
for(int y = 0; y < 256; y++) { for(int y = 0; y < 256; y++) {
if(y <= height) if(y == height){
setBlock(x, y, z, GRASS);
} else if(y < height)
setBlock(x, y, z, DIRT); setBlock(x, y, z, DIRT);
else else
setBlock(x, y, z, AIR); setBlock(x, y, z, AIR);

View file

@ -1,6 +1,9 @@
#pragma once #pragma once
#include "xe_model.hpp" #include "xe_model.hpp"
#include "xe_engine.hpp"
#include "xe_image.hpp"
#include "PerlinNoise.hpp" #include "PerlinNoise.hpp"
#include <glm/common.hpp> #include <glm/common.hpp>
@ -11,19 +14,30 @@
#include <string> #include <string>
#include <map> #include <map>
#define INVALID 0 #define INVALID -1
#define AIR 1 #define AIR 0
#define DIRT 2 #define DIRT 1
#define GRASS 3 #define GRASS 2
#define DIRT_TEXTURE "res/image/dirt.png"
#define GRASS_TEXTURE "res/image/grass.png"
#define GRASS_TOP_TEXTURE "res/image/grass_top.png"
namespace app { namespace app {
struct Block {
uint32_t textures[6];
};
class Chunk { class Chunk {
public: public:
static void load();
static void unload();
static std::vector<xe::Image*>& getTextures();
static Chunk* newChunk(int32_t gridX, int32_t gridZ, uint32_t world_seed); static Chunk* newChunk(int32_t gridX, int32_t gridZ, uint32_t world_seed);
static void reset();
Chunk(int32_t gridX, int32_t gridZ, uint32_t world_seed); Chunk(int32_t gridX, int32_t gridZ, uint32_t world_seed);
~Chunk() {}; ~Chunk() {};
@ -43,14 +57,14 @@ class Chunk {
private: private:
void generate(); void generate();
void addVerticies(uint8_t side, int32_t x, int32_t y, int32_t z); void addVerticies(uint8_t side, int32_t x, int32_t y, int32_t z, uint8_t block);
bool reloadRequired{false}; bool reloadRequired{false};
bool working{false}; bool working{false};
std::shared_ptr<xe::Model> chunkMesh; std::shared_ptr<xe::Model> chunkMesh;
std::vector<float> vertexData; xe::Model::Data vertexData;
std::vector<uint8_t> blocks; std::vector<uint8_t> cubes;
std::thread worker; std::thread worker;
}; };

View file

@ -3,20 +3,17 @@
namespace app { namespace app {
FirstApp::FirstApp() : xeEngine{WIDTH, HEIGHT, "Xenon Vulkan Engine"} { FirstApp::FirstApp() : xeEngine{WIDTH, HEIGHT, "Xenon Vulkan Engine"} {};
loadGameObjects();
}
FirstApp::~FirstApp() {} FirstApp::~FirstApp() {}
void FirstApp::run() { void FirstApp::run() {
std::shared_ptr<xe::Image> dirt = xeEngine.loadImageFromFile("res/image/dirt.jpg"); Chunk::load();
std::shared_ptr<xe::Image> grass = xeEngine.loadImageFromFile("res/image/grass.png");
std::vector<xe::Image*> images = {dirt.get(), grass.get()}; loadGameObjects();
SimpleRenderer renderer{xeEngine, images}; SimpleRenderer renderer{xeEngine, Chunk::getTextures()};
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);
@ -41,10 +38,10 @@ void FirstApp::run() {
} }
Chunk::reset();
xeEngine.close(); xeEngine.close();
Chunk::unload();
} }
void FirstApp::loadGameObjects() { void FirstApp::loadGameObjects() {

View file

@ -4,10 +4,10 @@ namespace app {
SimpleRenderer::SimpleRenderer(xe::Engine &xeEngine, std::vector<xe::Image*> &images) { 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 .addVertexBindingf(0, 3, 0) // position
.addVertexBinding(1, 3, 12) // normal .addVertexBindingf(1, 3, 12) // normal
.addVertexBinding(2, 2, 24) // uvs .addVertexBindingf(2, 2, 24) // uvs
.addVertexBinding(3, 1, 32) // texture .addVertexBindingi(3, 1, 32) // texture
.setVertexSize(36) .setVertexSize(36)
.addPushConstant(sizeof(PushConstant)) .addPushConstant(sizeof(PushConstant))
.addUniformBinding(0, sizeof(UniformBuffer)) .addUniformBinding(0, sizeof(UniformBuffer))