vertex buffer is not a byte vector, multi texture loading
This commit is contained in:
parent
873ca38c0d
commit
5a08c9c8e2
19 changed files with 140 additions and 249944 deletions
|
@ -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() {
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
0
engine/xe_vertex_array.cpp
Normal file
0
engine/xe_vertex_array.cpp
Normal file
0
engine/xe_vertex_array.hpp
Normal file
0
engine/xe_vertex_array.hpp
Normal file
Binary file not shown.
Before Width: | Height: | Size: 5.8 KiB |
BIN
res/image/dirt.png
Normal file
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
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
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in a new issue