Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
build
*.swp
259 changes: 25 additions & 234 deletions README.md

Large diffs are not rendered by default.

Binary file added img/culling.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/distance_culling.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/final_render.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/number_of_blades.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/BufferUtils.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include "BufferUtils.h"
#include "Instance.h"
#include <cstring>

using std::memcpy;

void BufferUtils::CreateBuffer(Device* device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {
// Create buffer
Expand Down
9 changes: 9 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ foreach(SHADER_SOURCE ${SHADER_SOURCES})
)
ExternalTarget("Shaders" ${fname}.spv)
add_dependencies(vulkan_grass_rendering ${fname}.spv)
else(WIN32)
get_filename_component(fname ${SHADER_SOURCE} NAME)
add_custom_target(${fname}.spv
COMMAND ${CMAKE_COMMAND} -E make_directory ${SHADER_DIR} &&
$ENV{VULKAN_SDK}/bin/glslangValidator -V ${SHADER_SOURCE} -o ${SHADER_DIR}/${fname}.spv
SOURCES ${SHADER_SOURCE}
)
ExternalTarget("Shaders" ${fname}.spv)
add_dependencies(vulkan_grass_rendering ${fname}.spv)
endif(WIN32)

# TODO: Build shaders on not windows
Expand Down
1 change: 1 addition & 0 deletions src/Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "QueueFlags.h"
#include "SwapChain.h"

class Instance;
class SwapChain;
class Device {
friend class Instance;
Expand Down
2,235 changes: 1,261 additions & 974 deletions src/Renderer.cpp

Large diffs are not rendered by default.

114 changes: 59 additions & 55 deletions src/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,77 +6,81 @@
#include "Camera.h"

class Renderer {
public:
Renderer() = delete;
Renderer(Device* device, SwapChain* swapChain, Scene* scene, Camera* camera);
~Renderer();
public:
Renderer() = delete;
Renderer(Device* device, SwapChain* swapChain, Scene* scene, Camera* camera);
~Renderer();

void CreateCommandPools();
void CreateCommandPools();

void CreateRenderPass();
void CreateRenderPass();

void CreateCameraDescriptorSetLayout();
void CreateModelDescriptorSetLayout();
void CreateTimeDescriptorSetLayout();
void CreateComputeDescriptorSetLayout();
void CreateCameraDescriptorSetLayout();
void CreateModelDescriptorSetLayout();
void CreateTimeDescriptorSetLayout();
void CreateComputeDescriptorSetLayout();

void CreateDescriptorPool();
void CreateDescriptorPool();

void CreateCameraDescriptorSet();
void CreateModelDescriptorSets();
void CreateGrassDescriptorSets();
void CreateTimeDescriptorSet();
void CreateComputeDescriptorSets();
void CreateCameraDescriptorSet();
void CreateModelDescriptorSets();
void CreateGrassDescriptorSets();
void CreateTimeDescriptorSet();
void CreateComputeDescriptorSets();

void CreateGraphicsPipeline();
void CreateGrassPipeline();
void CreateComputePipeline();
void CreateGraphicsPipeline();
void CreateGrassPipeline();
void CreateComputePipeline();

void CreateFrameResources();
void DestroyFrameResources();
void RecreateFrameResources();
void CreateFrameResources();
void DestroyFrameResources();
void RecreateFrameResources();

void RecordCommandBuffers();
void RecordComputeCommandBuffer();
void RecordCommandBuffers();
void RecordComputeCommandBuffer();

void Frame();
void Frame();

private:
Device* device;
VkDevice logicalDevice;
SwapChain* swapChain;
Scene* scene;
Camera* camera;
private:
Device* device;
VkDevice logicalDevice;
SwapChain* swapChain;
Scene* scene;
Camera* camera;

VkCommandPool graphicsCommandPool;
VkCommandPool computeCommandPool;
VkCommandPool graphicsCommandPool;
VkCommandPool computeCommandPool;

VkRenderPass renderPass;
VkRenderPass renderPass;

VkDescriptorSetLayout cameraDescriptorSetLayout;
VkDescriptorSetLayout modelDescriptorSetLayout;
VkDescriptorSetLayout timeDescriptorSetLayout;

VkDescriptorPool descriptorPool;
VkDescriptorSetLayout cameraDescriptorSetLayout;
VkDescriptorSetLayout modelDescriptorSetLayout;
VkDescriptorSetLayout timeDescriptorSetLayout;
VkDescriptorSetLayout compute_descriptor_set_layout_;

VkDescriptorSet cameraDescriptorSet;
std::vector<VkDescriptorSet> modelDescriptorSets;
VkDescriptorSet timeDescriptorSet;
VkDescriptorPool descriptorPool;

VkPipelineLayout graphicsPipelineLayout;
VkPipelineLayout grassPipelineLayout;
VkPipelineLayout computePipelineLayout;
VkDescriptorSet cameraDescriptorSet;
std::vector<VkDescriptorSet> modelDescriptorSets;
VkDescriptorSet timeDescriptorSet;
std::vector<VkDescriptorSet> grassDescriptorSets;
std::vector<VkDescriptorSet> compute_descriptor_sets_;

VkPipeline graphicsPipeline;
VkPipeline grassPipeline;
VkPipeline computePipeline;
VkPipelineLayout graphicsPipelineLayout;
VkPipelineLayout grassPipelineLayout;
VkPipelineLayout computePipelineLayout;

std::vector<VkImageView> imageViews;
VkImage depthImage;
VkDeviceMemory depthImageMemory;
VkImageView depthImageView;
std::vector<VkFramebuffer> framebuffers;
VkPipeline graphicsPipeline;
VkPipeline grassPipeline;
VkPipeline computePipeline;

std::vector<VkImageView> imageViews;
VkImage depthImage;
VkDeviceMemory depthImageMemory;
VkImageView depthImageView;
std::vector<VkFramebuffer> framebuffers;

std::vector<VkCommandBuffer> commandBuffers;
VkCommandBuffer computeCommandBuffer;

std::vector<VkCommandBuffer> commandBuffers;
VkCommandBuffer computeCommandBuffer;
};
1 change: 1 addition & 0 deletions src/ShaderModule.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <fstream>
#include "ShaderModule.h"
#include <iostream>

namespace {
std::vector<char> readFile(const std::string& filename) {
Expand Down
1 change: 1 addition & 0 deletions src/SwapChain.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <vector>
#include <limits>
#include "SwapChain.h"
#include "Instance.h"
#include "Device.h"
Expand Down
3 changes: 3 additions & 0 deletions src/Window.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include <stdio.h>
#include <cstdlib>
#include "Window.h"

#define EXIT_FAILURE 1

namespace {
GLFWwindow* window = nullptr;
}
Expand Down
124 changes: 106 additions & 18 deletions src/shaders/compute.comp
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,116 @@ struct Blade {
// The project is using vkCmdDrawIndirect to use a buffer as the arguments for a draw call
// This is sort of an advanced feature so we've showed you what this buffer should look like
//
// layout(set = ???, binding = ???) buffer NumBlades {
// uint vertexCount; // Write the number of blades remaining here
// uint instanceCount; // = 1
// uint firstVertex; // = 0
// uint firstInstance; // = 0
// } numBlades;
layout(set = 2, binding = 0) buffer InputBlades {
Blade blades[];
} inputBlades;

layout(set = 2, binding = 1) buffer CulledBlades {
Blade blades[];
} culledBlades;

layout(set = 2, binding = 2) buffer NumBlades {
uint vertexCount; // Write the number of blades remaining here
uint instanceCount; // = 1
uint firstVertex; // = 0
uint firstInstance; // = 0
} numBlades;

bool inBounds(float value, float bounds) {
return (value >= -bounds) && (value <= bounds);
}

void main() {
// Reset the number of blades to 0
if (gl_GlobalInvocationID.x == 0) {
// numBlades.vertexCount = 0;
}
barrier(); // Wait till all threads reach this point

// TODO: Apply forces on every blade and update the vertices in the buffer

// TODO: Cull blades that are too far away or not in the camera frustum and write them
// to the culled blades buffer
// Note: to do this, you will need to use an atomic operation to read and update numBlades.vertexCount
// You want to write the visible blades to the buffer without write conflicts between threads
uint index = gl_GlobalInvocationID.x;
// Reset the number of blades to 0
if (index == 0) {
numBlades.vertexCount = 0;
}
barrier(); // Wait till all threads reach this point

// TODO: Apply forces on every blade and update the vertices in the buffer
Blade blade = inputBlades.blades[index];
vec3 v0 = blade.v0.xyz;
vec3 v1 = blade.v1.xyz;
vec3 v2 = blade.v2.xyz;
vec3 up = blade.up.xyz;
float height = blade.v1.w;
float orientation = blade.v0.w;
float stiff = blade.up.w;

vec3 f = vec3(cos(orientation), 0, sin(orientation));

// gravity
vec3 gE = vec3(0, -1, 0);
vec3 gF = 0.25 * 1 * f;
vec3 g = gF + gE;

// restoration
vec3 iv2 = v0 + height * up;
vec3 r = (iv2 - v2) * stiff;
//r = vec3(0);

// wind
vec3 w = vec3(sin(totalTime/5 + v0.x + v0.z/2.0)+1, 0, 0);
//w = vec3(0);

vec3 tv2 = (g + r + w) * deltaTime;
vec3 n_v2 = blade.v2.xyz + tv2;

// validation

n_v2 = n_v2 - up * (min(dot(up, n_v2 - v0), 0));

float lProj = length(n_v2 - v0 - up * dot((n_v2 - v0), up));

blade.v1.xyz =
v0 + height * up * max(1 - lProj / height, 0.05 * max(lProj / height, 1));
blade.v2.xyz = n_v2;

inputBlades.blades[index] = blade;

// TODO: Cull blades that are too far away or not in the camera
// frustum and write them
// to the culled blades buffer
// Note: to do this, you will need to use an atomic operation to
// read and update numBlades.vertexCount
// You want to write the visible blades to the buffer without write
// conflicts between threads

bool culled = false;

mat4 inv_view = inverse(camera.view);
vec3 dir_c = vec3(inv_view * vec4(0,0,1,0));
if (abs(dot(dir_c, f)) > 0.9) {
culled = true;
}

vec3 m = 0.25*v0 + 0.5*blade.v1.xyz + 0.25*n_v2;
vec4 view_p = camera.proj * camera.view * vec4(v0, 1);
vec4 view_m = camera.proj * camera.view * vec4(m, 1);
vec4 view_t = camera.proj * camera.view * vec4(n_v2, 1);
view_p /= view_p.w;
view_m /= view_m.w;
view_t /= view_t.w;

if ((!inBounds(view_p.x, 1) || !inBounds(view_p.y, 1) ||
!inBounds(view_p.z, 1)) &&
(!inBounds(view_m.x, 1) || !inBounds(view_m.y, 1) ||
!inBounds(view_m.z, 1)) &&
(!inBounds(view_t.x, 1) || !inBounds(view_t.y, 1) ||
!inBounds(view_t.z, 1))) {
culled = true;
}

float max_dist = 30;
float dist = -(camera.view * vec4(v0, 1.0)).z;
if (index % int(max_dist) < dist) {
culled = true;
}

if (!culled) {
culledBlades.blades[atomicAdd(numBlades.vertexCount, 1)] = blade;
}
//numBlades.vertexCount = 10;
;
}
11 changes: 10 additions & 1 deletion src/shaders/grass.frag
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,19 @@ layout(set = 0, binding = 0) uniform CameraBufferObject {

// TODO: Declare fragment shader inputs

layout(location = 0) in vec3 nor;
layout(location = 1) in vec3 world_pos;

layout(location = 0) out vec4 outColor;

void main() {
// TODO: Compute fragment color
vec3 col = vec3(0.15, 0.8, 0.1);
vec3 light = vec3(0.0, 15.0, 5.0);

vec3 L = normalize(light - world_pos);

outColor = vec4(1.0);
//outColor = vec4(1.0);
outColor = vec4(col * clamp(dot(nor.xyz, L), 0.0, 1.0) + col * 0.15, 0);
//outColor = vec4(nor,1);
}
39 changes: 27 additions & 12 deletions src/shaders/grass.tesc
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,32 @@ layout(set = 0, binding = 0) uniform CameraBufferObject {

// TODO: Declare tessellation control shader inputs and outputs

layout (location = 0) in vec4[] v_in0;
layout (location = 1) in vec4[] v_in1;
layout (location = 2) in vec4[] v_in2;
layout (location = 3) in vec4[] v_in3;

layout (location = 0) out vec4[] v0;
layout (location = 1) out vec4[] v1;
layout (location = 2) out vec4[] v2;
layout (location = 3) out vec4[] v3;

void main() {
// Don't move the origin location of the patch
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;

// TODO: Write any shader outputs

// TODO: Set level of tesselation
// gl_TessLevelInner[0] = ???
// gl_TessLevelInner[1] = ???
// gl_TessLevelOuter[0] = ???
// gl_TessLevelOuter[1] = ???
// gl_TessLevelOuter[2] = ???
// gl_TessLevelOuter[3] = ???
// Don't move the origin location of the patch
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;

// TODO: Write any shader outputs
v0[gl_InvocationID] = v_in0[gl_InvocationID];
v1[gl_InvocationID] = v_in1[gl_InvocationID];
v2[gl_InvocationID] = v_in2[gl_InvocationID];
v3[gl_InvocationID] = v_in3[gl_InvocationID];


// TODO: Set level of tesselation
gl_TessLevelInner[0] = 2;
gl_TessLevelInner[1] = 6;
gl_TessLevelOuter[0] = 2;
gl_TessLevelOuter[1] = 2;
gl_TessLevelOuter[2] = 2;
gl_TessLevelOuter[3] = 2;
}
Loading