I want to render an animation in which a car drives along a certain stretch of road. To one side there is a grass field, but this is quite big, both in the direction perpendicular to the car, and along the direction of travel. I don't have enough memory to put highly detailed grass on the whole field, so I was wondering if it was possible to reduce the number of grass strands based on the distance from the camera.

Or maybe there are other tricks to achieving this?


2 Answers 2


You can use a script that calculates the distance of each vertex in your grass field from the camera at each frame, and updates a vertex group controlling your particle system's density accordingly.

enter image description here

To get this to work:

  1. Your grass field needs to have a vertex group, with all vertices included (create then select all verts and press "Assign").
  2. In your particle system, you need to set this vertex group as the Density group, with inverted weight (see the image below).
  3. Make sure to replace the names of your grass field object, particle system and vertex group if needed in the script (they're called "Plane", "ParticleSystem" and "Group" in the code below).
  4. Open a text editor window, create a new text file, copy the code there and press "Run Script".

enter image description here

Here's the code:

import bpy

def weight_from_distance( scene ):
    floor = bpy.data.objects['Plane']  # <== REPLACE "Plane" with the name of your grass field object
    cam   = bpy.data.objects['Camera']

    vert_distances = [ 
        ( cam.location - floor.matrix_world @ v.co ).length for v in floor.data.vertices #Updated for 2.8+: Replaced '*' with '@'

    maxDist = max( vert_distances )
    minDist = min( vert_distances )

    for i, d in enumerate( vert_distances ):
        # Normalize distance and set as vertex weight
        floor.data.vertices[i].groups[0].weight = ( d - minDist ) / ( maxDist - minDist )

    pSysName      = 'ParticleSystem' # <== REPLACE with the name of your grass' particle system if needed
    vertGroupName = 'Group'          # <== REPLACE with the name of your vertex group if needed
    floor.particle_systems[ pSysName ].vertex_group_density = vertGroupName # Update / Refresh

bpy.app.handlers.frame_change_pre.append( weight_from_distance )
  • $\begingroup$ Amazing work, thanks! I'm going to try and implement this as soon as I have time. I hope you the grass won't flicker too much between density variations, but I guess that will be a matter of fine tuning. $\endgroup$
    – cybrbeast
    Feb 23, 2016 at 17:42
  • $\begingroup$ Sure :) Flickering could be an issue. Let me know how it worked for you, I'm curious if this will be actually useful or if a smarter solution is needed. $\endgroup$
    – TLousky
    Feb 23, 2016 at 17:43
  • 2
    $\begingroup$ Basically this same result can be done with dynamic paint. $\endgroup$
    – PGmath
    Feb 23, 2016 at 22:08
  • $\begingroup$ Makes sense, @PGmath. However, isn't object intersection required for this to work? (I guess you can parent a sphere to the camera to achieve this). By the way - might be worth another answer to demonstrate this. $\endgroup$
    – TLousky
    Feb 23, 2016 at 22:11
  • 1
    $\begingroup$ @TLousky I think you do need an actual mesh for the DP brush. I'd use proximity instead of intersection though. $\endgroup$
    – PGmath
    Feb 23, 2016 at 22:23

I'm not sure if theres a way of achieving this.


You can hide the grass in 3d view mode if you want, but let it still be visible while rendering. Here's a picture:

Picture of where to hide

Simply click on the little eyeball to hide the grass. You can press the camera if you want to hide it in render mode.

I'm not sure if this completely solves your problem, but I'm guessing it's the best way to go.

Happy blending!

  • 1
    $\begingroup$ That doesn't work, as when I go and render my memory (16GB) overflows due to the millions of particles. $\endgroup$
    – cybrbeast
    Feb 23, 2016 at 13:40
  • $\begingroup$ Sorry then. Don't know what to do... $\endgroup$ Feb 23, 2016 at 13:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.