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: Jason Xie #20

Open
wants to merge 5 commits into
base: main
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin
build
28 changes: 28 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Process",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/bin/vulkan_grass_rendering",
"processId": "${command:pickProcess}",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
],
}
]
}
17 changes: 17 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"ros.distro": "humble",
"files.associations": {
"*.sdf": "xml",
"*.world": "xml",
"*.gltf": "json",
"array": "cpp",
"string": "cpp",
"string_view": "cpp",
"ranges": "cpp",
"*.ipp": "cpp",
"bitset": "cpp",
"initializer_list": "cpp",
"utility": "cpp",
"valarray": "cpp"
}
}
128 changes: 121 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,126 @@
Vulkan Grass Rendering
Touching Grass in Vulkan
==================================

**University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 5**
![grass](img/submission/grass.gif)
Jason Xie, October 2023

* (TODO) YOUR NAME HERE
* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab)
## About

### (TODO: Your README)
A grass simulation in Vulkan.

*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.
This project implements the paper [Responsive Real-Time Grass Rendering for General 3D Scenes](https://www.cg.tuwien.ac.at/research/publications/2017/JAHRMANN-2017-RRTG/JAHRMANN-2017-RRTG-draft.pdf), including Bezier curve grass blades, physical models for grass motion, and culling.

## Features

### 🌿 Bezier Curve Grass Blades

Grass is represented as Bezier curves, where $v_0, v_1, v_2, v_3$ are the control points. In addition to these control points, the direction, height, width, and the "up" vector are also stored, resulting in four vec4s per grass blade.

![bezier](img/blade_model.jpg)

To draw the grass, vertices from the initial quad is refined through the tessellation shader. First, two separate Bezier curves are generated for each side of the grass blade. Then, the vertex position is determined by interpolating between the two curves.

![shape](img/shape.png)

### 🌿 Physical Models

![physics](img/physics.png)

Grass motion is modeled as displacements of the grass tip $v_2$ due to a comination of forces.

**🌎️ Gravity**

Gravity is simulated as a combination of *environmental gravity* and *frontal gravity*:

$g = g_e + g_f$

$g_f = \frac{1}{4} ||g_e|| f$

**🌬️ Wind**

The deflection of grass due to wind is modeled as a function of wind magnitude and grass alignment with the wind direction:

$w = w_i(v_0) \theta(w_i(v_o), h)$

Wind vector is modeled as a function of position and time, and it is layered using progressively smaller sinusoids.

![wind](img/submission/grass1.gif)

**πŸͺƒ Recovery**

Elastic forces that help the grass bounce back is modeled using Hooke's law:

$r = (I_{v_2} - v_2) s$

### 🌿 Culling

![culling](img/submission/grass2.gif)

To allow for fast simulations, grass blades are culled through a combination of orientation culling, frustum culling and distance culling.

**Orientation Culling**

Grass blades that are not facing the camera are culled. This is done by checking the angle between the camera direction and the grass blade direction.

**Frustum Culling**

Grass blades that are outside of the view frustum are culled. Culling is performed by checking the intersection between the grass blade control points and the view frustum.

**Distance Culling**

Grass blades that are too far away from the camera are culled.

## Performance Analysis

Let's analyze the impace of culling and number of grass blades on the performance of the simulation.

**All Culling**

| Number of Grass Blades | FPS |
| ---------------------- | --- |
| 2^22 | 34 |
| 2^20 | 90 |
| 2^18 | 250 |

**No Culling**

| Number of Grass Blades | FPS |
| ---------------------- | --- |
| 2^22 | 9 |
| 2^20 | 32 |
| 2^18 | 100 |

**Orientation Culling**

| Number of Grass Blades | FPS |
| ---------------------- | --- |
| 2^22 | 9 |
| 2^20 | 30 |
| 2^18 | 80 |

**Frustum Culling**

| Number of Grass Blades | FPS |
| ---------------------- | --- |
| 2^22 | 35 |
| 2^20 | 92 |
| 2^18 | 250 |

**Distance Culling**

| Number of Grass Blades | FPS |
| ---------------------- | --- |
| 2^22 | 8 |
| 2^20 | 32 |
| 2^18 | 78 |

![culling](img/submission/perf_cull.png)

From the analysis, it appears that frustrum culling has the most impact on FPS. This is likely because in a large scene, the vast majority of blades will be hidden from view.

## Build & Run

```bash
bash build.sh debug
cd bin && ./vulkan_grass_rendering
```
Binary file removed bin/Release/vulkan_grass_rendering.exe
Binary file not shown.
28 changes: 28 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

# Create build directory if it doesn't exist
mkdir -p build

# Change into the build directory
cd build

# Default build type to Release
build_type="Release"

# Check for argument "debug" to change build type
if [ "$1" == "debug" ]; then
echo "Building in debug mode"
build_type="Debug"
fi

# Run cmake with the specified build type
cmake -DCMAKE_BUILD_TYPE=$build_type ..

# Build the project with dbg if debug was specified
if [ "$1" == "debug" ]; then
make dbg=1
else
make
fi

# recursively move bin dir/ into build/
Binary file added images/grass.jpg
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/grass1.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/grass3.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/physics.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/shape.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/submission/grass.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/submission/grass1.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/submission/grass2.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/submission/grass3.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/submission/perf_cull.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion src/Blades.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ Blades::Blades(Device* device, VkCommandPool commandPool, float planeDim) : Mode
Blade currentBlade = Blade();

glm::vec3 bladeUp(0.0f, 1.0f, 0.0f);
// perturb up vector
bladeUp.x += (generateRandomFloat() - 0.5f) * 0.2f;
bladeUp.z += (generateRandomFloat() - 0.5f) * 0.2f;

// Generate positions and direction (v0)
float x = (generateRandomFloat() - 0.5f) * planeDim;
Expand Down Expand Up @@ -45,7 +48,7 @@ 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_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_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);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Blades.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <array>
#include "Model.h"

