Rendering Countless Blades of Waving Grass
description
Transcript of Rendering Countless Blades of Waving Grass
Rendering Countless Blades of Waving Grass
Jeff SchmidtCS 680
Project Problem
Nature scenes are a prevalent topic in computer graphics (for example, computer games)
In addition, to realistic trees and flowing water effects, we want to render a high-quality grass effect in real-time that looks realistic from all angles
Project Problem
In general, grass needs to cover a vast amount of the scene. This makes modeling each individual blade of grass with polygons unrealistic
A simple, flat grass texture will only look realistic from certain angles
Solution
We create a “star” organization of quads and cover them with grass textures
Solution
The star formation gives us the same effect no matter which side of the grass object we are viewing
SolutionFinally, we want to simulate a wind
effect to make the grass feel more realistic
To simulate the blowing of grass, we shift the upper vertices of our grass object
My implementation
I have implemented both a CPU only and a GPU version of the program
I use OpenGL/GLUT for rendering
I used the GPU to speed up various tasks
My implementation
I have been running my project on double/float
CPU: Intel(R) Xeon(R) CPU GPU: GeForce GTX 580
Timings were taken using cudaEvent’s
No compiler flags
Where I use the GPU – Texture Loading
For the grass texture, I use .ppm files for their simple r, g, b, r, g, b,… file format
However, ppm files do not support an alpha channel
Solution: Pick a color that does not appear in any textures and fill the background with it. Then parse the texture file, and fill in alpha values where you used the “transparent” color
Where I use the GPU – Texture Loading
Each (r, g, b) triple is independent, therefore, splitting it amongst threads is simple
We only read each r, g, b value once, and we only write each alpha value once
Therefore, I used zero-copy host memory to eliminate copying the texture from the CPU to the GPU and back
Where I use the GPU – Texture Loading
Experiment ran with varying texture sizes. GPU version has 64 blocks, 64 threads
100 200 300 400 5000
100200300400500600700800900
Timings
Texture dimensions
Time (ms)
CPU
GPU
Where I use the GPU – Texture Loading
100 200 300 400 5000
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
GPU - Speedup
Texture dimensions
Speedup
Where I use the GPU – Scene InitializationAgain, each grass object is
independent of one another, therefore, each thread can create it’s own set of grass objects in parallel
Each grass object has an initial position that is perturbed by some random value, which gives slightly non-uniform distribution
PROBLEM: Creating a random number on the GPU
Where I use the GPU – Scene Initialization
To generate random numbers, I create an array on the host filled with random numbers
Then I place the array in texture memory
Each block/thread indexes into the texture to retrieve the desired random numbers
Where I use the GPU – Scene InitializationExperiment ran with varying numbers of grass
objects. GPU version has 64 blocks, 64 threads
10000 20000 30000 40000 500000
102030405060708090
100
Timings
Number of Grass Objects
Time (ms)
CPU
GPU
Where I use the GPU – Scene Initialization
10000 20000 30000 40000 500001.351.4
1.451.5
1.551.6
1.651.7
1.751.8
1.85
GPU - Speedup
Number of Grass Objects
Speedup
Where I use the GPU – Wind Simulation
Create random wind vectors crossing the viewing area
Calculate vector to shift the grass objects by measuring their distance from wind vector
After the wind blows, “spring” back towards resting position
Include some slight randomness, so that all grass doesn’t move exactly the same speed/direction
Where I use GPU – Wind Simulation
Unfortunately, due to time, I was unable to simulate wind
Instead, my grass objects wave randomly
Where I use the GPU – Wind Simulation My “wind” simulation actually runs
slower on the GPU version, due to creating the texture of random numbers and copying them to the GPU
For this reason, I did not include any timings
For a more in-depth wind simulation, the GPU version would likely out-perform the CPU
Lessons Learned
Strategies to get random numbers from the GPU: Store them in a texture generated by the
host Implement a simple psuedo-random
number generator that runs on the GPU (example: linear congruential generators)
Lessons Learned
I got to implement some new (for me) CUDA features Zero-copy host memory – used for
updating my textures with transparency Texture memory – used for storing
random numbers and passing them to the GPU
Use __host__ __device__ for functions you want on both the CPU and GPU
Future Improvements
I would have liked to use CUDA’s interoperability features with OpenGL to have the GPU render the scene without going through the CPU
I would have liked to explore CUDA streams for overlapping of GPU calculations and memory copying
Future Improvements
Due to time constraints, I was unable to implement wind simulation. I would have liked to use a real simulation formula and better grass textures to make the scene look more realistic
A screenshot