gkjohnson / three-gpu-pathtracer

Path tracing renderer and utilities for three.js built on top of three-mesh-bvh.
https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/index.html
MIT License
1.38k stars 133 forks source link

Using a THREE.ShaderMaterial does not work #346

Closed Shrilliant closed 1 year ago

Shrilliant commented 1 year ago

Describe the bug

Adding a mesh to a THREE.Scene that uses a THREE.ShaderMaterial on render from three-gpu-pathtracer results in:

Uncaught TypeError: Cannot read properties of undefined (reading 'r') at MaterialsTexture.updateFrom (index.module.js:1754:37) at render

The code (from three-gpu-pathtracer in index.module.js) looks like:

    for ( let i = 0, l = materials.length; i < l; i ++ ) {

        const m = materials[ i ];

        // sample 0
        // color
        floatArray[ index ++ ] = m.color.r; // where the error occurrs 

The shader material has no "color" attribute because the colors on the mesh are determined by a GLSL program, so when the renderer tries to render it, it causes an error.

Expected behavior

The colors should be rendered from the GLSL shader onto the geometry, then behaving as a material in the scene, respecting the light in the scene, causing bounces, etc.

An alternative implementation could be to support GLSL Shaders in .onBeforeCompile() which is a way for THREE.JS to overlay GLSL shaders onto its base materials, causing their color to be defined by the shader but their material attributes behaving as they normally would.

I chose to use a THREE.ShaderMaterial instead since it more directly addresses the problem, but the preferred solution is to support .onBeforeCompile() so that shaders can work on ANY material with any parameters, but... baby steps? 🤷‍♂️ (they behave in similar ways)

(on request I can re-factor this to use .onBeforeCompile, I think the problem will still persist. I started that way so I can just go back to it :D )

Screenshots and Repro Model

Screen Shot 2022-12-31 at 6 26 57 PM

A GLTF model doesn't exist for this problem from my end since I'm generating the geometry on-the-fly with parametric equations, so the link to my repo and github pages that I made just for this issue is linked here: https://shrilliant.github.io/Raytracing-Flower-THREE.ShaderMaterial/

and the repo can be found here: https://github.com/Shrilliant/Raytracing-Flower-THREE.ShaderMaterial

Platform:

gkjohnson commented 1 year ago

Hello! Unfortunately there's no plan or way to support procedural geometry this way with the pathtracer. Someday SDF rendering could be supported or maybe procedural surface color but generally supporting "onBeforeCompile" isn't viable since geometry must be known ahead of time so a BVH can be generated.

One solution for supporting this kind of procedural geometry would be to write a utility class / material that can write the generated vertex positions out to a texture, read them back to the CPU, generate a geometry & BVH from them, and then perform the path tracing. I don't have any immediate plans to support this but if you'd like to put time into it I'm happy to provide some guidance.

Shrilliant commented 1 year ago

I'd be more than willing to spend time to accomplish this :) I've been working on this project for the flowers for about 6 months now and raytracing is something I just began looking into, but it adds so much to what the project could be.

The geometry is generated beforehand and exists as a normal geometry in the BVH since it doesn't change after it's added to the scene. The main thing is just getting the colors to exist from GLSL -> (somewhere that can be read by the renderer, maybe vertex colors or a map?) -> the renderer -> pixels. I haven't looked into actually just getting the texture to exist as some kind of a map, but this could be the workaround that I need :)

thank you for discussing this with me!

gkjohnson commented 1 year ago

Okay in that case the approach I mentioned may be overkill. Your best bet is probably generated textures or vertex colors as you suspect.