Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
2f5ad8d
adjustments to cmake to compile
thumun Oct 19, 2025
2b2a87c
basic compute, need to finish and check renderer code
thumun Oct 21, 2025
b19beb2
fix runtime error
thumun Oct 21, 2025
62bbde1
need to fix another runtime thing
thumun Oct 21, 2025
6b2965e
need to fix more runtime issues
thumun Oct 23, 2025
89057c2
renderer done
thumun Oct 24, 2025
352db51
fix grass shaders
thumun Oct 24, 2025
a91bf64
need to fix normal perhaps
thumun Oct 25, 2025
f3bbd9b
need to add wind func, fixed diffuse issue
thumun Oct 26, 2025
b07835f
fixes
thumun Oct 26, 2025
790b631
fix
thumun Oct 26, 2025
a7b58f4
gen clean up in shaders
thumun Oct 26, 2025
7d7f765
oops wrong time
thumun Oct 26, 2025
35dde48
need to adjust wind to be less regular
thumun Oct 27, 2025
454825f
not sure about orientation culling and check view frustrum
thumun Oct 27, 2025
9ee1dc4
slightly more interesting wind
thumun Oct 27, 2025
30c9978
setting up gui (not done yet), more alterations to wind, fixes for re…
thumun Oct 28, 2025
cf8559f
Update README.md
thumun Oct 28, 2025
bf001e2
parameterizing threshold
thumun Oct 28, 2025
c5fea46
Merge branch 'main' of github.com:thumun/Project5-Vulkan-Grass-Rendering
thumun Oct 28, 2025
34fe123
Update README.md
thumun Oct 28, 2025
b7b6225
Update README.md
thumun Oct 28, 2025
e1c96b0
Update README.md
thumun Oct 29, 2025
aa3c6df
Update README.md
thumun Oct 30, 2025
e769044
adding fps && making lod logic better
thumun Oct 30, 2025
dd23db8
Merge branch 'main' of github.com:thumun/Project5-Vulkan-Grass-Rendering
thumun Oct 30, 2025
e01da6d
adding gifs
thumun Oct 30, 2025
0ccd0ad
fix & gif
thumun Oct 30, 2025
73fef12
Update README.md
thumun Oct 30, 2025
7ca279e
Update README.md
thumun Oct 30, 2025
791020a
charts
thumun Oct 30, 2025
5d60d9d
Merge branch 'main' of github.com:thumun/Project5-Vulkan-Grass-Rendering
thumun Oct 30, 2025
bb1049f
main img
thumun Oct 30, 2025
22ce885
Update README.md
thumun Oct 30, 2025
98a77cb
release data
thumun Oct 30, 2025
a83056b
Update README.md
thumun Oct 30, 2025
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: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.12)
cmake_minimum_required(VERSION 3.18)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")

