Vertex colors with lighting info

Greetings !

I am working on implementation of a custom external renderer and would like to update vertex colors according to present lighting (Gouraud method will be fine for the start) and save this information to file. Is it possible to fetch the color info from existing shader (material) and bake it to vertex colors somehow ?

Short answer: not directly.

In three.js, lighting is computed in the shader on the GPU at render time. The material doesn’t store ā€œfinal colorsā€ per vertex anywhere you can just read back on the CPU, so you can’t simply fetch baked Gouraud colors from an existing material.

If you want vertex colors that include lighting, you have a couple of options:

  1. Recompute on the CPU
    You can mimic the lighting calculations yourself in JavaScript. Loop through the geometry vertices, evaluate your lights (directional, point, etc.), normals, and material properties, then write the result into a color attribute. This is basically doing Gouraud shading manually on the CPU.

  2. Custom shader + readback
    Modify or replace the material with a custom shader that outputs the lighting result per vertex (passed to fragment). Then render to a render target and read pixels back. The tricky part is mapping pixels back to vertices cleanly, so this is not as straightforward as it sounds.

  3. GPU baking approach
    Render the mesh in a way where each vertex maps to a known pixel (for example using a special UV or ID encoding), output the computed lighting, and read that back. This is more advanced but closer to an actual ā€œbakeā€.

If your goal is just Gouraud-style vertex colors, the CPU route is usually the simplest starting point. You already have access to geometry attributes and light data in three.js, so you can approximate what the built-in shaders are doing without fighting the GPU readback limitations.

1 Like

Thanks so much for your suggestions, I thought about all these approaches before writing the post, but they will take too much time and effort. Maybe I will choose a shader-based way if do not find a workaround.

It’s no longer part of three.js, but you could start with MeshGouraudMaterial, which was removed here:

The Gouraud materials implements per-vertex Lambertian shading. You would still need to add a way to read back the per-vertex data, perhaps with Transform Feedback.

Many thanks !
Transform feedback is very close to what I am looking for:

Will try to follow this way …

I don’t think it’s supported yet (or doesn’t have an example at least…) but another idea to keep an eye on would be:

2 Likes

Thanks for this idea. I’ve seen it before, but did not consider it in the context of this task - I need to explore it in detail, probably this is a solution. I will get back to this question in a few days after completing the present, less challenged project ).