简体   繁体   中英

ID Rendering + Diffuse Rendering in THREE.js

I'm trying to use onBeforeRender to add an id material override function in my THREEjs app. This is a pretty common function for rendering applications, and I'd like to be able to use a scene.overrideMaterial to do it, but from my research it seems like I'm going to roll my own.

My approach is as follows.

When I instantiate objects:

...
      m.onBeforeRender = function (){
        if(Renderer._renderID){
            this.material = new THREE.MeshBasicMaterial(this.userData.idColor.getHex());
            this.material.needsUpdate = true;

            // Attempt at using a shader material
            //this.material = Renderer._idMat;
            //this.material.uniforms.idColor.value = this.userData.idColor;
            //this.material.uniforms.needsUpdate = true;
        }
      }
      m.onAfterRender = function (){
            if(Renderer._renderID){
                this.material = this.userData.material;
            }
      }
...

In my render loop:

...
        var idTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight);
        Renderer._renderID = true;
        Renderer._renderer.render(Renderer._scene, Renderer._camera, idTarget);
        Renderer._renderID = false;
...

Right now the id buffer and diffuse buffer are both rendering with the diffuse material.

Any help would be much appreciated. Please let me know if additional information is needed, I will update this post.

Three.js has an official gpu picking example which can be seen here .

They seem to be rendering things in two different scenes and with vertex colors. That's not a bad approach, and i disagree with the comment and your commented out code. Changing the uniforms is not the only way to achieve this, the official example uses vertex colors and merges all the geometries.

There are many ways to skin this cat.

You should by all means avoid creating new materials in tight loops.

This is suuuuper bad:

  m.onBeforeRender = function (){
    if(Renderer._renderID){
        this.material = new THREE.MeshBasicMaterial(this.userData.idColor.getHex()); //just a big NO
        this.material.needsUpdate = true; //no it doesnt! it's a new material it has this true by default

To achieve something like this, or your own custom override:

const myMesh = new Mesh()
myMesh.myMaterials = [
  someRenderMaterial,
  someIDMaterial,
]

scene.traverse(o=>{if(o.myMaterials) o.material = o.myMaterials[1]})
renderer.render(scene,camera)

scene.traverse(o=>{if(o.myMaterials) o.material = o.myMaterials[0]})
renderer.render(scene,camera)

But again, there's many many ways to do this. You could just make another scene and render vertex colors. You could make an override material and render vertex colors. Many parameters, many permutations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM