Procedural Grass Geometry Shader [GLSL 4.0 v.3 && GLSL 1.5 v.2] AMD fully supported!


This is an entirely procedural grass shader that generates grass from information passed from a ground mesh. It takes a stencil map to determine grass placement, and 3 grass textures to create various grass objects. It does not render the ground, I was unable to solve problems with the grass objects clipping through the ground. However, it is trivial to duplicate the ground mesh, and separating the materials is probably a good idea anyway.

The above video starts at dark and runs through the dawn transition to daytime.

The shader is setup to run 9 instances of the geo shader. That means that for every grass object created, 8 more will be created also (each instance is randomized - placement and rotation).

The grass moves in the wind using an almost identical function as in my previous shader; however, the strength of the wind has been exposed so that it can be easily changed.

I have added a lighting model, the lighting is done per grass object, not per-fragment or per-vertex. It supports up to 8 lights; directional or point, and you can mix and match them however you like. There is no limit (as I thought I was going to have) on directional lights. If you want all 8 lights to be directional, you can (and vice versa).

The info for the lighting comes straight from the lights. For directional lights; the color and strength can both be adjusted, and for point lights; the color, strength, and distance (radius) is adjustable.

There is a built-in multi-level LOD system. The initial LOD levels are two-tiered, the first level is at 24 meter by default. The second is at 2x the first, each instance changes this by a certain amount. Total (default) - there are 12 different LODs; 6 per tier, hopefully erasing any ‘lines’ showing grass poping in and out. (edited for v2)

I wrote a decent readme that contains much more info, including how to customize the shader. And I’ll echo here what I ended it with:

I am sure that there are a million things that I am forgetting. If you have any questions, feel free to send me a PM. Also, if anyone has a feature request that the community would find useful, feel free to ask. I am still working on this thing. For some reason, I just cant put it down…

There are plenty more things that I want to add to it || change about it:

  • move lighting to the fragment shader
  • add spotlights
  • more user friendly
  • version for GLSL 1.5
  • auto-detect GLSL version
  • a lot of tweaking

There are some requirements for this one:
GPU compatible with GLSL 4.0 (OpenGL 4.0)
Better GPU = Better performance
Less Lights = Better performance
Less Grass = Better performance
Smaller Grass Size = Better performance

Lights are a killer for performance, on my system disabling them yield 30+ fps increase.

Update v2:

  • more grass, better performance
  • fixed an issue with a grass height equation that was causing massive slowdowns
  • switched all of the lighting info to the geometry shader - performance increase
  • exposed the LOD distance float
  • created a lighting factor property
  • created a material intensity factor property
  • other small tweaks

    Update v3:
  • same as v2
  • more performance optimizations
  • better user access to vars
  • more detail in the readme
  • AMD support

Full version - requires GLSL 4.0
ProceduralGrassShader_v3.blend

Lite version for GLSL 1.5
ProceduralGrassShaderLite_v2.blend

3 Likes

It’s stunning!

Blender game error is=

Invalid uniform value: Type2.
Invalid uniform value: Time.
Invalid uniform value: windStrength.
Invalid uniform value: AmbientMulti.
Invalid uniform value: Radius1.
Invalid uniform value: Radius2.
Invalid uniform value: Type1.
Invalid uniform value: Type2.
Blender Game Engine Finished

The computer i am using is a Hewlett packard
windows 8.1
processor: AMD E1-2500 APU with Radeon™HD Graphics 1.40 GHz
installed memory(RAM): 4.00 GB(3.43 GB usable)
system type: 64-bit Operating System,x64-based processor
pen and touch: No Pen or Touch Input is available for this Display:(

Even day/night cycle. So beautiful:)

Invalid uniform value: Type2.Invalid uniform value: Time.
Invalid uniform value: windStrength.
Invalid uniform value: AmbientMulti.
Invalid uniform value: Radius1.
Invalid uniform value: Radius2.
Invalid uniform value: Type1.
Invalid uniform value: Type2. Blender Game Engine Finished

Yup got the same errors here, all works but grass not showing again. (amd)

all works, stable 60 fps,

most of my % are in rasterizer. (like 14 ms) on alienware alpha.

Very nice shader. Looking very good!:slight_smile:
I get around 40-50fps on a some years old Notebook with i5 2.3-2.9GHz and NVIDIA GeForce GT 540M but with ~90%/~20ms GPU Latency.

I hope he fixes it.I would love to see that grass with the night and day cycle.

Thank you for the compliments!

For AMD; I will definitely be looking into the problem, but first I will need to create a simpler version for testing (i.e. GLSL version 1.5). Shouldn’t take too long to weed out the 4.0 dependencies…

I get 30-37 FPS when looking at grass, I think it’s fine:)

I found a bug that was causing performance issues… My randomizing grass height formula was wrong, causing extra grass to travel through some expensive calculations and ultimately not render. I will be releasing an update soon; more grass and better performance…

Not sure where I got this, but for some reason I also thought that GLSL’s compatibility profile was discontinued after OpenGL 3.3. I fixed that mistake. This means less information is needed to travel from the vertex shader to the geo shader - better performance again. This might also resolve some people’s issue with too many components being passed from the vertex shader (not sure if anyone has hit that limit). I do not know if it will solve the issues for AMD though, I will start work on rectifying those after the update.

I get a framrate of 7.5.

I updated the blend.

Fixed an issue that was causing slowdowns and some of the grass to not appear. With the extra grass I decreased the instances from 9 to 6. I also moved all of the lighting info to the geo shader thanks to #version 400 compatibility. This increased performance again as less information is calculated and sent from the vertex shader to the geo shader.

I also went ahead and made the LOD distance an object property so that it could be easily adjusted (only first level, second is still 2x the first). Additionally, I created a lighting multiplier. Adjusting its value increases or decreases the amount of lighting applied to the grass objects. Similarly, I created a ‘material’ intensity factor. Adjusting its values changes everything about the final color (lighting, diffuse, and ambient). The lighting and intensity multipliers are object properties for easy adjustment.

For me framerate now is lower…:frowning:

smooth looking scene. for me the framerate is 60

Wow, I guess that shows that each implementation of GLSL is different. My GeForce GT 640 saw an increase from 51 fps to 78… (frametime from ~17ms to ~12ms)

Gooooood job mate.

Incredible work!

Is it possible to get the grass to react to a local force, i.e. a gust of wind only affecting some areas, a player pushing through grass etc?

For an image, think of the PS3 game Flower and the grass in that.

Maybe low-end technology has lower support for the new method?

A gust of wind might be hard to do, but pushing through grass would probably not be too hard. I’ll take and look into pushing the grass away as the camera gets close to it…

I want to find a way to trample the grass down; either the player or an object that is thrown, but first I need to increase the resolution of the stencil map. If I can increase the resolution of the stencil map, we could use a separate channel to store information like trampling the grass down with texture painting (i.e 1.0 = grass standing, 0.0 = grass trampled).

I’m not sure, right now there is still room for improvement…