Some unidentified vertex or index generation error

This commit is contained in:
Conál 2024-02-05 11:50:58 -05:00
parent a778a406d0
commit 8e2559cf26
20 changed files with 203 additions and 31 deletions

View File

@ -28,6 +28,8 @@ file(GLOB SHADER_SOURCE_FILES
assets/shaders/*.frag
assets/shaders/*.vert
assets/shaders/*.geom
assets/shaders/*.tese
assets/shaders/*.tesc
)
foreach(SHADER_SOURCE ${SHADER_SOURCE_FILES})

View File

@ -20,7 +20,7 @@ struct Buffer {
}
template<typename T>
inline void upload(const std::vector<T>& data) {
upload(reinterpret_cast<uint8_t*>(data.data()), data.size()*sizeof(T));
upload(reinterpret_cast<const uint8_t*>(data.data()), data.size()*sizeof(T));
}
operator vk::Buffer& () {

View File

@ -9,7 +9,7 @@
#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 = Type::GLTF) : 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, enum Type type) : dev(dev) {
/* create layout
* Eventually add a graphicspipline constructor that allows specification of layouts etc
* kinda like how Image::Image has all those versions
@ -80,10 +80,21 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& sh
.primitiveRestartEnable = vk::False,
};
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 {
.depthClampEnable = vk::False,
.polygonMode = type == Type::eGLTF? vk::PolygonMode::eFill : vk::PolygonMode::eLine,
.cullMode = vk::CullModeFlagBits::eBack,
.cullMode = vk::CullModeFlagBits::eNone,
.frontFace = vk::FrontFace::eCounterClockwise,
.depthBiasEnable = vk::False,
.lineWidth = 1.0,
@ -154,7 +165,7 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector<Shader>& sh
.pStages = shader_info.data(),
.pVertexInputState = &vertex_input_info,
.pInputAssemblyState = &input_asm_info,
.pTessellationState = nullptr,
.pTessellationState = ptesselation_info,
.pViewportState = &viewport_info,
.pRasterizationState = &raster_info,
.pMultisampleState = &multisample_info,

View File

@ -143,6 +143,8 @@ Renderer::Renderer(Window& win) : win(win) {
const auto features = vk::PhysicalDeviceFeatures{
.geometryShader = vk::True,
.tessellationShader = vk::True,
.fillModeNonSolid = vk::True,
};
auto dev_info = vk::DeviceCreateInfo{
@ -182,6 +184,7 @@ Renderer::Renderer(Window& win) : win(win) {
textures = createResources({
"assets/textures/oil.jpg",
"assets/textures/heightmap.png",
});
std::vector<Shader> shaders = {
@ -209,7 +212,7 @@ Renderer::Renderer(Window& win) : win(win) {
/* create Terrain */
terrain = std::make_unique<Terrain>(phys_dev, dev, textures[0]);
terrain = std::make_unique<Terrain>(phys_dev, dev, textures[1]);
std::vector<Shader> terrain_shaders = {
{ dev, "assets/shaders/terrain.vert.spv", vk::ShaderStageFlagBits::eVertex },
@ -218,7 +221,7 @@ Renderer::Renderer(Window& win) : win(win) {
{ 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 = std::make_unique<GraphicsPipeline>(dev, terrain_shaders, swapchain->extent, *render_pass, bindings, *terrain->vertex_buffer, GraphicsPipeline::eTERRAIN);
for (auto& shader : shaders)
shader.cleanup();
@ -236,7 +239,7 @@ std::vector<Texture> Renderer::createResources(const std::vector<std::string>& n
texture_cmd.begin();
for (const auto& name : names) {
ret.push_back({phys_dev, dev, texture_cmd, name});
ret.push_back({phys_dev, dev, texture_cmd, name, false});
}
texture_cmd.end();
@ -338,11 +341,13 @@ void Renderer::draw() {
uniform_buffer->upload(UniformData {
.mvp = p * cam.view(),
.time = time,
// .aspect_ratio= static_cast<float>(sz.width) / static_cast<float>(sz.height),
.cam_pos = cam.pos,
.viewport = glm::vec2(viewport.width, viewport.y),
.tess_factor = tess_factor,
.tess_edge_size = tess_edge_size,
});
command_buffer->command_buffer.drawIndexed(models[0]->indices.size(), 10, 0, 0, 0);
//command_buffer->command_buffer.drawIndexed(models[0]->indices.size(), 10, 0, 0, 0);
command_buffer->bind(*terrain_pipeline);
command_buffer->command_buffer.setViewport(0, viewport);
@ -411,10 +416,14 @@ Renderer::~Renderer() {
for(auto& model : models)
model.reset();
terrain.reset();
uniform_buffer.reset();
vertex_buffer.reset();
terrain_pipeline.reset();
pipeline.reset();
for (auto& tex : textures) {
tex.cleanup();
}

View File

@ -72,4 +72,7 @@ struct Renderer {
float time = 0.0;
float speed = 1.0;
bool running = true;
float tess_factor;
float tess_edge_size = 20.0f;
};

View File

@ -13,6 +13,9 @@ struct UniformData {
glm::mat4 mvp;
float time;
glm::vec3 cam_pos;
glm::vec2 viewport;
float tess_factor;
float tess_edge_size;
};
struct UniformBuffer {

View File

@ -18,6 +18,7 @@ Texture::Texture(vk::PhysicalDevice phys_dev, vk::Device dev, CommandBuffer& com
image_data = stbi_load(fname.c_str(), reinterpret_cast<int*>(&extent.width), reinterpret_cast<int*>(&extent.height), &n_channels, STBI_rgb_alpha);
Log::info("Texture is %dx%d loaded at %p\n", extent.width, extent.height, image_data);
extent.depth = 1;
image = std::make_unique<Image>(phys_dev, dev, extent, vk::Format::eR8G8B8A8Unorm,
@ -31,8 +32,10 @@ Texture::Texture(vk::PhysicalDevice phys_dev, vk::Device dev, CommandBuffer& com
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
staging->upload(image_data);
if(free_memory)
if(free_memory) {
stbi_image_free(image_data);
image_data = nullptr;
}
/* pipeline memory barrier ensures this doesn't get reordered wrong */

View File

@ -5,17 +5,16 @@
float Terrain::getHeight(int32_t x, int32_t y) {
Log::debug("Height queried at %d, %d\n", x, y);
if (x < 0)
x += heightmap_tex->extent.width;
x += 64;
if (y < 0)
y += heightmap_tex->extent.height;
y += 64;
if (x <= heightmap_tex->extent.width)
x -= heightmap_tex->extent.width;
if (y <= heightmap_tex->extent.height)
y -= heightmap_tex->extent.height;
x %= 64;
y %= 64;
return heightmap_tex->image_data[y * heightmap_tex->extent.width + x * 4];
return heightmap_tex->image_data[(y * heightmap_tex->extent.height * heightmap_tex->extent.width / 64 + x * heightmap_tex->extent.width / 64) * 4];
}
Terrain::Terrain(vk::PhysicalDevice phys_dev, vk::Device dev, Texture& tex) : phys_dev(phys_dev), dev(dev) {
@ -26,12 +25,15 @@ Terrain::Terrain(vk::PhysicalDevice phys_dev, vk::Device dev, Texture& tex) : ph
const auto uv_scale = 1.0f;
const auto vertex_count = patch_size * patch_size;
vertices.reserve(vertex_count);
vertices.resize(vertex_count);
for (size_t x = 0; x < patch_size; x++)
for (size_t y = 0; y < patch_size; y++)
vertices.push_back(Vertex {
.pos = glm::vec3(2.0f*x+1.0f - patch_size, 0.0f, 2.0f * y + 1.0f - patch_size),
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,
});
@ -54,8 +56,8 @@ Terrain::Terrain(vk::PhysicalDevice phys_dev, vk::Device dev, Texture& tex) : ph
* +----+----+----+
*/
for(auto x = 0_u32; x < patch_size; x++)
for (auto y = 0_u32; y < patch_size; y++) {
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) },
@ -84,8 +86,8 @@ Terrain::Terrain(vk::PhysicalDevice phys_dev, vk::Device dev, Texture& tex) : ph
const auto w = patch_size - 1;
indices.resize(w * w * 4);
for (auto x = 0_u32; x < patch_size; x++)
for (auto y = 0_u32; y < patch_size; y++) {
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;

View File

@ -11,7 +11,7 @@
#include <Scene/Camera.hpp>
UI::UI(Renderer* ren) : info{ .flycam = ren->flycam, .time = ren->time, .cam = ren->cam, }, dev(ren->dev) {
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) {
IMGUI_CHECKVERSION();
ImGui::CreateContext();
@ -92,11 +92,8 @@ void UI::newFrame() {
ImGui::Text("FPS: %f", info.fps);
ImGui::Text("Time: %f", info.time);
ImGui::Checkbox("Fly Camera", &info.flycam);
ImGui::SliderAngle("Theta", &info.cam.theta, 0.01, 179.9);
ImGui::SliderAngle("Phi", &info.cam.phi, 0.0, 360.0, "%.0f def");
ImGui::SliderFloat("cam.x", &info.cam.pos.x, -1e2, 1e2);
ImGui::SliderFloat("cam.y", &info.cam.pos.y, -1e2, 1e2);
ImGui::SliderFloat("cam.z", &info.cam.pos.z, -1e2, 1e2);
ImGui::SliderFloat("Tessellation Factor: %f", &info.tess_factor, 0.0, 20.0);
ImGui::SliderFloat("Edge Size: %f", &info.tess_edge_size, 0.0, 40.0);
ImGui::End();
}

View File

@ -15,6 +15,8 @@ struct UI {
float& time;
/* camera stuff */
Camera& cam;
float& tess_factor;
float& tess_edge_size;
} info;
vk::Device dev;

View File

@ -0,0 +1,18 @@
#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 mvp;
float time;
vec3 cam_pos;
};
layout (set = 0, binding = 1) uniform sampler2D tex;
void main() {
FragColor = vec4(1.0);
}

Binary file not shown.

View File

@ -0,0 +1,60 @@
#version 450 core
layout (set = 0, binding = 0) uniform Matrices {
mat4 mvp;
float time;
vec3 cam_pos;
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 mid = (p0+p1) / 2.0;
float r = distance(p0, p1) / 2.0;
vec4 v0 = mvp * mid;
/* projevt into clip spaace */
vec4 clip0 = mvp * (v0 - vec4(r, 0.0, 0.0, 0.0));
vec4 clip1 = mvp * (v0 + vec4(r, 0.0, 0.0, 0.0));
clip0 /= clip0.w;
clip1 /= clip1.w;
/* convert to viewport coords */
clip0.xy * viewport;
clip1.xy * viewport;
return clamp(distance(clip0, clip0) / tess_edge_size * tess_factor, 1.0, 64.0);
}
void main() {
if(gl_InvocationID == 0) {
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);
}
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.

View File

@ -0,0 +1,42 @@
#version 450 core
layout (set = 0, binding = 0) uniform Matrices {
mat4 mvp;
float time;
vec3 cam_pos;
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);
_pos = mix(pos1, pos2, gl_TessCoord.y).xyz;
gl_Position = mvp * mix(pos1, pos2, gl_TessCoord.y);
}

Binary file not shown.

View File

@ -0,0 +1,20 @@
#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;
gl_Position = vec4(pos, 1.0);
texCoord = aTexCoord;
norm = aNorm;
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

View File

@ -28,7 +28,7 @@ int main(int argc, char* argv[]) {
while (in->queue.size()) {
/* take event from front of queue, then process it */
const auto& event = in->queue.front();
const auto event = in->queue.front();
in->queue.pop();
switch (event.tag) {
case InputEvent::Tag::eRESIZE: