Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project 5: RICHARD CHEN #9

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
bin/*
build/*
bin/Release/vulkan_grass_rendering.exe
bin/*
*.exe
59 changes: 54 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,59 @@ Vulkan Grass Rendering

**University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 5**

* (TODO) YOUR NAME HERE
* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab)
* Richard Chen
* Tested on: Windows 11, i7-10875H @ 2.3GHz 16GB, RTX 2060 MAX-Q 6GB (PC)

### (TODO: Your README)
![](img/vulkan_grass_gif.gif)

*DO NOT* leave the README to the last minute! It is a crucial part of the
project, and we will not be able to grade you without a good README.
## Overview

Unlike the ubiquitous OpenGL, Vulkan is a low level graphics API that gives much
more control to the programmer (at the cost of being incredibly verbose).
This comes with the added benefit of having a much higher performance ceiling
and low level graphics APIs like Vulkan, Metal, and DirectX 12 being used by
game engines and where performance is needed.

In this project, we implemented a grass simulation based on "Responsive
Real-Time Grass Rendering for General 3D Scenes" by Jahrmann and Wimmer in
Vulkan. We used compute shaders to do physics calculations like wind, gravity,
and restoring force. Additionally, tessellation shaders were added to the usual
graphics pipeline of vertex and fragment shaders, where fixed function dedicated
hardware allows for fast and efficient tessellation of scenes.

## Features

### Grass
The blades of grass were modelled as Bezier curves. Each blade had v0, v1, and v2
as the control points and an up vector, and orientation, height, width, and
stiffness as scalar parameters. All of the parameters fit nicely into 4 vec4s.
![](img/blade_model.jpg)

### Physics
As an approximation, the forces of gravity, wind, and a restoring force were
scaled by the time step and applied to the tip of the grass blade. Then,
corrections were added to
ensure the resulting position was valid,
calculate v1 from v2,
and maintain that grass blade lengths were invariant.
![](img/thick_grass.png)

### Optimizations

* Orientation Culling: Grass blades can be approximated as a 2D plane so they
are not rendered when viewed edge-on

* Distance Culling: When farther away, less grass is rendered until none are
rendered at all

* View Frustrum Culling: Blades that the outside the camera's field of view are
not rendered as there is no point to doing computations on objects that will
not be seen

### Other
* Lambertian Shading, where the color intensity is scaled by how directly the
surface faces the camera

Lambert | Flat
--------|------
![](img/lambert.png) | ![](img/flat.png)
Binary file modified bin/Release/vulkan_grass_rendering.exe
Binary file not shown.
Binary file added img/flat.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/grass_butts.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/lambert.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/thick_grass.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/vulkan_grass_gif.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 15 additions & 8 deletions src/Blades.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@
#include "Blades.h"
#include "BufferUtils.h"

float generateRandomFloat() {
float generateRandomFloat()
{
return rand() / (float)RAND_MAX;
}

Blades::Blades(Device* device, VkCommandPool commandPool, float planeDim) : Model(device, commandPool, {}, {}) {
Blades::Blades(Device *device, VkCommandPool commandPool, float planeDim) : Model(device, commandPool, {}, {})
{
std::vector<Blade> blades;
blades.reserve(NUM_BLADES);

for (int i = 0; i < NUM_BLADES; i++) {
for (int i = 0; i < NUM_BLADES; i++)
{
Blade currentBlade = Blade();

glm::vec3 bladeUp(0.0f, 1.0f, 0.0f);
Expand Down Expand Up @@ -45,23 +48,27 @@ Blades::Blades(Device* device, VkCommandPool commandPool, float planeDim) : Mode
indirectDraw.firstInstance = 0;

BufferUtils::CreateBufferFromData(device, commandPool, blades.data(), NUM_BLADES * sizeof(Blade), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, bladesBuffer, bladesBufferMemory);
BufferUtils::CreateBuffer(device, NUM_BLADES * sizeof(Blade), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, culledBladesBuffer, culledBladesBufferMemory);
BufferUtils::CreateBuffer(device, NUM_BLADES * sizeof(Blade), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, culledBladesBuffer, culledBladesBufferMemory);
BufferUtils::CreateBufferFromData(device, commandPool, &indirectDraw, sizeof(BladeDrawIndirect), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, numBladesBuffer, numBladesBufferMemory);
}

VkBuffer Blades::GetBladesBuffer() const {
VkBuffer Blades::GetBladesBuffer() const
{
return bladesBuffer;
}

VkBuffer Blades::GetCulledBladesBuffer() const {
VkBuffer Blades::GetCulledBladesBuffer() const
{
return culledBladesBuffer;
}

VkBuffer Blades::GetNumBladesBuffer() const {
VkBuffer Blades::GetNumBladesBuffer() const
{
return numBladesBuffer;
}

Blades::~Blades() {
Blades::~Blades()
{
vkDestroyBuffer(device->GetVkDevice(), bladesBuffer, nullptr);
vkFreeMemory(device->GetVkDevice(), bladesBufferMemory, nullptr);
vkDestroyBuffer(device->GetVkDevice(), culledBladesBuffer, nullptr);
Expand Down
19 changes: 12 additions & 7 deletions src/Blades.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@
#include <array>
#include "Model.h"

constexpr static unsigned int NUM_BLADES = 1 << 13;
constexpr static unsigned int NUM_BLADES = 1 << 14;
constexpr static float MIN_HEIGHT = 1.3f;
constexpr static float MAX_HEIGHT = 2.5f;
constexpr static float MIN_WIDTH = 0.1f;
constexpr static float MAX_WIDTH = 0.14f;
constexpr static float MIN_BEND = 7.0f;
constexpr static float MAX_BEND = 13.0f;

struct Blade {
struct Blade
{
// Position and direction
glm::vec4 v0;
// Bezier point and height
Expand All @@ -22,7 +23,8 @@ struct Blade {
// Up vector and stiffness coefficient
glm::vec4 up;

static VkVertexInputBindingDescription getBindingDescription() {
static VkVertexInputBindingDescription getBindingDescription()
{
VkVertexInputBindingDescription bindingDescription = {};
bindingDescription.binding = 0;
bindingDescription.stride = sizeof(Blade);
Expand All @@ -31,7 +33,8 @@ struct Blade {
return bindingDescription;
}

static std::array<VkVertexInputAttributeDescription, 4> getAttributeDescriptions() {
static std::array<VkVertexInputAttributeDescription, 4> getAttributeDescriptions()
{
std::array<VkVertexInputAttributeDescription, 4> attributeDescriptions = {};

// v0
Expand Down Expand Up @@ -62,14 +65,16 @@ struct Blade {
}
};

struct BladeDrawIndirect {
struct BladeDrawIndirect
{
uint32_t vertexCount;
uint32_t instanceCount;
uint32_t firstVertex;
uint32_t firstInstance;
};

class Blades : public Model {
class Blades : public Model
{
private:
VkBuffer bladesBuffer;
VkBuffer culledBladesBuffer;
Expand All @@ -80,7 +85,7 @@ class Blades : public Model {
VkDeviceMemory numBladesBufferMemory;

public:
Blades(Device* device, VkCommandPool commandPool, float planeDim);
Blades(Device *device, VkCommandPool commandPool, float planeDim);
VkBuffer GetBladesBuffer() const;
VkBuffer GetCulledBladesBuffer() const;
VkBuffer GetNumBladesBuffer() const;
Expand Down
Loading