project(cis565_project5_vulkan_grass_rendering)
Expand Down
119 changes: 114 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,119 @@ 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)
* Neha Thumu
* [LinkedIn](https://www.linkedin.com/in/neha-thumu/)
* Tested on: Windows 11 Pro, i9-13900H @ 2.60GHz 32GB, Nvidia GeForce RTX 4070

### (TODO: Your README)
![main](https://github.com/thumun/Project5-Vulkan-Grass-Rendering/blob/main/img/grassmain.gif?raw=true)

*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.
## Project Details

This project is based on the following 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) and was built using the Vulkan API. We use various forces to simulate the movement of the grass and employ culling methods along with tesselation to optimize the process.

### Rendering the Grass
![still](https://github.com/thumun/Project5-Vulkan-Grass-Rendering/blob/main/img/stillgrass.gif?raw=true)

The grass in this project is represented as bezier curves composed of three control points: v0, v1, and v2.
- v0: the position of the grass blade on the geometry (or ground)
- v1: a curve guide that is always above v0 (with respect to the grass blade's up vector)
- v2: a guide for simulating the forces as well as the tip of the blade

The blades also have the following properties:
- Up: the blade's up vector, which corresponds to the normal of the geometry that the grass blade resides on at v0
- Orientation: the orientation of the grass blade's face
- Height: the height of the grass blade
- Width: the width of the grass blade's face
- Stiffness coefficient: the stiffness of our grass blade, which will affect the force computations on our blade
![bladeDiagram](https://github.com/thumun/Project5-Vulkan-Grass-Rendering/blob/main/img/blade_model.jpg?raw=true)

We use the above data to construct the individual grass blades via De Casteljau's algorithm as well as simulate the movement of the blades.

### Simulating Forces
![forces](https://github.com/thumun/Project5-Vulkan-Grass-Rendering/blob/main/img/forces.gif?raw=true)

#### Recovery
The recovery force is a counterforce against the applied forces of gravity and wind. This logic follows Hooke's Law. We take the difference of the initial position of the grass blade and the current position and apply the stiffness coefficient to create this force:

<img width="187" height="45" alt="image" src="https://github.com/user-attachments/assets/81619755-047e-4fb4-a1ed-f13e7d57440a" />

#### Gravity
The gravitational force is a combination of environmental gravity annd front gravity. Environmental gravity is a global force that affects all the blades in the scene. In this case, it is a downwards pull of a constant value.

<img width="534" height="91" alt="image" src="https://github.com/user-attachments/assets/05b32bce-4407-48a5-bd7d-c68f1e1a8af4" />

On the other hand, front gravity is blade specific-which means it uses the front direction of the blade in combination with the enivornmental gravity.

<img width="166" height="68" alt="image" src="https://github.com/user-attachments/assets/706a186c-ffcd-43b6-80d7-9a6c9e637bcb" />

<img width="172" height="45" alt="image" src="https://github.com/user-attachments/assets/f4d56cdd-0516-40f8-88fd-bf7e08500f9f" />

#### Wind
The wind utilizes an analytic function to control the direction of the wind force. In this case, the function utilizes noise in combination with sinusodial functions to mimic a breeze. We then take this function to find the directional alignment of the wind. We also calculate a height ratio which indicated the "straightness of the blade with respect to the up vector of the blade" - this is used to apply a stronger affect on blades that are at the resting/initial position.

<img width="516" height="172" alt="image" src="https://github.com/user-attachments/assets/2b4f67fa-281e-47ec-8117-c9ac037ba392" />

Then we combine the forces together to create our total wind force.

<img width="300" height="44" alt="image" src="https://github.com/user-attachments/assets/792eb4ba-7b5b-4ca8-8195-532a46a227c3" />

### Culling
#### Orientation
![orientation](https://github.com/thumun/Project5-Vulkan-Grass-Rendering/blob/main/img/orientation.gif?raw=true)

Orientation based culling allows for grass blades that are parallel to the view direction of the camera to be optimized away. As these blades would not be visible anyways due to the blades not having a thickness. We accomplish this by taking the dot product of the view direction and the direction of the blade and comparing it with a threshold value.

<img width="388" height="50" alt="image" src="https://github.com/user-attachments/assets/e559f222-5803-4cf8-92f2-8716abfae15f" />

#### View-Frustrum
![viewfrustrum](https://github.com/thumun/Project5-Vulkan-Grass-Rendering/blob/main/img/viewfrustrum.gif?raw=true)

View-Frustrum culling takes care of blades that are outside of the camera's view-frustrum. We check to make sure that three points on the blade: v0, m (the midpoint of a curve composed of the three points), and v2 are all in the frustrum otherwise the blade is culled.

<img width="234" height="58" alt="image" src="https://github.com/user-attachments/assets/13faf523-f387-4c9d-8a63-5dedd3c17db7" />

We want to ensure that all of our points are in NDC space prior to comparing with our homogenous coordinate, h. There is also an arbitrary threshold, t, that is taken into account when comparing the points with the frustrum.

<img width="447" height="115" alt="image" src="https://github.com/user-attachments/assets/1f513433-a586-4419-939c-c193ec0d36b7" />

In the gif above, the culling is very subtle as it culls blades that are outside the camera's frustrum. The culling can be seen on the edges of the grass plane.

#### Distance
![dist](https://github.com/thumun/Project5-Vulkan-Grass-Rendering/blob/main/img/distanceculling.gif?raw=true)

Distance culling is where we cull blades based on their distance from the camera. In this implementation we use the distance from the camera to a blade (dproj), a maximum distance (where all grass beyond this distance will be culled), and buckets that our blades are sorted into such that the blades in the farther buckets are culled.
<img width="316" height="38" alt="image" src="https://github.com/user-attachments/assets/3b6a8327-4144-4f5e-9df8-6b318506f997" />

<img width="388" height="67" alt="image" src="https://github.com/user-attachments/assets/f212054e-02a8-409f-ac43-4b030cac7abe" />

### Level of Detail
![lod](https://github.com/thumun/Project5-Vulkan-Grass-Rendering/blob/main/img/tesselation.gif?raw=true)

A tesselation control shader is used to provide varying amounts of detail for our grass blades depending on how far they are from our camera. The blades closest to our camera have more verticies/detail while those farther away are simplified - this can be seen more clearly in the above gif. This is done via a smoothstep function in order to smoothly transition from varying levels of detail rather than have clear patches of grass of different verticies.

## Performance Analysis

Number of Blades vs FPS | Culling Methods vs FPS |
:-------------------------:|:-------------------------:|
![bladevsfps](https://github.com/thumun/Project5-Vulkan-Grass-Rendering/blob/main/img/numbladesvsfps.png?raw=true) | ![cullingmethods](https://github.com/thumun/Project5-Vulkan-Grass-Rendering/blob/main/img/cullingmethods.png?raw=true) |

Here is a table version of the data presented in the charts above:

Number of Blades | None | Orientation | View-Frustrum | Distance | All |
:-------------------------:|:-------------------------:|:-------------------------:|:-------------------------:|:-------------------------:|:-------------------------:|
2^10 | 624.8 | 528.3 | 626.6 | 223.3 | 248.8 |
2^12 | 594.6 | 596.6 | 633.4 | 419.7 | 512.2 |
2^14 | 504.4 | 605.6 | 572.2 | 590.3 | 604.3 |
2^16 | 287.1 | 565.5 | 412.9 | 619.7 | 622.9 |
2^18 | 98.4 | 311.3 | 151.7 | 407.5 | 562.5 |
2^20 | 29.9 | 105.1 | 44.2 | 105.3 | 421.0 |

The first chart depicts the renderer's performance as the number of blades increases while having no additional optimization methods (culling). As the blade count increases, the FPS gets lower as expected. The renderer is able to effectively simulate the grass until there is 2^16 blades of grass in the scene-at this point, the FPS drops to approximately 287 - which is still workable. The worse frame rates can be seen beyond this point.

The second chart depicts the effect of the various culling methods on the FPS as the number of blades increases. There is a general trend (as expected) of the FPS going down for all the methods as the number of blades increases. However, it is worth noting that each of the culling methods result in a better FPS than the base renderer (however small that increase may be). It is interesting to look at how for the case of all of the culling methods in tandem and distance, there is a worse FPS than having no culling at all. I imagine that may be due to having extra computation that may not be necessary for a lower number of blades. It is also curious that orientation seems to be the best method in general while view-frustrum improves as the number of blades increases. The most optimal number of blades for each of the methods appears to be 2^14 or 2^16.

## Resources Used
- [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) : the research paper that this project is based on and the diagrams above are sourced from here
- 5650 class material (recitation)
- [Noise Shadertoy](https://www.shadertoy.com/view/4dS3Wd)
- [OpenGL tutorial for tessalation](https://learnopengl.com/Guest-Articles/2021/Tessellation/Tessellation)
Binary file modified bin/Release/vulkan_grass_rendering.exe
Binary file not shown.
8 changes: 1 addition & 7 deletions external/GLFW/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
cmake_minimum_required(VERSION 2.8.12)
cmake_minimum_required(VERSION 3.18)

project(GLFW C)

set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)

if (NOT CMAKE_VERSION VERSION_LESS "3.0")
# Until all major package systems have moved to CMake 3,
# we stick with the older INSTALL_NAME_DIR mechanism
cmake_policy(SET CMP0042 OLD)
endif()

if (NOT CMAKE_VERSION VERSION_LESS "3.1")
cmake_policy(SET CMP0054 NEW)
endif()
Expand Down
Binary file added img/cullingmethods.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/distanceculling.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/forces.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/grassmain.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/numbladesvsfps.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/orientation.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/proj5.xlsx
Binary file not shown.
Binary file added img/stillgrass.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/tesselation.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/viewfrustrum.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/Blades.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,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_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);
}

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 << 16;
constexpr static float MIN_HEIGHT = 1.3f;
constexpr static float MAX_HEIGHT = 2.5f;
constexpr static float MIN_WIDTH = 0.1f;
Expand Down
8 changes: 8 additions & 0 deletions src/Camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
struct CameraBufferObject {
glm::mat4 viewMatrix;
glm::mat4 projectionMatrix;
uint32_t tessellationLODEnabled = 1;
uint32_t renderSettingEnableRecovery = 1;
float renderSettingEnableGravity = 9.8f;
uint32_t renderSettingEnableWind = 1;
// 0 to disable the below
float orientationCullingThreshold = 0.9f;
float viewFrustumCullingEnabled = 0.2f;
float distanceCullingThreshold = 15.0f;
};

class Camera {
Expand Down
Loading