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
bin
314 changes: 30 additions & 284 deletions README.md

Large diffs are not rendered by default.

Binary file added comparison.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 culled.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 showcase.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 showcase2.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2,071 changes: 1,105 additions & 966 deletions src/Renderer.cpp

Large diffs are not rendered by default.

129 changes: 67 additions & 62 deletions src/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,76 +7,81 @@

class Renderer {
public:
Renderer() = delete;
Renderer(Device* device, SwapChain* swapChain, Scene* scene, Camera* camera);
~Renderer();
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();

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

VkCommandPool graphicsCommandPool;
VkCommandPool computeCommandPool;

VkRenderPass renderPass;

VkDescriptorSetLayout cameraDescriptorSetLayout;
VkDescriptorSetLayout modelDescriptorSetLayout;
VkDescriptorSetLayout timeDescriptorSetLayout;

VkDescriptorPool descriptorPool;

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

VkPipelineLayout graphicsPipelineLayout;
VkPipelineLayout grassPipelineLayout;
VkPipelineLayout computePipelineLayout;

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;
};
Device* device;
VkDevice logicalDevice;
SwapChain* swapChain;
Scene* scene;
Camera* camera;

VkCommandPool graphicsCommandPool;
VkCommandPool computeCommandPool;

VkRenderPass renderPass;

VkDescriptorSetLayout cameraDescriptorSetLayout;
VkDescriptorSetLayout modelDescriptorSetLayout;
VkDescriptorSetLayout timeDescriptorSetLayout;

VkDescriptorSetLayout computeDescriptorSetLayout;//Added

VkDescriptorPool descriptorPool;

VkDescriptorSet cameraDescriptorSet;
std::vector<VkDescriptorSet> modelDescriptorSets;
std::vector<VkDescriptorSet> computeDescriptorSetContainer;
std::vector<VkDescriptorSet> grassDescriptorSetContainer;
VkDescriptorSet timeDescriptorSet;

VkPipelineLayout graphicsPipelineLayout;
VkPipelineLayout grassPipelineLayout;
VkPipelineLayout computePipelineLayout;

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;
};
5 changes: 5 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Camera.h"
#include "Scene.h"
#include "Image.h"
#include <iostream>

Device* device;
SwapChain* swapChain;
Expand Down Expand Up @@ -143,11 +144,15 @@ int main() {
glfwSetMouseButtonCallback(GetGLFWWindow(), mouseDownCallback);
glfwSetCursorPosCallback(GetGLFWWindow(), mouseMoveCallback);

double timeStarted = glfwGetTime();
while (!ShouldQuit()) {
glfwPollEvents();
scene->UpdateTime();
renderer->Frame();
}
double timeEnded = glfwGetTime();
std::cout << static_cast<double>(renderer->frames) / (timeEnded - timeStarted) << std::endl;
system("pause");

vkDeviceWaitIdle(device->GetVkDevice());

Expand Down
104 changes: 90 additions & 14 deletions src/shaders/compute.comp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
#extension GL_ARB_separate_shader_objects : enable

#define WORKGROUP_SIZE 32
#define CULL_N_BLADES 10
#define D_MAX 10.0
#define TOLERANCE 1.0

layout(local_size_x = WORKGROUP_SIZE, local_size_y = 1, local_size_z = 1) in;

layout(set = 0, binding = 0) uniform CameraBufferObject {
Expand All @@ -12,45 +16,117 @@ layout(set = 0, binding = 0) uniform CameraBufferObject {
layout(set = 1, binding = 0) uniform Time {
float deltaTime;
float totalTime;
};
}time;

struct Blade {
vec4 v0;
vec4 v1;
vec4 v2;
vec4 up;
};
vec4 v0; //Orientation: the orientation of the grass blade's face
vec4 v1; //Height: the height of the grass blade
vec4 v2; //Width: the width of the grass blade's face
vec4 up; //Stiffness coefficient: the stiffness of our grass blade, which will affect the force computations on our blade
};

// TODO: Add bindings to:
// 1. Store the input blades
// 2. Write out the culled blades
// 3. Write the total number of blades remaining

layout(set = 2, binding = 0) buffer Blades
{
Blade blades[];
};

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

// 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 = 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);
}

float randWind(float n) {
return fract(sin(n) * 43758.5453123);
}

