Created raymarching branch
This commit is contained in:
parent
caff659c1f
commit
5df7032caa
160
Model/Model.cpp
160
Model/Model.cpp
@ -1,160 +0,0 @@
|
|||||||
#include <Model/Model.hpp>
|
|
||||||
|
|
||||||
#include <util/log.hpp>
|
|
||||||
#include <util/file.hpp>
|
|
||||||
|
|
||||||
#define TINYGLTF_IMPLEMENTATION
|
|
||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
||||||
#include <tinygltf/tiny_gltf.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
|
||||||
|
|
||||||
Model::Model(vk::PhysicalDevice phys_dev, vk::Device dev, const std::string& fname) {
|
|
||||||
Log::debug("Loading model " + fname + "\n");
|
|
||||||
|
|
||||||
tinygltf::TinyGLTF loader;
|
|
||||||
std::string err, warn;
|
|
||||||
|
|
||||||
model = std::make_shared<tinygltf::Model>();
|
|
||||||
|
|
||||||
auto ret = loader.LoadASCIIFromFile(model.get(), &err, &warn, fname);
|
|
||||||
|
|
||||||
if(!warn.empty()) {
|
|
||||||
Log::debug(fname + ": " + warn);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!err.empty()) {
|
|
||||||
Log::debug(fname + ": " + err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!ret) {
|
|
||||||
Log::error("Failed to pase glTF model\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto& node: model->nodes)
|
|
||||||
initNode(node, nullptr);
|
|
||||||
|
|
||||||
/* vertex, index buffer should be populated now */
|
|
||||||
Log::debug("%zu vertices loaded from model " + fname + "\n", vertices.size());
|
|
||||||
vertex_buffer = std::make_unique<VertexBuffer>(phys_dev, dev, vertices.size());
|
|
||||||
vertex_buffer->upload(vertices);
|
|
||||||
|
|
||||||
index_buffer = std::make_unique<Buffer>(phys_dev, dev, indices.size()*sizeof(uint16_t),
|
|
||||||
vk::BufferUsageFlagBits::eIndexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
|
|
||||||
index_buffer->upload(reinterpret_cast<uint8_t*>(indices.data()), static_cast<vk::DeviceSize>(indices.size()*sizeof(uint16_t)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Model::initVertices(Node* node, const tinygltf::Primitive& prim) {
|
|
||||||
Log::debug("Loading vertices\n");
|
|
||||||
uint32_t first_idx = indices.size();
|
|
||||||
uint32_t vert_start = vertices.size();
|
|
||||||
uint32_t idx_count = 0;
|
|
||||||
|
|
||||||
const float* pos_buff = nullptr;
|
|
||||||
const float* norm_buff = nullptr;
|
|
||||||
const float* uv_buff = nullptr;
|
|
||||||
size_t vertex_count = 0;
|
|
||||||
|
|
||||||
auto loc = prim.attributes.find("POSITION");
|
|
||||||
if(loc != prim.attributes.end()) {
|
|
||||||
auto accessor = model->accessors[loc->second];
|
|
||||||
const auto& view = model->bufferViews[accessor.bufferView];
|
|
||||||
pos_buff = reinterpret_cast<const float*>(&model->buffers[view.buffer].data[accessor.byteOffset+view.byteOffset]);
|
|
||||||
vertex_count = accessor.count;
|
|
||||||
}
|
|
||||||
loc = prim.attributes.find("NORMAL");
|
|
||||||
if(loc != prim.attributes.end()) {
|
|
||||||
auto accessor = model->accessors[loc->second];
|
|
||||||
const auto& view = model->bufferViews[accessor.bufferView];
|
|
||||||
norm_buff = reinterpret_cast<const float*>(&model->buffers[view.buffer].data[accessor.byteOffset+view.byteOffset]);
|
|
||||||
}
|
|
||||||
loc = prim.attributes.find("TEXCOORD_0");
|
|
||||||
if(loc != prim.attributes.end()) {
|
|
||||||
auto accessor = model->accessors[loc->second];
|
|
||||||
const auto& view = model->bufferViews[accessor.bufferView];
|
|
||||||
uv_buff = reinterpret_cast<const float*>(&model->buffers[view.buffer].data[accessor.byteOffset+view.byteOffset]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(size_t i = 0; i < vertex_count; i++) {
|
|
||||||
vertices.push_back(Vertex {
|
|
||||||
.pos = pos_buff? glm::make_vec3(pos_buff+i*3) : glm::vec3(0.0),
|
|
||||||
.norm = norm_buff? glm::normalize(glm::make_vec3(norm_buff+i*3)) : glm::vec3(0.0),
|
|
||||||
.uv = uv_buff? glm::make_vec2(uv_buff+i*2) : glm::vec2(0.0),
|
|
||||||
.color = glm::vec3(0.0),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::debug("Finished loading %zu vertices\n", vertex_count);
|
|
||||||
|
|
||||||
const auto& accessor = model->accessors[prim.indices];
|
|
||||||
const auto& view = model->bufferViews[accessor.bufferView];
|
|
||||||
const auto& buffer = model->buffers[view.buffer];
|
|
||||||
|
|
||||||
idx_count += accessor.count;
|
|
||||||
|
|
||||||
switch(accessor.componentType) {
|
|
||||||
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT:
|
|
||||||
for(size_t i = 0; i < accessor.count; i++)
|
|
||||||
indices.push_back(
|
|
||||||
reinterpret_cast<const uint32_t*>(
|
|
||||||
&buffer.data[accessor.byteOffset+view.byteOffset
|
|
||||||
])[i]
|
|
||||||
+ vert_start
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT:
|
|
||||||
for(size_t i = 0; i < accessor.count; i++)
|
|
||||||
indices.push_back(
|
|
||||||
reinterpret_cast<const uint16_t*>(
|
|
||||||
&buffer.data[accessor.byteOffset+view.byteOffset
|
|
||||||
])[i]
|
|
||||||
+ vert_start
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE:
|
|
||||||
for(size_t i = 0; i < accessor.count; i++)
|
|
||||||
indices.push_back(
|
|
||||||
reinterpret_cast<const uint8_t*>(
|
|
||||||
&buffer.data[accessor.byteOffset+view.byteOffset
|
|
||||||
])[i]
|
|
||||||
+ vert_start
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log::error("Unrecognized index type in model\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::debug("Loaded %zu indices of type %d\n", accessor.count, (accessor.componentType-TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE)/2+1);
|
|
||||||
|
|
||||||
node->mesh.push_back(Primitive {
|
|
||||||
.first_idx = first_idx,
|
|
||||||
.idx_count = idx_count,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Model::initNode(const tinygltf::Node& node, Node* parent, int level) {
|
|
||||||
Log::debug("%*sNode:"+node.name+"\n", level*4, " ");
|
|
||||||
|
|
||||||
Node* ret = new Node;
|
|
||||||
|
|
||||||
ret->parent = parent;
|
|
||||||
|
|
||||||
/* load kids */
|
|
||||||
for(auto& child_idx : node.children) {
|
|
||||||
initNode(model->nodes[child_idx], ret, level+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(node.mesh >= 0) {
|
|
||||||
const auto& mesh = model->meshes[node.mesh];
|
|
||||||
for(auto& prim : mesh.primitives) {
|
|
||||||
initVertices(ret, prim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ret->parent)
|
|
||||||
ret->parent->children.push_back(ret);
|
|
||||||
else
|
|
||||||
nodes.push_back(ret);
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Memory/Buffer.hpp>
|
|
||||||
|
|
||||||
#include <Renderer/VertexBuffer.hpp>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <tinygltf/tiny_gltf.h>
|
|
||||||
|
|
||||||
struct Model {
|
|
||||||
struct Primitive {
|
|
||||||
uint32_t first_idx;
|
|
||||||
uint32_t idx_count;
|
|
||||||
uint32_t mat_idx;
|
|
||||||
};
|
|
||||||
|
|
||||||
using Mesh = std::vector<Primitive>;
|
|
||||||
struct Node {
|
|
||||||
Node* parent;
|
|
||||||
std::vector<Node*> children;
|
|
||||||
Mesh mesh;
|
|
||||||
glm::mat4 mat;
|
|
||||||
~Node() {
|
|
||||||
for(auto& n : children)
|
|
||||||
delete n;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Model(vk::PhysicalDevice phys_dev, vk::Device dev, const std::string& fname);
|
|
||||||
|
|
||||||
std::shared_ptr<tinygltf::Model> model;
|
|
||||||
|
|
||||||
void initVertices(Node*, const tinygltf::Primitive&);
|
|
||||||
|
|
||||||
std::unique_ptr<VertexBuffer> vertex_buffer;
|
|
||||||
std::unique_ptr<Buffer> index_buffer;
|
|
||||||
std::vector<Vertex> vertices;
|
|
||||||
std::vector<uint16_t> indices;
|
|
||||||
|
|
||||||
/* recusively initialize nodes with an accumulative vertex and index buffer collector */
|
|
||||||
void initNode(const tinygltf::Node& node, Node* parent, int level = 0);
|
|
||||||
|
|
||||||
std::vector<Node*> nodes;
|
|
||||||
|
|
||||||
~Model() {
|
|
||||||
for(auto& n : nodes)
|
|
||||||
delete n;
|
|
||||||
|
|
||||||
vertex_buffer.reset();
|
|
||||||
index_buffer.reset();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,15 +1,12 @@
|
|||||||
# Pléascach
|
# Pléascach - Dronuilleog
|
||||||
|
|
||||||
|
No models, everything RAYMARCHED!!!!
|
||||||
|
|
||||||
## Short Term Changes
|
|
||||||
- Make index buffer device-local instead of host-coherent
|
|
||||||
- Possibly restructure Buffer class to use templates to change
|
|
||||||
constructor and functions to use staging buffers if needed.
|
|
||||||
## Constant Improvements
|
## Constant Improvements
|
||||||
- Add more comments
|
- Add more comments
|
||||||
## Long Term Improvements
|
## Long Term Improvements
|
||||||
- ~~Properly query surface to find supported formats for surfaces~~
|
- ~~Properly query surface to find supported formats for surfaces~~
|
||||||
- Fix all this cleanup vs destructor NONSENSE (inconsistency)
|
- Fix all this cleanup vs destructor NONSENSE (inconsistency)
|
||||||
- Add pipeline caching
|
|
||||||
- Make more robust solution to window minimization (flushing out Input system should provide candidates)
|
- Make more robust solution to window minimization (flushing out Input system should provide candidates)
|
||||||
- Command buffer per swapchain image
|
- Command buffer per swapchain image
|
||||||
- Make smaller memory allocation object to pass around instead of directly passing physical device to everything
|
- Make smaller memory allocation object to pass around instead of directly passing physical device to everything
|
||||||
@ -2,10 +2,6 @@
|
|||||||
#include <Renderer/Pipeline.hpp>
|
#include <Renderer/Pipeline.hpp>
|
||||||
#include <Renderer/VertexBuffer.hpp>
|
#include <Renderer/VertexBuffer.hpp>
|
||||||
|
|
||||||
#include <Scene/Terrain.hpp>
|
|
||||||
|
|
||||||
#include <Model/Model.hpp>
|
|
||||||
|
|
||||||
#include <Memory/Buffer.hpp>
|
#include <Memory/Buffer.hpp>
|
||||||
#include <Memory/Image.hpp>
|
#include <Memory/Image.hpp>
|
||||||
|
|
||||||
@ -77,16 +73,6 @@ void CommandBuffer::bind(const VertexBuffer& vertex_buffer, uint32_t binding) {
|
|||||||
command_buffer.bindVertexBuffers(binding, vertex_buffer.buffer->buffer, offsets);
|
command_buffer.bindVertexBuffers(binding, vertex_buffer.buffer->buffer, offsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBuffer::bind(std::shared_ptr<Model> model) {
|
|
||||||
bind(*model->vertex_buffer);
|
|
||||||
command_buffer.bindIndexBuffer(*model->index_buffer, 0, vk::IndexType::eUint16);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommandBuffer::bind(Terrain* terrain) {
|
|
||||||
bind(*terrain->vertex_buffer);
|
|
||||||
command_buffer.bindIndexBuffer(*terrain->index_buffer, 0, vk::IndexType::eUint32);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommandBuffer::draw(uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance) {
|
void CommandBuffer::draw(uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance) {
|
||||||
command_buffer.draw(vertex_count, instance_count, first_vertex, first_instance);
|
command_buffer.draw(vertex_count, instance_count, first_vertex, first_instance);
|
||||||
}
|
}
|
||||||
@ -97,7 +83,6 @@ void CommandBuffer::end() {
|
|||||||
|
|
||||||
void CommandBuffer::recycle() {
|
void CommandBuffer::recycle() {
|
||||||
command_buffer.reset();
|
command_buffer.reset();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBuffer::cleanup(vk::Device dev) {
|
void CommandBuffer::cleanup(vk::Device dev) {
|
||||||
|
|||||||
@ -31,8 +31,6 @@ struct CommandBuffer {
|
|||||||
void bind(const GraphicsPipeline& pipeline);
|
void bind(const GraphicsPipeline& pipeline);
|
||||||
void bind(vk::PipelineLayout layout, vk::ArrayProxy<vk::DescriptorSet> desc_sets);
|
void bind(vk::PipelineLayout layout, vk::ArrayProxy<vk::DescriptorSet> desc_sets);
|
||||||
void bind(const VertexBuffer& vertex_buffer, uint32_t binding = 0);
|
void bind(const VertexBuffer& vertex_buffer, uint32_t binding = 0);
|
||||||
void bind(std::shared_ptr<Model> model);
|
|
||||||
void bind(Terrain* terrain);
|
|
||||||
|
|
||||||
void draw(uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex = 0, uint32_t first_instance = 0);
|
void draw(uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex = 0, uint32_t first_instance = 0);
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include <util/log.hpp>
|
#include <util/log.hpp>
|
||||||
|
|
||||||
GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& shaders, const vk::Extent2D& extent, const RenderPass& render_pass, vk::ArrayProxy<vk::DescriptorSetLayoutBinding> bindings, const VertexBuffer& vertex_buffer, enum Type type) : dev(dev) {
|
GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& shaders, const vk::Extent2D& extent, const RenderPass& render_pass, vk::ArrayProxy<vk::DescriptorSetLayoutBinding> bindings, const VertexBuffer& vertex_buffer) : dev(dev) {
|
||||||
/* create layout
|
/* create layout
|
||||||
* Eventually add a graphicspipline constructor that allows specification of layouts etc
|
* Eventually add a graphicspipline constructor that allows specification of layouts etc
|
||||||
* kinda like how Image::Image has all those versions
|
* kinda like how Image::Image has all those versions
|
||||||
@ -75,27 +75,18 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& sh
|
|||||||
};
|
};
|
||||||
|
|
||||||
const auto input_asm_info = vk::PipelineInputAssemblyStateCreateInfo{
|
const auto input_asm_info = vk::PipelineInputAssemblyStateCreateInfo{
|
||||||
.topology = type == Type::eGLTF ? vk::PrimitiveTopology::eTriangleList : vk::PrimitiveTopology::ePatchList,
|
.topology = vk::PrimitiveTopology::eTriangleList,
|
||||||
/* matters later if we use strip primitives */
|
/* matters later if we use strip primitives */
|
||||||
.primitiveRestartEnable = vk::False,
|
.primitiveRestartEnable = vk::False,
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::PipelineTessellationStateCreateInfo* ptesselation_info = nullptr;
|
const vk::PipelineTessellationStateCreateInfo* ptesselation_info = nullptr;
|
||||||
|
|
||||||
const auto tess_info = vk::PipelineTessellationStateCreateInfo {
|
|
||||||
/* quads*/
|
|
||||||
.patchControlPoints = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
if(type == Type::eTERRAIN) {
|
|
||||||
ptesselation_info = &tess_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto raster_info = vk::PipelineRasterizationStateCreateInfo {
|
const auto raster_info = vk::PipelineRasterizationStateCreateInfo {
|
||||||
.depthClampEnable = vk::False,
|
.depthClampEnable = vk::False,
|
||||||
.polygonMode = type == Type::eGLTF? vk::PolygonMode::eFill : vk::PolygonMode::eFill,
|
.polygonMode = vk::PolygonMode::eFill,
|
||||||
.cullMode = vk::CullModeFlagBits::eNone,
|
.cullMode = vk::CullModeFlagBits::eNone,
|
||||||
.frontFace = Type::eGLTF ? vk::FrontFace::eClockwise : vk::FrontFace::eCounterClockwise,
|
.frontFace = vk::FrontFace::eCounterClockwise,
|
||||||
.depthBiasEnable = vk::False,
|
.depthBiasEnable = vk::False,
|
||||||
.lineWidth = 1.0,
|
.lineWidth = 1.0,
|
||||||
};
|
};
|
||||||
@ -106,8 +97,8 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& sh
|
|||||||
};
|
};
|
||||||
|
|
||||||
const auto depth_stencil_info = vk::PipelineDepthStencilStateCreateInfo{
|
const auto depth_stencil_info = vk::PipelineDepthStencilStateCreateInfo{
|
||||||
.depthTestEnable = vk::True,
|
.depthTestEnable = vk::False,
|
||||||
.depthWriteEnable = vk::True,
|
.depthWriteEnable = vk::False,
|
||||||
.depthCompareOp = vk::CompareOp::eLessOrEqual,
|
.depthCompareOp = vk::CompareOp::eLessOrEqual,
|
||||||
.depthBoundsTestEnable = vk::False,
|
.depthBoundsTestEnable = vk::False,
|
||||||
.stencilTestEnable = vk::False,
|
.stencilTestEnable = vk::False,
|
||||||
|
|||||||
@ -10,15 +10,10 @@ struct RenderPass;
|
|||||||
struct Texture;
|
struct Texture;
|
||||||
|
|
||||||
struct GraphicsPipeline {
|
struct GraphicsPipeline {
|
||||||
enum Type {
|
|
||||||
eGLTF,
|
|
||||||
eTERRAIN,
|
|
||||||
};
|
|
||||||
|
|
||||||
GraphicsPipeline(vk::Device dev, const std::vector<Shader>& shaders,
|
GraphicsPipeline(vk::Device dev, const std::vector<Shader>& shaders,
|
||||||
const vk::Extent2D& extent, const RenderPass& render_pass,
|
const vk::Extent2D& extent, const RenderPass& render_pass,
|
||||||
vk::ArrayProxy<vk::DescriptorSetLayoutBinding> bindings,
|
vk::ArrayProxy<vk::DescriptorSetLayoutBinding> bindings,
|
||||||
const VertexBuffer& vertex_buffer, enum Type type = Type::eGLTF);
|
const VertexBuffer& vertex_buffer);
|
||||||
vk::Device dev;
|
vk::Device dev;
|
||||||
vk::Pipeline pipeline;
|
vk::Pipeline pipeline;
|
||||||
vk::PipelineLayout layout;
|
vk::PipelineLayout layout;
|
||||||
|
|||||||
@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
#include <UI/UI.hpp>
|
#include <UI/UI.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std::string_literals;
|
using namespace std::string_literals;
|
||||||
|
|
||||||
Renderer::Renderer(Window& win) : win(win) {
|
Renderer::Renderer(Window& win) : win(win) {
|
||||||
@ -200,9 +198,8 @@ Renderer::Renderer(Window& win) : win(win) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
std::vector<Shader> shaders = {
|
std::vector<Shader> shaders = {
|
||||||
{dev, "assets/shaders/fraglight.vert.spv", vk::ShaderStageFlagBits::eVertex },
|
{dev, "assets/shaders/ray.vert.spv", vk::ShaderStageFlagBits::eVertex },
|
||||||
{ dev, "assets/shaders/fraglight.geom.spv", vk::ShaderStageFlagBits::eGeometry },
|
{ dev, "assets/shaders/ray.frag.spv", vk::ShaderStageFlagBits::eFragment },
|
||||||
{ dev, "assets/shaders/lambert.frag.spv", vk::ShaderStageFlagBits::eFragment },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> bindings = {
|
std::vector<vk::DescriptorSetLayoutBinding> bindings = {
|
||||||
@ -210,38 +207,25 @@ Renderer::Renderer(Window& win) : win(win) {
|
|||||||
textures[0].binding(1),
|
textures[0].binding(1),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* initialize models */
|
vertex_buffer = std::make_unique<VertexBuffer>(phys_dev, dev, 6);
|
||||||
Timer model_timer;
|
|
||||||
models.push_back(std::make_shared<Model>(phys_dev, dev, "assets/models/dragon.gltf"));
|
|
||||||
auto t = model_timer.stop();
|
|
||||||
|
|
||||||
Log::debug("Models loaded in %lf milliseconds\n", model_timer.read());
|
/* simple quad */
|
||||||
|
vertex_buffer->upload(std::vector<Vertex> {
|
||||||
|
{ { -1.0,-1.0 } },
|
||||||
|
{ { -1.0, 1.0 } },
|
||||||
|
{ { 1.0, 1.0 } },
|
||||||
|
{ { 1.0, 1.0 } },
|
||||||
|
{ { 1.0,-1.0 } },
|
||||||
|
{ { -1.0,-1.0 } },
|
||||||
|
});
|
||||||
|
|
||||||
pipeline = std::make_unique<GraphicsPipeline>(dev, shaders, swapchain->extent, *render_pass, bindings, *models[0]->vertex_buffer);
|
pipeline = std::make_unique<GraphicsPipeline>(dev, shaders, swapchain->extent, *render_pass, bindings, *vertex_buffer);
|
||||||
|
|
||||||
pipeline->update(0, *uniform_buffer);
|
pipeline->update(0, *uniform_buffer);
|
||||||
pipeline->update(1, textures[1]);
|
pipeline->update(1, textures[1]);
|
||||||
|
|
||||||
|
|
||||||
/* create Terrain */
|
|
||||||
terrain = std::make_unique<Terrain>(phys_dev, dev, textures[1]);
|
|
||||||
|
|
||||||
std::vector<Shader> terrain_shaders = {
|
|
||||||
{ dev, "assets/shaders/terrain.vert.spv", vk::ShaderStageFlagBits::eVertex },
|
|
||||||
{ dev, "assets/shaders/terrain.tesc.spv", vk::ShaderStageFlagBits::eTessellationControl },
|
|
||||||
{ dev, "assets/shaders/terrain.tese.spv", vk::ShaderStageFlagBits::eTessellationEvaluation },
|
|
||||||
{ dev, "assets/shaders/terrain.frag.spv", vk::ShaderStageFlagBits::eFragment },
|
|
||||||
};
|
|
||||||
|
|
||||||
terrain_pipeline = std::make_unique<GraphicsPipeline>(dev, terrain_shaders, swapchain->extent, *render_pass, bindings, *terrain->vertex_buffer, GraphicsPipeline::eTERRAIN);
|
|
||||||
|
|
||||||
terrain_pipeline->update(0, *uniform_buffer);
|
|
||||||
terrain_pipeline->update(1, textures[1]);
|
|
||||||
|
|
||||||
for (auto& shader : shaders)
|
for (auto& shader : shaders)
|
||||||
shader.cleanup();
|
shader.cleanup();
|
||||||
for (auto& shader : terrain_shaders)
|
|
||||||
shader.cleanup();
|
|
||||||
|
|
||||||
ui = std::make_unique<UI>(this);
|
ui = std::make_unique<UI>(this);
|
||||||
}
|
}
|
||||||
@ -339,30 +323,19 @@ void Renderer::draw() {
|
|||||||
|
|
||||||
auto sz = win.getDimensions();
|
auto sz = win.getDimensions();
|
||||||
|
|
||||||
const auto p = glm::perspective(glm::radians(90.0f), static_cast<float>(sz.width) / static_cast<float>(sz.height), 0.01f, 2000.0f);
|
uniform_buffer->upload(UniformData{
|
||||||
|
.viewport = glm::vec2(viewport.width, viewport.y),
|
||||||
auto uni = UniformData{
|
|
||||||
.view = cam.view(),
|
|
||||||
.proj = p,
|
|
||||||
.time = time,
|
.time = time,
|
||||||
.cam_pos = cam.pos,
|
.cam_pos = cam.pos,
|
||||||
.cam_dir = cam.dir(),
|
.cam_dir = cam.dir(),
|
||||||
.viewport = glm::vec2(viewport.width, viewport.y),
|
});
|
||||||
.tess_factor = tess_factor,
|
|
||||||
.tess_edge_size = tess_edge_size,
|
|
||||||
};
|
|
||||||
|
|
||||||
std::memcpy(uni.frustum, frustum(p * uni.view).data(), sizeof(uni.frustum));
|
command_buffer->bind(*pipeline);
|
||||||
|
|
||||||
uniform_buffer->upload(uni);
|
|
||||||
|
|
||||||
command_buffer->bind(*terrain_pipeline);
|
|
||||||
command_buffer->command_buffer.setViewport(0, viewport);
|
command_buffer->command_buffer.setViewport(0, viewport);
|
||||||
command_buffer->command_buffer.setScissor(0, scissor);
|
command_buffer->command_buffer.setScissor(0, scissor);
|
||||||
|
command_buffer->bind(pipeline->layout, pipeline->desc_set);
|
||||||
command_buffer->bind(terrain_pipeline->layout, terrain_pipeline->desc_set);
|
command_buffer->bind(*vertex_buffer);
|
||||||
command_buffer->bind(terrain.get());
|
command_buffer->command_buffer.draw(6, 1, 0, 0);
|
||||||
command_buffer->command_buffer.drawIndexed(terrain->indices.size(), 1, 0, 0, 0);
|
|
||||||
|
|
||||||
/* draw User Interface stuff */
|
/* draw User Interface stuff */
|
||||||
ui->newFrame();
|
ui->newFrame();
|
||||||
@ -421,17 +394,10 @@ Renderer::~Renderer() {
|
|||||||
|
|
||||||
ui.reset();
|
ui.reset();
|
||||||
|
|
||||||
for(auto& model : models)
|
|
||||||
model.reset();
|
|
||||||
|
|
||||||
terrain.reset();
|
|
||||||
|
|
||||||
uniform_buffer.reset();
|
uniform_buffer.reset();
|
||||||
vertex_buffer.reset();
|
vertex_buffer.reset();
|
||||||
terrain_pipeline.reset();
|
|
||||||
pipeline.reset();
|
pipeline.reset();
|
||||||
|
|
||||||
|
|
||||||
for (auto& tex : textures) {
|
for (auto& tex : textures) {
|
||||||
tex.cleanup();
|
tex.cleanup();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,9 +10,6 @@
|
|||||||
#include <Renderer/RenderPass.hpp>
|
#include <Renderer/RenderPass.hpp>
|
||||||
|
|
||||||
#include <Scene/Camera.hpp>
|
#include <Scene/Camera.hpp>
|
||||||
#include <Scene/Terrain.hpp>
|
|
||||||
|
|
||||||
#include <Model/Model.hpp>
|
|
||||||
|
|
||||||
#include <UI/UI.hpp>
|
#include <UI/UI.hpp>
|
||||||
|
|
||||||
@ -50,21 +47,18 @@ struct Renderer {
|
|||||||
|
|
||||||
|
|
||||||
std::unique_ptr<GraphicsPipeline> pipeline;
|
std::unique_ptr<GraphicsPipeline> pipeline;
|
||||||
std::unique_ptr<GraphicsPipeline> terrain_pipeline;
|
/* just holds single quad */
|
||||||
std::unique_ptr<VertexBuffer> vertex_buffer;
|
std::unique_ptr<VertexBuffer> vertex_buffer;
|
||||||
std::unique_ptr<UniformBuffer> uniform_buffer;
|
std::unique_ptr<UniformBuffer> uniform_buffer;
|
||||||
|
|
||||||
std::unique_ptr<Terrain> terrain;
|
|
||||||
|
|
||||||
std::vector<Texture> textures;
|
std::vector<Texture> textures;
|
||||||
|
|
||||||
uint32_t current_image_idx;
|
uint32_t current_image_idx;
|
||||||
uint64_t frame = 0;
|
uint64_t frame = 0;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Model>> models;
|
|
||||||
std::unique_ptr<UI> ui;
|
std::unique_ptr<UI> ui;
|
||||||
|
|
||||||
Camera cam{ .pos = glm::vec3(0.0, 5.0, 0.0), };
|
Camera cam{ .pos = glm::vec3(0.0, -10.0, 0.0), };
|
||||||
|
|
||||||
bool capture_mouse = false;
|
bool capture_mouse = false;
|
||||||
bool flycam = false;
|
bool flycam = false;
|
||||||
@ -72,7 +66,4 @@ struct Renderer {
|
|||||||
float time = 0.0;
|
float time = 0.0;
|
||||||
float speed = 1.0;
|
float speed = 1.0;
|
||||||
bool running = true;
|
bool running = true;
|
||||||
|
|
||||||
float tess_factor = 1.8f;
|
|
||||||
float tess_edge_size = 20.0f;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,16 +8,9 @@ UniformBuffer::UniformBuffer(vk::PhysicalDevice phys_dev, vk::Device dev) {
|
|||||||
vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible
|
vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible
|
||||||
);
|
);
|
||||||
|
|
||||||
Log::debug("Offset of view: %zu\n", offsetof(UniformData, view));
|
|
||||||
Log::debug("Offset of proj: %zu\n", offsetof(UniformData, proj));
|
|
||||||
Log::debug("Offset of time: %zu\n", offsetof(UniformData, time));
|
Log::debug("Offset of time: %zu\n", offsetof(UniformData, time));
|
||||||
Log::debug("Offset of pad0: %zu\n", offsetof(UniformData, pad0));
|
|
||||||
Log::debug("Offset of pad1: %zu\n", offsetof(UniformData, pad1));
|
|
||||||
Log::debug("Offset of pad2: %zu\n", offsetof(UniformData, pad2));
|
|
||||||
Log::debug("Offset of cam_pos: %zu\n", offsetof(UniformData, cam_pos));
|
Log::debug("Offset of cam_pos: %zu\n", offsetof(UniformData, cam_pos));
|
||||||
Log::debug("Offset of viewport: %zu\n", offsetof(UniformData, viewport));
|
Log::debug("Offset of viewport: %zu\n", offsetof(UniformData, viewport));
|
||||||
Log::debug("Offset of tess_factor: %zu\n", offsetof(UniformData, tess_factor));
|
|
||||||
Log::debug("Offset of tess_edge_size: %zu\n", offsetof(UniformData, tess_edge_size));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,34 +12,19 @@
|
|||||||
/* Uniform:
|
/* Uniform:
|
||||||
*
|
*
|
||||||
* layout (set = 0, binding = 0) uniform Matrices {
|
* layout (set = 0, binding = 0) uniform Matrices {
|
||||||
* mat4 view;
|
* vec2 viewport;
|
||||||
* mat4 proj;
|
|
||||||
* float time;
|
* float time;
|
||||||
* vec3 cam_pos;
|
* vec3 cam_pos;
|
||||||
* vec3 cam_dir;
|
* vec3 cam_dir;
|
||||||
* vec4 frustum[6];
|
|
||||||
* vec2 viewport;
|
|
||||||
* float tess_factor;
|
|
||||||
* float tess_edge_size;
|
|
||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct UniformData {
|
struct UniformData {
|
||||||
glm::mat4 view;
|
|
||||||
glm::mat4 proj;
|
|
||||||
float time;
|
|
||||||
float pad0;
|
|
||||||
float pad1;
|
|
||||||
float pad2;
|
|
||||||
glm::vec3 cam_pos;
|
|
||||||
float pad3;
|
|
||||||
glm::vec3 cam_dir;
|
|
||||||
float pad4;
|
|
||||||
glm::vec4 frustum[6];
|
|
||||||
glm::vec2 viewport;
|
glm::vec2 viewport;
|
||||||
float tess_factor;
|
float time;
|
||||||
float tess_edge_size;
|
glm::vec3 cam_pos;
|
||||||
|
glm::vec3 cam_dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UniformBuffer {
|
struct UniformBuffer {
|
||||||
|
|||||||
@ -9,10 +9,7 @@
|
|||||||
#include <tinygltf/tiny_gltf.h>
|
#include <tinygltf/tiny_gltf.h>
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
glm::vec3 pos;
|
glm::vec2 pos;
|
||||||
glm::vec3 norm;
|
|
||||||
glm::vec2 uv;
|
|
||||||
glm::vec3 color;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VertexBuffer {
|
struct VertexBuffer {
|
||||||
@ -37,24 +34,9 @@ struct VertexBuffer {
|
|||||||
{
|
{
|
||||||
.location = 0,
|
.location = 0,
|
||||||
.binding = binding,
|
.binding = binding,
|
||||||
.format = vk::Format::eR32G32B32Sfloat,
|
|
||||||
.offset = offsetof(Vertex, pos),
|
|
||||||
}, {
|
|
||||||
.location = 1,
|
|
||||||
.binding = binding,
|
|
||||||
.format = vk::Format::eR32G32B32Sfloat,
|
|
||||||
.offset = offsetof(Vertex, norm),
|
|
||||||
},{
|
|
||||||
.location = 2,
|
|
||||||
.binding = binding,
|
|
||||||
.format = vk::Format::eR32G32Sfloat,
|
.format = vk::Format::eR32G32Sfloat,
|
||||||
.offset = offsetof(Vertex, uv),
|
.offset = offsetof(Vertex, pos),
|
||||||
},{
|
},
|
||||||
.location = 3,
|
|
||||||
.binding = binding,
|
|
||||||
.format = vk::Format::eR32G32B32Sfloat,
|
|
||||||
.offset = offsetof(Vertex, color),
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1,118 +0,0 @@
|
|||||||
#include <Renderer/CommandBuffer.hpp>
|
|
||||||
#include <Scene/Terrain.hpp>
|
|
||||||
|
|
||||||
#include <util/int.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
float Terrain::getHeight(int32_t x, int32_t y) {
|
|
||||||
if (x < 0)
|
|
||||||
x += 64;
|
|
||||||
if (y < 0)
|
|
||||||
y += 64;
|
|
||||||
|
|
||||||
x %= 64;
|
|
||||||
y %= 64;
|
|
||||||
|
|
||||||
float xf = x;
|
|
||||||
float yf = y;
|
|
||||||
xf /= 64.0;
|
|
||||||
xf *= heightmap_tex->extent.width;
|
|
||||||
yf /= 64.0;
|
|
||||||
yf *= heightmap_tex->extent.height;
|
|
||||||
|
|
||||||
return static_cast<float>(heightmap_tex->image_data[static_cast<int>(static_cast<int>(yf) * heightmap_tex->extent.width + xf) * 4]) / 256.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
Terrain::Terrain(vk::PhysicalDevice phys_dev, vk::Device dev, Texture& tex) : phys_dev(phys_dev), dev(dev) {
|
|
||||||
/* tell Texture() not to free so we can apply our sobel filter */
|
|
||||||
heightmap_tex = &tex;
|
|
||||||
|
|
||||||
const auto patch_size = 64_u32;
|
|
||||||
const auto uv_scale = 1.0f;
|
|
||||||
const auto vertex_count = patch_size * patch_size;
|
|
||||||
|
|
||||||
vertices.resize(vertex_count);
|
|
||||||
|
|
||||||
for (size_t x = 0; x < patch_size; x++)
|
|
||||||
for (size_t y = 0; y < patch_size; y++)
|
|
||||||
vertices[x + y*patch_size] = (Vertex {
|
|
||||||
.pos = glm::vec3(
|
|
||||||
2.0f * x + 1.0f - patch_size,
|
|
||||||
0.0f,
|
|
||||||
2.0f * y + 1.0f - patch_size),
|
|
||||||
.uv = glm::vec2(static_cast<float>(x)/patch_size, static_cast<float>(y) / patch_size) * uv_scale,
|
|
||||||
});
|
|
||||||
|
|
||||||
/* use sobel filters to get normal:
|
|
||||||
* X sobel:
|
|
||||||
* +----+----+----+
|
|
||||||
* | +1 | +0 | -1 |
|
|
||||||
* +----+----+----+
|
|
||||||
* | +2 | +0 | -2 |
|
|
||||||
* +----+----+----+
|
|
||||||
* | +1 | +0 | -1 |
|
|
||||||
* +----+----+----+
|
|
||||||
* Y sobel:
|
|
||||||
* +----+----+----+
|
|
||||||
* | +1 | +2 | +1 |
|
|
||||||
* +----+----+----+
|
|
||||||
* | +0 | +0 | +0 |
|
|
||||||
* +----+----+----+
|
|
||||||
* | -1 | -2 | -1 |
|
|
||||||
* +----+----+----+
|
|
||||||
*/
|
|
||||||
|
|
||||||
for(auto x = 0_i32; x < patch_size; x++)
|
|
||||||
for (auto y = 0_i32; y < patch_size; y++) {
|
|
||||||
float moores_heights[3][3] = {
|
|
||||||
{ getHeight(x - 1, y - 1), getHeight(x - 1, y), getHeight(x - 1, y + 1) },
|
|
||||||
{ getHeight(x + 0, y - 1), getHeight(x + 0, y), getHeight(x + 0, y + 1) },
|
|
||||||
{ getHeight(x + 1, y - 1), getHeight(x + 1, y), getHeight(x + 1, y + 1) },
|
|
||||||
};
|
|
||||||
|
|
||||||
auto normal = glm::vec3(
|
|
||||||
/* x gets X sobel filter */
|
|
||||||
moores_heights[0][0] + 2.0f * moores_heights[0][1] + moores_heights[0][2]
|
|
||||||
- moores_heights[2][0] - 2.0f * moores_heights[2][1] - moores_heights[2][2],
|
|
||||||
0.0,
|
|
||||||
/* z gets Y sobel filter */
|
|
||||||
moores_heights[0][0] + 2.0f * moores_heights[1][0] + moores_heights[2][0]
|
|
||||||
- moores_heights[0][2] - 2.0f * moores_heights[1][2] - moores_heights[2][2]
|
|
||||||
);
|
|
||||||
/* fill in missing component, first scalar scales bump */
|
|
||||||
normal.y = 0.25 * glm::sqrt(glm::abs(1.0 - normal.x*normal.x - normal.z*normal.z));
|
|
||||||
|
|
||||||
//vertices[x + y * patch_size].norm = glm::vec3(getHeight(x, y));
|
|
||||||
vertices[x + y * patch_size].norm = glm::normalize(normal * glm::vec3(2.0f, 1.0f, 2.0f));
|
|
||||||
}
|
|
||||||
|
|
||||||
vertex_buffer = std::make_unique<VertexBuffer>(phys_dev, dev, vertices.size());
|
|
||||||
vertex_buffer->upload(vertices);
|
|
||||||
|
|
||||||
/* index generation */
|
|
||||||
const auto w = patch_size - 1;
|
|
||||||
indices.resize(w * w * 4);
|
|
||||||
|
|
||||||
for (auto x = 0_u32; x < w; x++)
|
|
||||||
for (auto y = 0_u32; y < w; y++) {
|
|
||||||
auto idx = (x + y * w) * 4;
|
|
||||||
indices[idx] = x+y*patch_size;
|
|
||||||
indices[idx+1] = indices[idx] + patch_size;
|
|
||||||
indices[idx+2] = indices[idx+1] + 1;
|
|
||||||
indices[idx + 3] = indices[idx] + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
index_buffer = std::make_unique<Buffer>(phys_dev, dev, sizeof(uint32_t)*indices.size(),
|
|
||||||
vk::BufferUsageFlagBits::eIndexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent
|
|
||||||
| vk::MemoryPropertyFlagBits::eHostVisible);
|
|
||||||
|
|
||||||
index_buffer->upload(indices);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Terrain::draw(CommandBuffer& cmd) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Terrain::~Terrain() {
|
|
||||||
index_buffer.reset();
|
|
||||||
vertex_buffer.reset();
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Resources/Texture.hpp>
|
|
||||||
#include <Renderer/VertexBuffer.hpp>
|
|
||||||
|
|
||||||
#include <Memory/Buffer.hpp>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
struct CommandBuffer;
|
|
||||||
|
|
||||||
struct Terrain {
|
|
||||||
vk::PhysicalDevice phys_dev;
|
|
||||||
vk::Device dev;
|
|
||||||
Texture* heightmap_tex;
|
|
||||||
|
|
||||||
std::unique_ptr<VertexBuffer> vertex_buffer;
|
|
||||||
std::unique_ptr<Buffer> index_buffer;
|
|
||||||
std::vector<Vertex> vertices;
|
|
||||||
std::vector<uint32_t> indices;
|
|
||||||
|
|
||||||
Terrain(vk::PhysicalDevice phys_dev, vk::Device dev, Texture& hieghtmap);
|
|
||||||
float getHeight(int32_t x, int32_t y);
|
|
||||||
void draw(CommandBuffer& cmd);
|
|
||||||
~Terrain();
|
|
||||||
};
|
|
||||||
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#include <Scene/Camera.hpp>
|
#include <Scene/Camera.hpp>
|
||||||
|
|
||||||
UI::UI(Renderer* ren) : info{ .flycam = ren->flycam, .time = ren->time, .cam = ren->cam, .tess_factor = ren->tess_factor, .tess_edge_size = ren->tess_edge_size }, dev(ren->dev) {
|
UI::UI(Renderer* ren) : info { .flycam = ren->flycam, .time = ren->time, .cam = ren->cam }, dev(ren->dev) {
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
|
|
||||||
@ -92,8 +92,6 @@ void UI::newFrame() {
|
|||||||
ImGui::Text("FPS: %f", info.fps);
|
ImGui::Text("FPS: %f", info.fps);
|
||||||
ImGui::Text("Time: %f", info.time);
|
ImGui::Text("Time: %f", info.time);
|
||||||
ImGui::Checkbox("Fly Camera", &info.flycam);
|
ImGui::Checkbox("Fly Camera", &info.flycam);
|
||||||
ImGui::SliderFloat("Tessellation Factor", &info.tess_factor, 0.1, 10.0);
|
|
||||||
ImGui::SliderFloat("Edge Size", &info.tess_edge_size, 0.0, 40.0);
|
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,8 +15,6 @@ struct UI {
|
|||||||
float& time;
|
float& time;
|
||||||
/* camera stuff */
|
/* camera stuff */
|
||||||
Camera& cam;
|
Camera& cam;
|
||||||
float& tess_factor;
|
|
||||||
float& tess_edge_size;
|
|
||||||
} info;
|
} info;
|
||||||
|
|
||||||
vk::Device dev;
|
vk::Device dev;
|
||||||
|
|||||||
Binary file not shown.
@ -1,108 +0,0 @@
|
|||||||
{
|
|
||||||
"asset":{
|
|
||||||
"generator":"Khronos glTF Blender I/O v4.0.44",
|
|
||||||
"version":"2.0"
|
|
||||||
},
|
|
||||||
"scene":0,
|
|
||||||
"scenes":[
|
|
||||||
{
|
|
||||||
"name":"Scene",
|
|
||||||
"nodes":[
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nodes":[
|
|
||||||
{
|
|
||||||
"name":"Mball"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"Circle",
|
|
||||||
"translation":[
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
-2.97784423828125
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"Circle.001"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mesh":0,
|
|
||||||
"name":"Sphere"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meshes":[
|
|
||||||
{
|
|
||||||
"name":"Sphere",
|
|
||||||
"primitives":[
|
|
||||||
{
|
|
||||||
"attributes":{
|
|
||||||
"POSITION":0,
|
|
||||||
"NORMAL":1
|
|
||||||
},
|
|
||||||
"indices":2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"accessors":[
|
|
||||||
{
|
|
||||||
"bufferView":0,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":30729,
|
|
||||||
"max":[
|
|
||||||
0.9991506934165955,
|
|
||||||
0.9976890087127686,
|
|
||||||
0.9973824620246887
|
|
||||||
],
|
|
||||||
"min":[
|
|
||||||
-0.9990072846412659,
|
|
||||||
-0.9995680451393127,
|
|
||||||
-0.9988008141517639
|
|
||||||
],
|
|
||||||
"type":"VEC3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":1,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":30729,
|
|
||||||
"type":"VEC3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":2,
|
|
||||||
"componentType":5123,
|
|
||||||
"count":56796,
|
|
||||||
"type":"SCALAR"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bufferViews":[
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":368748,
|
|
||||||
"byteOffset":0,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":368748,
|
|
||||||
"byteOffset":368748,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":113592,
|
|
||||||
"byteOffset":737496,
|
|
||||||
"target":34963
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"buffers":[
|
|
||||||
{
|
|
||||||
"byteLength":851088,
|
|
||||||
"uri":"ball.bin"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,107 +0,0 @@
|
|||||||
{
|
|
||||||
"asset":{
|
|
||||||
"generator":"Khronos glTF Blender I/O v4.0.44",
|
|
||||||
"version":"2.0"
|
|
||||||
},
|
|
||||||
"scene":0,
|
|
||||||
"scenes":[
|
|
||||||
{
|
|
||||||
"name":"Scene",
|
|
||||||
"nodes":[
|
|
||||||
0
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nodes":[
|
|
||||||
{
|
|
||||||
"mesh":0,
|
|
||||||
"name":"stanford-bunny",
|
|
||||||
"rotation":[
|
|
||||||
0.7071068286895752,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0.7071068286895752
|
|
||||||
],
|
|
||||||
"scale":[
|
|
||||||
10.410737037658691,
|
|
||||||
10.410737037658691,
|
|
||||||
10.410737037658691
|
|
||||||
],
|
|
||||||
"translation":[
|
|
||||||
0,
|
|
||||||
-0.39514416456222534,
|
|
||||||
0
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meshes":[
|
|
||||||
{
|
|
||||||
"name":"stanford-bunny",
|
|
||||||
"primitives":[
|
|
||||||
{
|
|
||||||
"attributes":{
|
|
||||||
"POSITION":0,
|
|
||||||
"NORMAL":1
|
|
||||||
},
|
|
||||||
"indices":2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"accessors":[
|
|
||||||
{
|
|
||||||
"bufferView":0,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":207619,
|
|
||||||
"max":[
|
|
||||||
0.0610090009868145,
|
|
||||||
0.058800000697374344,
|
|
||||||
-0.032986998558044434
|
|
||||||
],
|
|
||||||
"min":[
|
|
||||||
-0.0946900025010109,
|
|
||||||
-0.06187399849295616,
|
|
||||||
-0.1873210072517395
|
|
||||||
],
|
|
||||||
"type":"VEC3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":1,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":207619,
|
|
||||||
"type":"VEC3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":2,
|
|
||||||
"componentType":5125,
|
|
||||||
"count":208353,
|
|
||||||
"type":"SCALAR"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bufferViews":[
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":2491428,
|
|
||||||
"byteOffset":0,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":2491428,
|
|
||||||
"byteOffset":2491428,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":833412,
|
|
||||||
"byteOffset":4982856,
|
|
||||||
"target":34963
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"buffers":[
|
|
||||||
{
|
|
||||||
"byteLength":5816268,
|
|
||||||
"uri":"bunny.bin"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -1,219 +0,0 @@
|
|||||||
{
|
|
||||||
"asset":{
|
|
||||||
"generator":"Khronos glTF Blender I/O v4.0.44",
|
|
||||||
"version":"2.0"
|
|
||||||
},
|
|
||||||
"scene":0,
|
|
||||||
"scenes":[
|
|
||||||
{
|
|
||||||
"name":"Scene",
|
|
||||||
"nodes":[
|
|
||||||
0,
|
|
||||||
1
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nodes":[
|
|
||||||
{
|
|
||||||
"mesh":0,
|
|
||||||
"name":"Suzanne",
|
|
||||||
"rotation":[
|
|
||||||
0.06356222927570343,
|
|
||||||
0.536848247051239,
|
|
||||||
-0.8056020140647888,
|
|
||||||
0.2424030303955078
|
|
||||||
],
|
|
||||||
"translation":[
|
|
||||||
0.1063065230846405,
|
|
||||||
-0.6601571440696716,
|
|
||||||
-0.6140139698982239
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mesh":1,
|
|
||||||
"name":"Cube",
|
|
||||||
"rotation":[
|
|
||||||
0.1050531193614006,
|
|
||||||
-0.23102691769599915,
|
|
||||||
-0.3264787197113037,
|
|
||||||
0.9104955196380615
|
|
||||||
],
|
|
||||||
"scale":[
|
|
||||||
0.6794998645782471,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"materials":[
|
|
||||||
{
|
|
||||||
"doubleSided":true,
|
|
||||||
"name":"Material",
|
|
||||||
"pbrMetallicRoughness":{
|
|
||||||
"baseColorFactor":[
|
|
||||||
0.800000011920929,
|
|
||||||
0.800000011920929,
|
|
||||||
0.800000011920929,
|
|
||||||
1
|
|
||||||
],
|
|
||||||
"metallicFactor":0,
|
|
||||||
"roughnessFactor":0.5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meshes":[
|
|
||||||
{
|
|
||||||
"name":"Suzanne",
|
|
||||||
"primitives":[
|
|
||||||
{
|
|
||||||
"attributes":{
|
|
||||||
"POSITION":0,
|
|
||||||
"NORMAL":1,
|
|
||||||
"TEXCOORD_0":2
|
|
||||||
},
|
|
||||||
"indices":3
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"Cube",
|
|
||||||
"primitives":[
|
|
||||||
{
|
|
||||||
"attributes":{
|
|
||||||
"POSITION":4,
|
|
||||||
"NORMAL":5,
|
|
||||||
"TEXCOORD_0":6
|
|
||||||
},
|
|
||||||
"indices":7,
|
|
||||||
"material":0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"accessors":[
|
|
||||||
{
|
|
||||||
"bufferView":0,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":1970,
|
|
||||||
"max":[
|
|
||||||
1.3671875,
|
|
||||||
0.984375,
|
|
||||||
0.8515625
|
|
||||||
],
|
|
||||||
"min":[
|
|
||||||
-1.3671875,
|
|
||||||
-0.984375,
|
|
||||||
-0.8515625
|
|
||||||
],
|
|
||||||
"type":"VEC3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":1,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":1970,
|
|
||||||
"type":"VEC3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":2,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":1970,
|
|
||||||
"type":"VEC2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":3,
|
|
||||||
"componentType":5123,
|
|
||||||
"count":2904,
|
|
||||||
"type":"SCALAR"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":4,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":24,
|
|
||||||
"max":[
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
],
|
|
||||||
"min":[
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
-1
|
|
||||||
],
|
|
||||||
"type":"VEC3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":5,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":24,
|
|
||||||
"type":"VEC3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":6,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":24,
|
|
||||||
"type":"VEC2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":7,
|
|
||||||
"componentType":5123,
|
|
||||||
"count":36,
|
|
||||||
"type":"SCALAR"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bufferViews":[
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":23640,
|
|
||||||
"byteOffset":0,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":23640,
|
|
||||||
"byteOffset":23640,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":15760,
|
|
||||||
"byteOffset":47280,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":5808,
|
|
||||||
"byteOffset":63040,
|
|
||||||
"target":34963
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":288,
|
|
||||||
"byteOffset":68848,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":288,
|
|
||||||
"byteOffset":69136,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":192,
|
|
||||||
"byteOffset":69424,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":72,
|
|
||||||
"byteOffset":69616,
|
|
||||||
"target":34963
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"buffers":[
|
|
||||||
{
|
|
||||||
"byteLength":69688,
|
|
||||||
"uri":"monk.bin"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,219 +0,0 @@
|
|||||||
{
|
|
||||||
"asset":{
|
|
||||||
"generator":"Khronos glTF Blender I/O v4.0.44",
|
|
||||||
"version":"2.0"
|
|
||||||
},
|
|
||||||
"scene":0,
|
|
||||||
"scenes":[
|
|
||||||
{
|
|
||||||
"name":"Scene",
|
|
||||||
"nodes":[
|
|
||||||
0,
|
|
||||||
1
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nodes":[
|
|
||||||
{
|
|
||||||
"mesh":0,
|
|
||||||
"name":"Suzanne",
|
|
||||||
"rotation":[
|
|
||||||
0.06356222927570343,
|
|
||||||
0.536848247051239,
|
|
||||||
-0.8056020140647888,
|
|
||||||
0.2424030303955078
|
|
||||||
],
|
|
||||||
"translation":[
|
|
||||||
0.1063065230846405,
|
|
||||||
-0.6601571440696716,
|
|
||||||
-0.6140139698982239
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mesh":1,
|
|
||||||
"name":"Cube",
|
|
||||||
"rotation":[
|
|
||||||
0.1050531193614006,
|
|
||||||
-0.23102691769599915,
|
|
||||||
-0.3264787197113037,
|
|
||||||
0.9104955196380615
|
|
||||||
],
|
|
||||||
"scale":[
|
|
||||||
0.6794998645782471,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"materials":[
|
|
||||||
{
|
|
||||||
"doubleSided":true,
|
|
||||||
"name":"Material",
|
|
||||||
"pbrMetallicRoughness":{
|
|
||||||
"baseColorFactor":[
|
|
||||||
0.800000011920929,
|
|
||||||
0.800000011920929,
|
|
||||||
0.800000011920929,
|
|
||||||
1
|
|
||||||
],
|
|
||||||
"metallicFactor":0,
|
|
||||||
"roughnessFactor":0.5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meshes":[
|
|
||||||
{
|
|
||||||
"name":"Suzanne",
|
|
||||||
"primitives":[
|
|
||||||
{
|
|
||||||
"attributes":{
|
|
||||||
"POSITION":0,
|
|
||||||
"NORMAL":1,
|
|
||||||
"TEXCOORD_0":2
|
|
||||||
},
|
|
||||||
"indices":3
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"Cube",
|
|
||||||
"primitives":[
|
|
||||||
{
|
|
||||||
"attributes":{
|
|
||||||
"POSITION":4,
|
|
||||||
"NORMAL":5,
|
|
||||||
"TEXCOORD_0":6
|
|
||||||
},
|
|
||||||
"indices":7,
|
|
||||||
"material":0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"accessors":[
|
|
||||||
{
|
|
||||||
"bufferView":0,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":1970,
|
|
||||||
"max":[
|
|
||||||
1.3671875,
|
|
||||||
0.984375,
|
|
||||||
0.8515625
|
|
||||||
],
|
|
||||||
"min":[
|
|
||||||
-1.3671875,
|
|
||||||
-0.984375,
|
|
||||||
-0.8515625
|
|
||||||
],
|
|
||||||
"type":"VEC3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":1,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":1970,
|
|
||||||
"type":"VEC3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":2,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":1970,
|
|
||||||
"type":"VEC2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":3,
|
|
||||||
"componentType":5123,
|
|
||||||
"count":2904,
|
|
||||||
"type":"SCALAR"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":4,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":24,
|
|
||||||
"max":[
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
],
|
|
||||||
"min":[
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
-1
|
|
||||||
],
|
|
||||||
"type":"VEC3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":5,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":24,
|
|
||||||
"type":"VEC3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":6,
|
|
||||||
"componentType":5126,
|
|
||||||
"count":24,
|
|
||||||
"type":"VEC2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bufferView":7,
|
|
||||||
"componentType":5123,
|
|
||||||
"count":36,
|
|
||||||
"type":"SCALAR"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bufferViews":[
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":23640,
|
|
||||||
"byteOffset":0,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":23640,
|
|
||||||
"byteOffset":23640,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":15760,
|
|
||||||
"byteOffset":47280,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":5808,
|
|
||||||
"byteOffset":63040,
|
|
||||||
"target":34963
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":288,
|
|
||||||
"byteOffset":68848,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":288,
|
|
||||||
"byteOffset":69136,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":192,
|
|
||||||
"byteOffset":69424,
|
|
||||||
"target":34962
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"buffer":0,
|
|
||||||
"byteLength":72,
|
|
||||||
"byteOffset":69616,
|
|
||||||
"target":34963
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"buffers":[
|
|
||||||
{
|
|
||||||
"byteLength":69688,
|
|
||||||
"uri":"monkebox.bin"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 norm;
|
|
||||||
layout (location = 1) in vec2 texCoord;
|
|
||||||
layout (location = 0) out vec4 FragColor;
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 mvp;
|
|
||||||
float time;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout (set = 0, binding = 1) uniform sampler2D tex;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
FragColor = vec4(norm, 1.0);
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,27 +0,0 @@
|
|||||||
#version 450 core
|
|
||||||
|
|
||||||
layout (triangles) in;
|
|
||||||
layout (triangle_strip) out;
|
|
||||||
layout (max_vertices = 3) out;
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 norm[];
|
|
||||||
layout (location = 1) in vec2 texCoord[];
|
|
||||||
|
|
||||||
layout (location = 0) out vec3 _norm;
|
|
||||||
layout (location = 1) out vec2 _texCoord;
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 mvp;
|
|
||||||
float time;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void main(void) {
|
|
||||||
for(int i = 0; i < gl_in.length(); i++) {
|
|
||||||
gl_Position = mvp * gl_in[i].gl_Position;
|
|
||||||
_norm = norm[i];
|
|
||||||
_texCoord = texCoord[i];
|
|
||||||
EmitVertex();
|
|
||||||
}
|
|
||||||
EndPrimitive();
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,18 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
layout (location = 0) in vec3 aPos;
|
|
||||||
layout (location = 1) in vec3 aNorm;
|
|
||||||
layout (location = 2) in vec2 aTexCoord;
|
|
||||||
|
|
||||||
layout (location = 0) out vec3 norm;
|
|
||||||
layout (location = 1) out vec2 texCoord;
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 mvp;
|
|
||||||
float time;
|
|
||||||
};
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = vec4(aPos + (vec3(10.0) * gl_InstanceIndex), 1.0);
|
|
||||||
texCoord = aTexCoord;
|
|
||||||
norm = aNorm;
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,44 +0,0 @@
|
|||||||
#version 450 core
|
|
||||||
|
|
||||||
layout (triangles) in;
|
|
||||||
layout (triangle_strip) out;
|
|
||||||
layout (max_vertices = 3) out;
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 norm[];
|
|
||||||
layout (location = 1) in vec2 texCoord[];
|
|
||||||
|
|
||||||
layout (location = 0) out vec3 _norm;
|
|
||||||
layout (location = 1) out vec2 _texCoord;
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 mvp;
|
|
||||||
float time;
|
|
||||||
};
|
|
||||||
|
|
||||||
vec4 explode(vec4 pos, vec3 n) {
|
|
||||||
float mag = 2.0;
|
|
||||||
vec3 dir = n * (time-3.0)/10.0 * mag;
|
|
||||||
return pos + vec4(dir, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(void) {
|
|
||||||
if (time < 3.0) {
|
|
||||||
for(int i = 0; i < gl_in.length(); i++) {
|
|
||||||
gl_Position = mvp * gl_in[i].gl_Position;
|
|
||||||
_norm = norm[i];
|
|
||||||
_texCoord = texCoord[i];
|
|
||||||
EmitVertex();
|
|
||||||
}
|
|
||||||
EndPrimitive();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vec3 n = norm[0] + norm[1] + norm[2];
|
|
||||||
n/=3;
|
|
||||||
for(int i = 0; i < gl_in.length(); i++) {
|
|
||||||
gl_Position = mvp * explode(gl_in[i].gl_Position, n);
|
|
||||||
_texCoord = texCoord[i];
|
|
||||||
_norm = n;
|
|
||||||
EmitVertex();
|
|
||||||
}
|
|
||||||
EndPrimitive();
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,30 +0,0 @@
|
|||||||
#version 450 core
|
|
||||||
|
|
||||||
layout (triangles) in;
|
|
||||||
layout (triangle_strip) out;
|
|
||||||
layout (max_vertices = 3) out;
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 norm[];
|
|
||||||
layout (location = 1) in vec2 texCoord[];
|
|
||||||
layout (location = 2) in vec3 pos[];
|
|
||||||
|
|
||||||
layout (location = 0) out vec3 _norm;
|
|
||||||
layout (location = 1) out vec2 _texCoord;
|
|
||||||
layout (location = 2) out vec3 _pos;
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 mvp;
|
|
||||||
float time;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void main(void) {
|
|
||||||
for(int i = 0; i < gl_in.length(); i++) {
|
|
||||||
gl_Position = mvp * gl_in[i].gl_Position;
|
|
||||||
_norm = norm[i];
|
|
||||||
_texCoord = texCoord[i];
|
|
||||||
_pos = pos[i];
|
|
||||||
EmitVertex();
|
|
||||||
}
|
|
||||||
EndPrimitive();
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,20 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
layout (location = 0) in vec3 aPos;
|
|
||||||
layout (location = 1) in vec3 aNorm;
|
|
||||||
layout (location = 2) in vec2 aTexCoord;
|
|
||||||
|
|
||||||
layout (location = 0) out vec3 norm;
|
|
||||||
layout (location = 1) out vec2 texCoord;
|
|
||||||
layout (location = 2) out vec3 pos;
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 mvp;
|
|
||||||
float time;
|
|
||||||
};
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
pos = (aPos + (vec3(10.0) * gl_InstanceIndex));
|
|
||||||
gl_Position = vec4(pos, 1.0);
|
|
||||||
texCoord = aTexCoord;
|
|
||||||
norm = aNorm;
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,44 +0,0 @@
|
|||||||
#version 450 core
|
|
||||||
|
|
||||||
layout (triangles) in;
|
|
||||||
layout (triangle_strip) out;
|
|
||||||
layout (max_vertices = 6) out;
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 norm[];
|
|
||||||
layout (location = 1) in vec2 texCoord[];
|
|
||||||
|
|
||||||
layout (location = 0) out vec3 _norm;
|
|
||||||
layout (location = 1) out vec2 _texCoord;
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 mvp;
|
|
||||||
float time;
|
|
||||||
};
|
|
||||||
|
|
||||||
vec4 explode(vec4 pos, vec3 n) {
|
|
||||||
float mag = 2.0;
|
|
||||||
vec3 dir = n * (sin(time/10.0)-3.0)/10.0 * mag;
|
|
||||||
return pos + vec4(dir, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void main(void) {
|
|
||||||
|
|
||||||
if (time < 3.0) {
|
|
||||||
for(int i = 0; i < gl_in.length(); i++) {
|
|
||||||
gl_Position = mvp * gl_in[i].gl_Position;
|
|
||||||
_norm = norm[i];
|
|
||||||
_texCoord = texCoord[i];
|
|
||||||
EmitVertex();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vec3 n = norm[0] + norm[1] + norm[2];
|
|
||||||
n/=3;
|
|
||||||
for(int i = 0; i < gl_in.length(); i++) {
|
|
||||||
gl_Position = mvp * explode(gl_in[i].gl_Position*abs(cos(time)), n);
|
|
||||||
_texCoord = texCoord[i];
|
|
||||||
_norm = n;
|
|
||||||
EmitVertex();
|
|
||||||
}
|
|
||||||
EndPrimitive();
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,38 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 norm;
|
|
||||||
layout (location = 1) in vec2 texCoord;
|
|
||||||
layout (location = 2) in vec3 pos;
|
|
||||||
layout (location = 0) out vec4 FragColor;
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 view;
|
|
||||||
mat4 proj;
|
|
||||||
float time;
|
|
||||||
vec3 cam_pos;
|
|
||||||
vec3 cam_dir;
|
|
||||||
vec4 frustum[6];
|
|
||||||
vec2 viewport;
|
|
||||||
float tess_factor;
|
|
||||||
float tess_edge_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout (set = 0, binding = 1) uniform sampler2D tex;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec3 light_pos = normalize(vec3(cos(time), sin(time), 0.0))*10.0;
|
|
||||||
/* calculate highlight using angle between fragment and viewer */
|
|
||||||
vec3 I = normalize(cam_pos-pos);
|
|
||||||
vec3 L = normalize(light_pos-pos);
|
|
||||||
vec3 cool = vec3(0.0, 0.0, 0.55);
|
|
||||||
vec3 warm = vec3(0.3, 0.3, 0);
|
|
||||||
float t = (dot(norm, L)+1.0)/2.0;
|
|
||||||
vec3 r = 2.0*(dot(norm,L)*norm)-L;
|
|
||||||
float s = 100.0*(dot(r,I))-97.0;
|
|
||||||
if(s < 0.0)
|
|
||||||
s = 0.0;
|
|
||||||
else if(s > 1.0)
|
|
||||||
s = 1.0;
|
|
||||||
|
|
||||||
FragColor = vec4((1.0-s)*(t*warm + (vec3(0.5)-t)*cool) + s*vec3(1.0), 1.0);
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,29 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 norm;
|
|
||||||
layout (location = 1) in vec2 texCoord;
|
|
||||||
layout (location = 2) in vec3 pos;
|
|
||||||
layout (location = 0) out vec4 FragColor;
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 view;
|
|
||||||
mat4 proj;
|
|
||||||
float time;
|
|
||||||
vec3 cam_pos;
|
|
||||||
vec3 cam_dir;
|
|
||||||
vec4 frustum[6];
|
|
||||||
vec2 viewport;
|
|
||||||
float tess_factor;
|
|
||||||
float tess_edge_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout (set = 0, binding = 1) uniform sampler2D tex;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec3 light_pos = normalize(vec3(cos(time), sin(time), 0.0))*10.0;
|
|
||||||
vec3 L = normalize(light_pos-pos);
|
|
||||||
float r = length(light_pos-pos);
|
|
||||||
float t = clamp(dot(L, norm), 0.0, 1.0) * 20.0/(r*r);
|
|
||||||
|
|
||||||
FragColor = vec4(t, t/2.0, t*2.0, 1.0);
|
|
||||||
}
|
|
||||||
Binary file not shown.
16
assets/shaders/ray.frag
Normal file
16
assets/shaders/ray.frag
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout (set = 0, binding = 0) uniform Matrices {
|
||||||
|
vec2 viewport;
|
||||||
|
float time;
|
||||||
|
vec3 cam_pos;
|
||||||
|
vec3 cam_dir;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 texCoord;
|
||||||
|
|
||||||
|
layout (location = 0) out vec4 fragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
fragColor = vec4(abs(texCoord), abs(cos(time)), 1.0);
|
||||||
|
}
|
||||||
BIN
assets/shaders/ray.frag.spv
Normal file
BIN
assets/shaders/ray.frag.spv
Normal file
Binary file not shown.
17
assets/shaders/ray.vert
Normal file
17
assets/shaders/ray.vert
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 460 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 aCoord;
|
||||||
|
|
||||||
|
layout (location = 0) out vec2 texCoord;
|
||||||
|
|
||||||
|
layout (set = 0, binding = 0) uniform Matrices {
|
||||||
|
vec2 viewport;
|
||||||
|
float time;
|
||||||
|
vec3 cam_pos;
|
||||||
|
vec3 cam_dir;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
texCoord = aCoord;
|
||||||
|
gl_Position = vec4(aCoord, 0.0, 1.0);
|
||||||
|
}
|
||||||
BIN
assets/shaders/ray.vert.spv
Normal file
BIN
assets/shaders/ray.vert.spv
Normal file
Binary file not shown.
@ -1,29 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 norm;
|
|
||||||
layout (location = 1) in vec2 texCoord;
|
|
||||||
layout (location = 2) in vec3 pos;
|
|
||||||
layout (location = 0) out vec4 FragColor;
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 view;
|
|
||||||
mat4 proj;
|
|
||||||
float time;
|
|
||||||
vec3 cam_pos;
|
|
||||||
vec3 cam_dir;
|
|
||||||
vec4 frustum[6];
|
|
||||||
vec2 viewport;
|
|
||||||
float tess_factor;
|
|
||||||
float tess_edge_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout (set = 0, binding = 1) uniform sampler2D heightmap;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
/* extract L (light direction) from view matrix */
|
|
||||||
vec3 L = -cam_dir;
|
|
||||||
float r = length(cam_pos-pos);
|
|
||||||
float t = clamp(dot(L, norm), 0.0, 1.0) * 20.0/(r*r);
|
|
||||||
|
|
||||||
FragColor = vec4(t*norm, 1.0);
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,89 +0,0 @@
|
|||||||
#version 450 core
|
|
||||||
#extension GL_EXT_debug_printf : enable
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 view;
|
|
||||||
mat4 proj;
|
|
||||||
float time;
|
|
||||||
vec3 cam_pos;
|
|
||||||
vec3 cam_dir;
|
|
||||||
vec4 frustum[6];
|
|
||||||
vec2 viewport;
|
|
||||||
float tess_factor;
|
|
||||||
float tess_edge_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(set = 0, binding = 1) uniform sampler2D heightmap;
|
|
||||||
|
|
||||||
layout (vertices = 4) out;
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 norm[];
|
|
||||||
layout (location = 1) in vec2 texCoord[];
|
|
||||||
layout (location = 2) in vec3 pos[];
|
|
||||||
|
|
||||||
layout (location = 0) out vec3 _norm[4];
|
|
||||||
layout (location = 1) out vec2 _texCoord[4];
|
|
||||||
layout (location = 2) out vec3 _pos[4];
|
|
||||||
|
|
||||||
|
|
||||||
float screen_space_tess(vec4 p0, vec4 p1) {
|
|
||||||
/* calc midpoint + distance btw the two points */
|
|
||||||
vec4 midp = 0.5*(p0+p1);
|
|
||||||
float r = distance(p0, p1) / 2.0;
|
|
||||||
|
|
||||||
vec4 v0 = view * midp;
|
|
||||||
|
|
||||||
/* project into clip spaace */
|
|
||||||
vec4 clip0 = proj * (v0 - vec4(r, vec3(0.0)));
|
|
||||||
vec4 clip1 = proj * (v0 + vec4(r, vec3(0.0)));
|
|
||||||
|
|
||||||
clip0 /= clip0.w;
|
|
||||||
clip1 /= clip1.w;
|
|
||||||
|
|
||||||
/* convert to viewport coords */
|
|
||||||
clip0.xy *= viewport;
|
|
||||||
clip1.xy *= viewport;
|
|
||||||
|
|
||||||
return clamp(distance(clip0, clip1) / tess_edge_size * tess_factor, 1.0, 64.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool frustum_culling() {
|
|
||||||
/* square root of patch size */
|
|
||||||
const float r = 8.0f;
|
|
||||||
/* ensure this is consistent with tese shader */
|
|
||||||
vec4 fpos = gl_in[gl_InvocationID].gl_Position;
|
|
||||||
fpos.y += 15.0 * textureLod(heightmap, texCoord[0], 0.0).r;
|
|
||||||
|
|
||||||
for(int i = 0; i < 6; i++) {
|
|
||||||
if(dot(fpos, frustum[i]) + r < 0.0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
|
|
||||||
if(gl_InvocationID == 0) {
|
|
||||||
/* perform frustum culling */
|
|
||||||
if(frustum_culling()) {
|
|
||||||
gl_TessLevelOuter[0] = screen_space_tess(gl_in[3].gl_Position, gl_in[0].gl_Position);
|
|
||||||
gl_TessLevelOuter[1] = screen_space_tess(gl_in[0].gl_Position, gl_in[1].gl_Position);
|
|
||||||
gl_TessLevelOuter[2] = screen_space_tess(gl_in[1].gl_Position, gl_in[2].gl_Position);
|
|
||||||
gl_TessLevelOuter[3] = screen_space_tess(gl_in[2].gl_Position, gl_in[3].gl_Position);
|
|
||||||
gl_TessLevelInner[0] = mix(gl_TessLevelOuter[0], gl_TessLevelOuter[3], 0.5);
|
|
||||||
gl_TessLevelInner[1] = mix(gl_TessLevelOuter[2], gl_TessLevelOuter[1], 0.5);
|
|
||||||
} else {
|
|
||||||
gl_TessLevelOuter[0] = 0.0;
|
|
||||||
gl_TessLevelOuter[1] = 0.0;
|
|
||||||
gl_TessLevelOuter[2] = 0.0;
|
|
||||||
gl_TessLevelOuter[3] = 0.0;
|
|
||||||
gl_TessLevelInner[0] = 0.0;
|
|
||||||
gl_TessLevelInner[1] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
|
|
||||||
_norm[gl_InvocationID] = norm[gl_InvocationID];
|
|
||||||
_texCoord[gl_InvocationID] = texCoord[gl_InvocationID];
|
|
||||||
_pos[gl_InvocationID] = pos[gl_InvocationID];
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,49 +0,0 @@
|
|||||||
#version 450 core
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 view;
|
|
||||||
mat4 proj;
|
|
||||||
float time;
|
|
||||||
vec3 cam_pos;
|
|
||||||
vec3 cam_dir;
|
|
||||||
vec4 frustum[6];
|
|
||||||
vec2 viewport;
|
|
||||||
float tess_factor;
|
|
||||||
float tess_edge_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(set = 0, binding = 1) uniform sampler2D heightmap;
|
|
||||||
|
|
||||||
layout(quads, equal_spacing, ccw) in;
|
|
||||||
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 norm[];
|
|
||||||
layout (location = 1) in vec2 texCoord[];
|
|
||||||
layout (location = 2) in vec3 pos[];
|
|
||||||
|
|
||||||
layout (location = 0) out vec3 _norm;
|
|
||||||
layout (location = 1) out vec2 _texCoord;
|
|
||||||
layout (location = 2) out vec3 _pos;
|
|
||||||
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
/* interpolation of UV coordinates */
|
|
||||||
vec2 uv1 = mix(texCoord[0], texCoord[1], gl_TessCoord.x);
|
|
||||||
vec2 uv2 = mix(texCoord[3], texCoord[2], gl_TessCoord.x);
|
|
||||||
_texCoord = mix(uv1, uv2, gl_TessCoord.y);
|
|
||||||
|
|
||||||
|
|
||||||
vec3 norm1 = mix(norm[0], norm[1], gl_TessCoord.x);
|
|
||||||
vec3 norm2 = mix(norm[3], norm[2], gl_TessCoord.x);
|
|
||||||
_norm = mix(norm1, norm2, gl_TessCoord.y);
|
|
||||||
|
|
||||||
/* not displacing yet */
|
|
||||||
vec4 pos1 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);
|
|
||||||
vec4 pos2 = mix(gl_in[3].gl_Position, gl_in[2].gl_Position, gl_TessCoord.x);
|
|
||||||
|
|
||||||
vec4 fpos = mix(pos1, pos2, gl_TessCoord.y);
|
|
||||||
fpos.y += 15.0 * texture(heightmap, _texCoord).r;
|
|
||||||
|
|
||||||
_pos = fpos.xyz;
|
|
||||||
gl_Position = proj * view * fpos;
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,26 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
layout (location = 0) in vec3 aPos;
|
|
||||||
layout (location = 1) in vec3 aNorm;
|
|
||||||
layout (location = 2) in vec2 aTexCoord;
|
|
||||||
|
|
||||||
layout (location = 0) out vec3 norm;
|
|
||||||
layout (location = 1) out vec2 texCoord;
|
|
||||||
layout (location = 2) out vec3 pos;
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 view;
|
|
||||||
mat4 proj;
|
|
||||||
float time;
|
|
||||||
vec3 cam_pos;
|
|
||||||
vec4 frustum[6];
|
|
||||||
vec2 viewport;
|
|
||||||
float tess_factor;
|
|
||||||
float tess_edge_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
pos = aPos;
|
|
||||||
gl_Position = vec4(pos, 1.0);
|
|
||||||
texCoord = aTexCoord;
|
|
||||||
norm = aNorm;
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1,65 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 norm;
|
|
||||||
layout (location = 1) in vec2 texCoord;
|
|
||||||
layout (location = 0) out vec4 FragColor;
|
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform Matrices {
|
|
||||||
mat4 mvp;
|
|
||||||
float time;
|
|
||||||
float aspect_ratio;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 4-float alignment in memory*/
|
|
||||||
struct Ray {
|
|
||||||
vec3 orig;
|
|
||||||
float min;
|
|
||||||
vec3 dir;
|
|
||||||
float max;
|
|
||||||
};
|
|
||||||
|
|
||||||
vec3 ray_color(vec3 ray) {
|
|
||||||
float a = 0.5 * (ray.y+1.0);
|
|
||||||
|
|
||||||
return vec3(1.0-a) + a*vec3(0.5, 0.7, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* returns float of where you hit, or -1.0 */
|
|
||||||
float sphere(vec3 center, float r, Ray ray) {
|
|
||||||
vec3 p = ray.orig-center;
|
|
||||||
float a = dot(ray.dir, ray.dir);
|
|
||||||
float half_b = dot(p, ray.dir);
|
|
||||||
float c = dot(p, p) - r*r;
|
|
||||||
float discr = half_b*half_b - a*c;
|
|
||||||
|
|
||||||
if(discr < 0.0)
|
|
||||||
return -1.0;
|
|
||||||
|
|
||||||
return -half_b-sqrt(discr)/a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec2 pixel = texCoord*2.0-1.0;
|
|
||||||
Ray ray;
|
|
||||||
ray.orig = vec3(0.0);
|
|
||||||
ray.min = 0.1;
|
|
||||||
ray.max = 10000.0;
|
|
||||||
float fov = radians(90);
|
|
||||||
ray.dir = normalize(vec3(pixel.x * aspect_ratio, pixel.y, tan(fov/2.0)));
|
|
||||||
|
|
||||||
vec3 sphere_center = vec3(0.0, 0.0, 1.0);
|
|
||||||
|
|
||||||
float d = sphere(sphere_center, 0.5, ray);
|
|
||||||
|
|
||||||
FragColor = vec4(texCoord, 1.0, 1.0);
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(d < 0.0) {
|
|
||||||
FragColor = vec4(0.0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 n = normalize(ray.dir*d-sphere_center);
|
|
||||||
FragColor = vec4((n+vec3(1.0)) / 2.0, 1.0);
|
|
||||||
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 MiB |
Loading…
x
Reference in New Issue
Block a user