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

Project5: LichengCao #7

Open
wants to merge 9 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
560 changes: 560 additions & 0 deletions .gitignore

Large diffs are not rendered by default.

50 changes: 45 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,50 @@ 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)
* Licheng CAO
* [LinkedIn](https://www.linkedin.com/in/licheng-cao-6a523524b/)
* Tested on: Windows 10, i7-10870H @ 2.20GHz 32GB, GTX 3060 6009MB

### (TODO: Your README)
Result
====
* This project is implemented based on [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).
<p align="center">
<img src="mdassets/result.gif">
</p>

*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.
Features
===
### Blade Geometry
* The [paper](https://www.cg.tuwien.ac.at/research/publications/2017/JAHRMANN-2017-RRTG/JAHRMANN-2017-RRTG-draft.pdf) presented 4 kinds of blade shapes as shown. I picked triangle-tip as my basic blade geometry.
<p align="center">
<img src="mdassets/geom.PNG">
</p>

### Force Simulation
* In the [paper](https://www.cg.tuwien.ac.at/research/publications/2017/JAHRMANN-2017-RRTG/JAHRMANN-2017-RRTG-draft.pdf), The authors constructed a physical model to simulate grass, as depicted below. According to the paper, the parameters required to simulate grass include `v0`, `v1`, `v2`, `up`, `height`, `direction`, `width`, and `stiffness`. The first four values are of type `vec3`, while the subsequent values are simply of type `float`. In my implementation, I passed four `vec4` values to the shader, with the float value stored in `vec4.w`. This application simulates three types of forces: `gravity`, `wind force`, and `recover force`. The `recover force` characterizes the force that restores the grass blade to its equilibrium position and is computed using the parameter stiffness.
<p align="center">
<img src="mdassets/phy.PNG">
</p>

### Culling
* To enhance performance, the paper also introduced several culling methods aimed at eliminating unnecessary blades, thereby reducing the overall number of shapes that need to be rendered.

|Orientation Culling|Frustum Culling|Distance Culling|
|:--:|:--:|:--:|
|<img src="mdassets/oriCull.gif" width="200">|<img src="mdassets/frusCull.gif" width="200">|<img src="mdassets/distCull.gif" width="200">|

Performance
===
* As expected, the average frames per second (FPS) decreases as the number of blades increases. However, as depicted in the figure, the FPS remains nearly constant when the number of blades is below 2^13, highlighting the efficiency of the algorithm.
<p align="center">
<img src="mdassets/fpsnum.PNG">
</p>

* I recorded the average FPS with 2^18 blades, and the result is shown below. The average fps indicates that all culling methods offer some improvement for rendering. With my test scene, the distance culling contributes the most to fps, the reason might be that I picked a relatively small max distance for culling test, so that many blades are culled. Frustum culling gives the least improvement, this may due to the fact that I tried to record every blades in the output so most blades fall in the frustum and therefore are not culled.

|culling method applied|all cullings|orientation culling|frustum culling|distance culling|none|
|:--:|:--:|:--:|:--:|:--:|:--:|
|average fps(higher better)|150.5|94.1|79.7|98.4|65.3|
<p align="center">
<img src="mdassets/fpscull.PNG">
</p>
Binary file modified bin/Release/vulkan_grass_rendering.exe
Binary file not shown.
Binary file added mdassets/distCull.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 mdassets/fpscull.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 mdassets/fpsnum.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 mdassets/frusCull.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 mdassets/geom.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 mdassets/oriCull.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 mdassets/phy.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 mdassets/result.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_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
59 changes: 55 additions & 4 deletions src/Camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,41 @@
#include "Camera.h"
#include "BufferUtils.h"

void Camera::updateAttrb()
{
forward = glm::normalize(ref - eye);
right = glm::cross(forward, worldUp);
up = glm::cross(right, forward);
}

glm::mat4 Camera::getViewMatrix()
{
glm::mat4 rot(glm::vec4(right,0), glm::vec4(up,0), glm::vec4(-forward,0), glm::vec4(0, 0, 0, 1));
rot = glm::transpose(rot);
glm::mat4 trans(glm::vec4(1,0,0,0), glm::vec4(0,1,0,0), glm::vec4(0,0,1,0), glm::vec4(-eye, 1));
glm::mat4 res = rot * trans;
return res;
}

Camera::Camera(Device* device, float aspectRatio) : device(device) {
r = 10.0f;
theta = 0.0f;
phi = 0.0f;
cameraBufferObject.viewMatrix = glm::lookAt(glm::vec3(0.0f, 1.0f, 10.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
eye = glm::vec3(0, 1, r);
ref = glm::vec3(0,1,0);
updateAttrb();
cameraBufferObject.forward = glm::vec4(forward,0);
cameraBufferObject.position = glm::vec4(eye,1);
cameraBufferObject.viewMatrix = getViewMatrix();
//for (int i = 0;i < 4;++i) {
// for (int j = 0;j < 4;++j) {
// std::cout << cameraBufferObject.viewMatrix[j][i] << " ";
// }
// std::cout << std::endl;
//}
cameraBufferObject.projectionMatrix = glm::perspective(glm::radians(45.0f), aspectRatio, 0.1f, 100.0f);
cameraBufferObject.projectionMatrix[1][1] *= -1; // y-coordinate is flipped


BufferUtils::CreateBuffer(device, sizeof(CameraBufferObject), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, buffer, bufferMemory);
vkMapMemory(device->GetVkDevice(), bufferMemory, 0, sizeof(CameraBufferObject), 0, &mappedData);
Expand All @@ -33,10 +61,33 @@ void Camera::UpdateOrbit(float deltaX, float deltaY, float deltaZ) {
float radTheta = glm::radians(theta);
float radPhi = glm::radians(phi);

glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), radTheta, glm::vec3(0.0f, 1.0f, 0.0f)) * glm::rotate(glm::mat4(1.0f), radPhi, glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 finalTransform = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f)) * rotation * glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 1.0f, r));
//glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), radTheta, glm::vec3(0.0f, 1.0f, 0.0f)) * glm::rotate(glm::mat4(1.0f), radPhi, glm::vec3(1.0f, 0.0f, 0.0f));
//glm::mat4 finalTransform = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f))
// * rotation
// * glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 1.0f, r));
float cosPhi = glm::cos(radPhi);
float sinPhi = glm::sin(radPhi);
float sinTheta = glm::sin(radTheta);
float cosTheta = glm::cos(radTheta);
eye = ref - glm::vec3(cosPhi * sinTheta, sinPhi, cosPhi * cosTheta) * r;
updateAttrb();
cameraBufferObject.forward = glm::vec4(forward, 0);
cameraBufferObject.position = glm::vec4(eye, 1);
cameraBufferObject.viewMatrix = getViewMatrix();//glm::inverse(finalTransform);

memcpy(mappedData, &cameraBufferObject, sizeof(CameraBufferObject));
}

cameraBufferObject.viewMatrix = glm::inverse(finalTransform);
void Camera::UpdatePosition(float fwd, float rt)
{
glm::vec3 diff = glm::normalize(glm::vec3(forward.x, 0, forward.z)) * fwd + glm::normalize(glm::vec3(right.x, 0, right.z))*rt;
eye += diff;
ref += diff;
cameraBufferObject.forward = glm::vec4(forward,0);
cameraBufferObject.position = glm::vec4(eye, 1);
cameraBufferObject.viewMatrix = getViewMatrix();
//std::cout << "act" << forward[0] << ", " << forward[1] << ", " << forward[2] << std::endl;
//std::cout << "mat" << cameraBufferObject.viewMatrix[0][2] << ", " << cameraBufferObject.viewMatrix[1][2] << ", " << cameraBufferObject.viewMatrix[2][2] << std::endl;

memcpy(mappedData, &cameraBufferObject, sizeof(CameraBufferObject));
}
Expand Down
17 changes: 14 additions & 3 deletions src/Camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
#include "Device.h"

struct CameraBufferObject {
glm::mat4 viewMatrix;
glm::mat4 projectionMatrix;
glm::vec4 forward;//add
glm::vec4 position;
glm::mat4 viewMatrix;
glm::mat4 projectionMatrix;
};

class Camera {
Expand All @@ -21,12 +23,21 @@ class Camera {
void* mappedData;

float r, theta, phi;

glm::vec3 eye;
glm::vec3 ref;
glm::vec3 forward;
glm::vec3 right;
glm::vec3 up;
glm::vec3 worldUp = glm::vec3(0,1, 0);

void updateAttrb();
glm::mat4 getViewMatrix();
public:
Camera(Device* device, float aspectRatio);
~Camera();

VkBuffer GetBuffer() const;

void UpdateOrbit(float deltaX, float deltaY, float deltaZ);
void UpdatePosition(float fwd, float rt);
};
Loading