void main() {
// Reset the number of blades to 0
if (gl_GlobalInvocationID.x == 0) {
// numBlades.vertexCount = 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
uint bladeIndex = gl_GlobalInvocationID.x;

vec3 v0 = blades[bladeIndex].v0.xyz;
vec3 v1 = blades[bladeIndex].v1.xyz;
vec3 v2 = blades[bladeIndex].v2.xyz;
vec3 up = blades[bladeIndex].up.xyz;

float direction = blades[bladeIndex].v0.w;
float height = blades[bladeIndex].v1.w;
float width = blades[bladeIndex].v2.w;
float stiffness = blades[bladeIndex].up.w;

float cosTheta = cos(direction);
float sinTheta = sin(direction);

vec3 gravityDir = vec3(0.0f, -1.0f, 0.0f);
float gravityMag = 0.2f;
vec3 gE = normalize(gravityDir) * gravityMag;
vec3 left = normalize(vec3(cosTheta, 0.0, -sinTheta));
vec3 f = normalize(cross(left, up));
vec3 gF = 0.25f * length(gE) * f;
vec3 gravityForce = gE + gF;

vec3 Iv2 = vec3(v0 + height*up);
vec3 recoveryForce = vec3(Iv2 - v2) * stiffness;

vec3 wV0 = 0.2f * cos(time.totalTime) * vec3(randWind(v0.x), 0.0, randWind(v0.z));
float fd = (1 - abs(dot(normalize(wV0), normalize(v2 - v0))));
vec3 windForce = fd * wV0;

vec3 tv2 = (gravityForce + recoveryForce + windForce) * time.deltaTime;
v2 = v1 + tv2;

float L0 = length(v2 - v0);
float L1 = length(v2 - v1) + length(v1 - v0);
float degree = 2.0f;
float L = (2.0f * L0 + L1) / (degree + 1.0f);
float r = height / L;

vec3 v1Corr = v0 + r * (v1 - v0);
vec3 v2Corr = v1Corr + r * (v2 - v1);
blades[bladeIndex].v1.x = v1Corr.x;
blades[bladeIndex].v1.y = v1Corr.y;
blades[bladeIndex].v1.z = v1Corr.z;

blades[bladeIndex].v1.x = v2Corr.x;
blades[bladeIndex].v2.y = v2Corr.y;
blades[bladeIndex].v2.z = v2Corr.z;

// 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
}

vec3 front = normalize(cross(left, up));

vec3 frontCamSpace = vec3(camera.view * vec4(front, 0.0f));
vec3 zMinus = vec3(0.0f, 0.0f, -1.0f);
if (abs(dot(zMinus, frontCamSpace)) >= 0.1f)
/*if (true)*/
{
culledBlades[atomicAdd(numBlades.vertexCount, 1)] = blades[bladeIndex];
}
}
23 changes: 21 additions & 2 deletions src/shaders/grass.frag
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,30 @@ layout(set = 0, binding = 0) uniform CameraBufferObject {
} camera;

// TODO: Declare fragment shader inputs
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 nor;

layout(location = 0) out vec4 outColor;

void main() {
// TODO: Compute fragment color
const vec3 lightPosition = vec3(1.0f, 3.0f, -1.0f);
vec3 lightDirection = normalize(pos - lightPosition);

outColor = vec4(1.0);
}
vec3 ambientColor = vec3(1.0f, 1.0f, 1.0f);
vec3 specColor = vec3(0.01f, 0.52f, 0.05f);
vec3 grassColor = vec3(0.01f, 0.325f, 0.01f);

vec3 L = -lightDirection;
vec3 E = normalize(-pos);
vec3 N = normalize(nor);
vec3 R = normalize(-reflect(L, N));
float specIntensity = pow(max(dot(R, E), 0.0f), 32.0f);

float ambientIntensity = 0.15f;
float diffuseIntensity = clamp(dot(nor, lightDirection), 0.3f, 1.0f);

vec3 accumulatedColor = ambientIntensity * ambientColor + diffuseIntensity * grassColor + specIntensity * specColor;
accumulatedColor = clamp(accumulatedColor, 0.0f, 1.0f);
outColor = vec4(accumulatedColor, 1.0f);
}
31 changes: 23 additions & 8 deletions src/shaders/grass.tesc
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,33 @@ layout(set = 0, binding = 0) uniform CameraBufferObject {
} camera;

// TODO: Declare tessellation control shader inputs and outputs
layout(location = 0) in vec4 tescV1[];
layout(location = 1) in vec4 tescV2[];
layout(location = 2) in vec4 tescUp[];
layout(location = 3) in vec3 tescTangent[];

layout(location = 0) out vec4 teseV1[];
layout(location = 1) out vec4 teseV2[];
layout(location = 2) out vec4 teseUp[];
layout(location = 3) out vec3 teseTangent[];


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: Write any shader output
teseV1[gl_InvocationID] = tescV1[gl_InvocationID];
teseV2[gl_InvocationID] = tescV2[gl_InvocationID];
teseUp[gl_InvocationID] = tescUp[gl_InvocationID];
teseTangent[gl_InvocationID] = tescTangent[gl_InvocationID];

// TODO: Set level of tesselation
// gl_TessLevelInner[0] = ???
// gl_TessLevelInner[1] = ???
// gl_TessLevelOuter[0] = ???
// gl_TessLevelOuter[1] = ???
// gl_TessLevelOuter[2] = ???
// gl_TessLevelOuter[3] = ???
}
gl_TessLevelInner[0] = 3.0f;
gl_TessLevelInner[1] = 3.0f;

gl_TessLevelOuter[0] = 3.0f;
gl_TessLevelOuter[1] = 3.0f;
gl_TessLevelOuter[2] = 3.0f;
gl_TessLevelOuter[3] = 3.0f;
}
Loading