constexpr static unsigned int NUM_BLADES = 1 << 13;
constexpr static unsigned int NUM_BLADES = 1 << 18;
constexpr static float MIN_HEIGHT = 1.3f;
constexpr static float MAX_HEIGHT = 2.5f;
constexpr static float MIN_WIDTH = 0.1f;
Expand Down
1 change: 1 addition & 0 deletions src/BufferUtils.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "BufferUtils.h"
#include "Instance.h"
#include <cstring>

void BufferUtils::CreateBuffer(Device* device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {
// Create buffer
Expand Down
23 changes: 20 additions & 3 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ file(GLOB IMAGES

foreach(IMAGE ${IMAGES})
get_filename_component(fname ${IMAGE} NAME)
configure_file(${IMAGE} ${CMAKE_CURRENT_BINARY_DIR}/images/${fname} COPYONLY)
configure_file(${IMAGE} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/images/${fname} COPYONLY)
endforeach()

file(GLOB_RECURSE SHADER_SOURCES
Expand All @@ -30,8 +30,10 @@ else(WIN32)
target_link_libraries(vulkan_grass_rendering ${CMAKE_THREAD_LIBS_INIT})
endif(WIN32)

set(COMPILED_SHADERS "")

foreach(SHADER_SOURCE ${SHADER_SOURCES})
set(SHADER_DIR ${CMAKE_CURRENT_BINARY_DIR}/shaders)
set(SHADER_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/shaders)

if(WIN32)
get_filename_component(fname ${SHADER_SOURCE} NAME)
Expand All @@ -42,11 +44,26 @@ 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)
set(SHADER_OUTPUT ${SHADER_DIR}/${fname}.spv)

add_custom_command(
OUTPUT ${SHADER_OUTPUT}
COMMAND ${CMAKE_COMMAND} -E make_directory ${SHADER_DIR}
COMMAND glslc ${SHADER_SOURCE} -o ${SHADER_OUTPUT}
DEPENDS ${SHADER_SOURCE}
COMMENT "Compiling ${fname} to SPIR-V"
)

list(APPEND COMPILED_SHADERS ${SHADER_OUTPUT})
endif(WIN32)

# TODO: Build shaders on not windows
endforeach()

add_custom_target(compile_shaders DEPENDS ${COMPILED_SHADERS})
add_dependencies(vulkan_grass_rendering compile_shaders)

target_link_libraries(vulkan_grass_rendering ${ASSIMP_LIBRARIES} Vulkan::Vulkan glfw)
target_include_directories(vulkan_grass_rendering PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
Expand Down
1 change: 1 addition & 0 deletions src/Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "QueueFlags.h"
#include "SwapChain.h"

class Instance;
class SwapChain;
class Device {
friend class Instance;
Expand Down
Loading