frustum-grass
TypeScript icon, indicating that this package has built-in type declarations

0.0.3 • Public • Published

frustum-grass

This is an incomplete a-frame component that provides an easy to use/performant grass renderer. You can check it out here.

What it does

You give frustum-grass a set of vertices representing your scene, and it adds a bunch of grass to your scene. It has a couple tricks to keep your framerate high.

  • It uses Web Workers to perform spawning and culling calculations in a background thread, which help keep framerate stable.
  • It improves rendering performance using instanced meshes via the aframe-instanced-mesh package.

How to use it

Since frustum-grass uses Web Workers, you'll have to make sure the frustum-grass-worker.js file isn't bundled in with everything else.

I'm using webpack in my projects, so I always add something like this to my webpack.config.js:

{
  module: {
    rules: [
      {
        test: /frustum-grass-worker/,
        generator: {
          // You'll have to change your publicPath and outputPath
          // values to suit your exact desired output structure.
          publicPath: "assets/scripts/",
          outputPath: "assets/scripts",
          filename: "frustum-grass-worker.js"
        }
      },
    ]
  }
}

Once the Web Worker script is in its own file, you'll have to pass its location to the component.

  const grassWorkerUrl = new URL("frustum-grass/frustum-grass-worker", import.meta.url)
  grassWorkerUrl.searchParams.append("isFile", "true")

  const grassWrapper = document.querySelector("#frustumGrass") as any
  grassWrapper.setAttribute("frustum-grass", {
    workerUrl: grassWorkerUrl,
    fov: Math.PI / 1.5,
    density: 32,
    color: "rgb(102, 244, 76)"
  })

Finally, you'll have to give your grass component some vertices so it can start spawning terrain. I built frustum-grass to be used with Terrainosaurus, my procedural terrain generator. You can pass the vertices generated by Terrainosaurus to frustum-grass, and it'll figure out everything from there.

terrain.addEventListener("terrainInitialized", (event: CustomEvent) => {
  const { detail: { terrainClient: { vertices } } } = event
  const isTerrainosaurus = true
  const grassWrapper = document.querySelector("#frustumGrass") as any
  grassWrapper.components["frustum-grass"].setVertices(vertices, isTerrainosaurus)
})

What needs improvement

There are several things that aren't working that are must-haves before I consider this project truly complete.

  • Grass doesn't sway. I have a custom material with a vertex shader that accomplish this, but to make it work I need to update a uniform every tick, and I cannot figure out how to do this.
  • Instanced meshes seem to interfere with vertex shaders. I had a simplified vertex shader that did work but didn't have a good lighting model. However, even this shader stopped working as soon as I started using instanced meshes.

Other things I would like to do.

  • Since I am constantly adding and removing objects from the scene, it seems logical to use a-frame's object pooling feature, but I can't get this to work with instanced meshes. I don't know enough about object pooling and/or instanced meshes to say whether this is an optimization worth making.
  • Dynamically set the fov based on current viewport (and camera height?).

Package Sidebar

Install

npm i frustum-grass

Weekly Downloads

2

Version

0.0.3

License

MIT

Unpacked Size

21.8 kB

Total Files

5

Last publish

Collaborators

  • mbern