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);
}
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{};
builder.vertexData = vertexData;
builder.vertexData.data = vertexData;
builder.vertexSize = vertexSize;
if(indices.size() > 0) {
builder.indices = indices;
@ -46,8 +46,8 @@ std::shared_ptr<Model> Engine::loadModelFromData(std::vector<float> vertexData,
return std::make_shared<Model>(xeDevice, builder);
}
std::shared_ptr<Image> Engine::loadImageFromFile(const std::string &filename) {
return std::make_shared<Image>(xeDevice, filename);
Image* Engine::loadImageFromFile(const std::string &filename) {
return new Image(xeDevice, filename);
}
bool Engine::poll() {

View file

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

View file

@ -221,8 +221,8 @@ void Image::createTextureSampler() {
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_LINEAR;
samplerInfo.minFilter = VK_FILTER_LINEAR;
samplerInfo.magFilter = VK_FILTER_NEAREST;
samplerInfo.minFilter = VK_FILTER_NEAREST;
samplerInfo.addressModeU = 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;

View file

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

View file

@ -14,8 +14,19 @@ namespace xe {
class Model {
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 {
std::vector<float> vertexData{};
Model::Data vertexData{};
uint32_t vertexSize;
std::vector<uint32_t> indices{};
@ -35,7 +46,7 @@ class Model {
void draw(VkCommandBuffer commandBuffer);
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);
Device &xeDevice;

View file

@ -24,7 +24,7 @@ class RenderSystem {
public:
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)
attributeDescptions.push_back({binding, 0, VK_FORMAT_R32_SFLOAT, offset});
if(dimension == 2)
@ -34,6 +34,16 @@ class RenderSystem {
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) {
vertexSize = size;
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 = 1) in vec2 fragUv;
layout (location = 2) in float fragTex;
layout (location = 2) in flat int fragTex;
layout (location = 0) out vec4 outColor;
@ -11,7 +11,7 @@ layout (binding = 0) uniform GlobalUbo {
vec3 directionToLight;
} ubo;
layout (binding = 1) uniform sampler2D texSampler[2];
layout (binding = 1) uniform sampler2D texSampler[3];
layout(push_constant) uniform Push {
mat4 transform;
@ -19,5 +19,5 @@ layout(push_constant) uniform Push {
} push;
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 = 1) in vec3 normal;
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 = 1) out vec2 fragUv;
layout (location = 2) out float fragTex;
layout (location = 2) out int fragTex;
layout (binding = 0) uniform GlobalUbo {
mat4 projectionViewMatrix;

View file

@ -1,6 +1,4 @@
#include "chunk.hpp"
#include "xe_engine.hpp"
namespace app {
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;
if(chunkX == gridX && chunkZ == gridZ) {
int index = x + (z * 16) + (y * 256);
return blocks[index];
return cubes[index];
} else {
Chunk* chunk = getChunk(chunkX, chunkZ);
if(chunk == NULL) {
return INVALID;
} else {
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) {
int index = x + (z * 16) + (y * 256);
blocks[index] = block;
static std::map<uint8_t, Block> blocks{};
static std::map<std::string, uint32_t> texturesIds{};
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) {
delete chunk;
}
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() {
@ -88,29 +116,29 @@ void Chunk::createMeshAsync() {
void Chunk::createMesh() {
working = true;
vertexData.clear();
vertexData.data.clear();
for(int32_t x=0;x<16;x++) {
for(int32_t y=0; y<256; y++) {
for(int32_t z=0; z<16; z++) {
uint8_t block = getBlock(x,y,z);
if(block == AIR) continue;
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) {
addVerticies(1, x, y, z);
addVerticies(1, x, y, z, block);
}
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) {
addVerticies(3, x, y, z);
addVerticies(3, x, y, z, block);
}
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) {
addVerticies(5, x, y, z);
addVerticies(5, x, y, z, block);
}
}
}
@ -119,22 +147,22 @@ void Chunk::createMesh() {
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 ++) {
vertexData.push_back(px[side * 6 + i][0] + x);
vertexData.push_back(px[side * 6 + i][1] + y);
vertexData.push_back(px[side * 6 + i][2] + z);
vertexData.push_back(nm[side][0]);
vertexData.push_back(nm[side][1]);
vertexData.push_back(nm[side][2]);
vertexData.push_back(uv[i][0]);
vertexData.push_back(uv[i][1]);
vertexData.push_back(0.f);
vertexData.write<float>(px[side * 6 + i][0] + x);
vertexData.write<float>(px[side * 6 + i][1] + y);
vertexData.write<float>(px[side * 6 + i][2] + z);
vertexData.write<float>(nm[side][0]);
vertexData.write<float>(nm[side][1]);
vertexData.write<float>(nm[side][2]);
vertexData.write<float>(uv[i][0]);
vertexData.write<float>(uv[i][1]);
vertexData.write<uint32_t>(static_cast<uint32_t>(blocks[block].textures[side]));
}
}
void Chunk::generate() {
blocks.resize(16*16*256);
cubes.resize(16*16*256);
const PerlinNoise perlin{world_seed};
@ -142,7 +170,9 @@ void Chunk::generate() {
for(int z = 0; z < 16; z++) {
int height = perlin.octave2D_01((( x + gridX * 16) * 0.01), ((z + gridZ * 16) * 0.01), 4) * 10;
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);
else
setBlock(x, y, z, AIR);

View file

@ -1,6 +1,9 @@
#pragma once
#include "xe_model.hpp"
#include "xe_engine.hpp"
#include "xe_image.hpp"
#include "PerlinNoise.hpp"
#include <glm/common.hpp>
@ -11,19 +14,30 @@
#include <string>
#include <map>
#define INVALID 0
#define AIR 1
#define DIRT 2
#define GRASS 3
#define INVALID -1
#define AIR 0
#define DIRT 1
#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 {
struct Block {
uint32_t textures[6];
};
class Chunk {
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 void reset();
Chunk(int32_t gridX, int32_t gridZ, uint32_t world_seed);
~Chunk() {};
@ -43,14 +57,14 @@ class Chunk {
private:
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 working{false};
std::shared_ptr<xe::Model> chunkMesh;
std::vector<float> vertexData;
std::vector<uint8_t> blocks;
xe::Model::Data vertexData;
std::vector<uint8_t> cubes;
std::thread worker;
};

View file

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

View file

@ -4,10 +4,10 @@ namespace app {
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")
.addVertexBinding(0, 3, 0) // position
.addVertexBinding(1, 3, 12) // normal
.addVertexBinding(2, 2, 24) // uvs
.addVertexBinding(3, 1, 32) // texture
.addVertexBindingf(0, 3, 0) // position
.addVertexBindingf(1, 3, 12) // normal
.addVertexBindingf(2, 2, 24) // uvs
.addVertexBindingi(3, 1, 32) // texture
.setVertexSize(36)
.addPushConstant(sizeof(PushConstant))
.addUniformBinding(0, sizeof(UniformBuffer))