DEV Community

Cover image for Rust Game Dev Log #3: Grass Part 3 | Color Gradient!
Michael Mironidis
Michael Mironidis

Posted on

Rust Game Dev Log #3: Grass Part 3 | Color Gradient!

Welcome back!

After a busy couple of months at work and a relaxing vacation, I'm back with another Rust Game Dev Log! Last time, we left off on realistic wind simulation. Today, I'll be giving our grass a realistic touch by introducing vertex coloring to create a gradient that gives off the appearance of being dried out by the sun.

This will be a short one, since my work on grass was put aside for implementing physics into the game using rapier3d, basic player movement, and a third person camera, as well as updating projectile logic to point in the direction it is initially fired. A post or two for these topics will come next, so stay tuned!

As always, there may be some changes I have made to the code that I miss, usually in the form of small, basic optimizations fixing fast-and-loose initial iterations of code, so be sure to check out the repo for the latest code.

Getting started

Since we will be coloring our vertices of our grass, we will change the base_color of our grass material to white so that when we color our vertices, we get the exact colors we specify.

Now, to programmatically define vertex coloring, we will need to know the base position of the grass blade so that we can use the relative y position of the vertex to do our calculation, like in the apply_wind function. Otherwise, grass generated at different heights would have different colors.
So, we update generate_grass_geometry to take a reference to grass_offsets as an argument. We then add a colors vector that stores an array of four f32 representing the rgba values of the vertices. We populate this variable with a new function generate_vertex_colors that takes a reference to the vertex positions vector we've already created and the grass_offsets pointer we've passed, and generates rgba values based off the relative y of the vertex:

fn generate_vertex_colors(positions: &Vec<[f32; 3]>, grass_offsets: &Vec<[f32; 3]>) -> Vec<[f32; 4]> {
    positions.iter().enumerate().map(|(i,[x,y,z])| {
        let [_, base_y, _] = grass_offsets.get(i).unwrap();
        let modified_y = *y - base_y;
        [0.03*modified_y + 0.07,0.128,0.106 * -modified_y, 1.]
    }).collect()
}
Enter fullscreen mode Exit fullscreen mode

The actual calculation of the rgba value is up to you! I picked two different rgba values with a color picker and just modelled it off of those. The end result, as seen in the header, is quite nice!

Grass with a green to yellow gradient from bottom to top

I wanted a subtle effect, but for more dried out looking grass you can increase the 0.07 base r value to 0.14 and get this:

Grass with a yellower green to orange-yellow gradient from bottom to top

Really, you can do anything you want by playing with how the rgba values are calculated!

Grass with a red to white/grey gradient from bottom to top

That's a huge impact on the visuals for not a lot of additional code!

Final Thoughts

The interface in which the color gradient is determined should, in the long-term, be improved to be able to simply pass in two rgba values, one for the base and one for the top, and calculate the vertex coloring accordingly.

That's all for this post! Be sure to follow me here on dev.to to keep up to date with developments on this project, and I encourage you to fork, open issues, or just play around with the repo yourselves!

Top comments (0)