Javascript 使用THREE.js中的相同渲染器在多个THREE.EffectComposer场景之间切换

Javascript 使用THREE.js中的相同渲染器在多个THREE.EffectComposer场景之间切换,javascript,three.js,Javascript,Three.js,我正在用three.js中的Composer创建复杂的场景。 我想知道是否有可能在两个具有不同作曲家效果的场景之间切换。为了获得某种透视效果,我创建了一个示例,它允许您在两个正常渲染的场景之间切换 根据我对composer工作原理的理解,您可以创建其实例,然后应用渲染过程,如下所示: this.composer = new THREE.EffectComposer(this.renderer.default.init); this.renderPass = new THREE.

我正在用three.js中的Composer创建复杂的场景。 我想知道是否有可能在两个具有不同作曲家效果的场景之间切换。为了获得某种透视效果,我创建了一个示例,它允许您在两个正常渲染的场景之间切换

根据我对composer工作原理的理解,您可以创建其实例,然后应用渲染过程,如下所示:

    this.composer = new THREE.EffectComposer(this.renderer.default.init);
    this.renderPass = new THREE.RenderPass(this.stage,  this.camera);
    this.renderPass.renderToScreen = true;
    this.composer.addPass(this.renderPass); 
然后应用composer渲染,如下所示:

    this.composer.render();
所以我的问题是,如果我有第二个场景是作曲家的实例,那么我怎么能:

  • 使用相同的渲染器(如果可能)
  • 在场景1和场景2之间切换,方式与我的示例类似

  • 您可以按照从一个场景切换到另一个场景的相同方式,从一个effectComposer切换到另一个effectComposer。所以这是这样的:

    const scenes = [
      new THREE.Scene(), 
      new THREE.Scene()
    ];
    
    const composers = scenes.map(function(scene) {
      const composer = new THREE.EffectComposer(renderer);
    
      // configure render-passes
      const renderpass = new THREE.RenderPass(scene, camera);
      renderpass.renderToScreen = true;
      composer.addPass(renderpass);
    
      scene.composer = composer;
      return composer;
    });
    
    // then use the composer for the scene
    let activeScene = scenes[0];
    activeScene.composer.render();
    
    如果愿意,您甚至可以重用某些渲染过程。

    因此,在我开始之前,我只想对谁提供了这个解决方案的见解大喊一声

    免责声明

    我不是javascript方面的专家或专业程序员,我绝不建议这是唯一的方法,我的演示应该以抽象的方式进行。我的想法只是解释了解决方案所基于的理论前提,而这一前提的实现将取决于您自己的体系结构

    架构

    在本例中,我使用的是OOP方法,您应该能够将解决方案操作到您正在使用的任何方法

    方法

    因此,根据Martin当前的示例,您可以看到我们可以将composer属性/对象添加到场景对象,这意味着场景可以继承相同的composer效果,这非常出色,但是在我的例子中,我有许多具有不同composer效果的场景,因此我需要重新思考这个问题

    1。创建一个Composer对象。

    因此,我创建了一个对象,将composer对象放入其中,并在引用我的效果时保持良好的“composer”名称约定

    This.composer = {};
    
    2。创建一个函数来初始化相关场景的渲染过程。

    因此,重要的是要记住,在调用编写器之前,我们需要首先定义并初始化renderPass。RenderPass允许我们对所需的效果(知道有着色器)进行属性化。在我的示例中,我有两个场景,因此需要创建:

  • 两个渲染器
  • 一个渲染过程复制了场景
  • 另一个渲染过程对其场景应用了深褐色效果
  • 代码示例:

    this.init = function() {
    
    stackoverflow.webgl.pass.base = new THREE.RenderPass(stackoverflow.webgl.scene.default, 
    stackoverflow.webgl.camera);
    
    stackoverflow.webgl.pass.base2 = new THREE.RenderPass(stackoverflow.webgl.scene.test, 
    stackoverflow.webgl.camera);
    
    stackoverflow.webgl.pass.sepia = new 
    THREE.ShaderPass(THREE.SepiaShader);
    stackoverflow.webgl.pass.sepia.renderToScreen = true;
    
    stackoverflow.webgl.pass.copy = new THREE.ShaderPass(THREE.CopyShader);
    stackoverflow.webgl.pass.copy.renderToScreen = true;
    
    } 
    
    注意:由于法律原因,一些文件名必须重命名,但关键是这个函数被调用到一个更大的对象中

    3。创建一个开始函数,并允许为场景指定作曲家

    此函数的目的只是演示如何将其组合在一起。我们的代码是这样的

    // so we create an object to use for reference for EffectComposer objects
        this.composer = {};
    
    
    // this property is used to set the scene that we want
    // this.scene.default = new THREE.Scene();
    
        this.activeScene = this.scene.default;
    
    // this function is just a wrapper for our code
    
        this.start = function () {
    
    // so call our initialise our RenderPasses
    
        stackoverflow.webgl.pass.init();
    
    // my own method of seting up the WebGLRenderer scene (You do it your Way!)
        stackoverflow.webgl.renderer.default.setup;
    
    // Create a new composer for scene 1
        this.composer.ui = new THREE.EffectComposer(stackoverflow.webgl.renderer.default.init);
    
    // Create a new composer for scene 1
        this.composer.ui2 = new THREE.EffectComposer(stackoverflow.webgl.renderer.default.init);
    
    // Now here is the cool stuff you can assign a composer to each scene
    
        this.scene.default.composer = stackoverflow.webgl.composer.ui;
        this.scene.test.composer = stackoverflow.webgl.composer.ui2;
    
    // and i always like to check that things happen and they do ;)
    
        console.log(this.scene.default);
        console.log(this.scene.test);
        console.log(this.composer);
    
    // so  you will need to add the passes some place, I created a function call render, (you do according to your code structure)
    
        stackoverflow.webgl.render();
    
        }
    
    4。定义在体系结构中添加过程的位置

    所以现在我们需要添加pass声明(composer提供的addpass函数)才能产生效果

    this.render = function () {    
    stackoverflow.webgl.composer.ui.addPass(stackoverflow.webgl.pass.base);        
    stackoverflow.webgl.composer.ui.addPass(stackoverflow.webgl.pass.copy);      
    stackoverflow.webgl.composer.ui2.addPass(stackoverflow.webgl.pass.base2);
    stackoverflow.webgl.composer.ui2.addPass(stackoverflow.webgl.pass.sepia);
    };
    
    5。添加EffectComposer渲染方法

    因此,这一行代码需要放在进行composer处理的任何位置(这取决于您的设置)

    请注意,“ActiveCcene”部分引用了当时使用的实际场景。正是这一点让我们能够改变场景

    6。创建一个按钮并在场景之间切换

    因此,我在dat.gui实例中创建了两个按钮,允许我在两个场景之间切换

    同样,你可以创建一个按钮,你喜欢的任何功能

    // again just change the vale of active scene to the scene you wish to change to
    
    // button 1 value will be something like this:
    stackoverflow.webgl.activeScene = stackoverflow.webgl.scene.test;
    
    // button 2 value will takes us back to scene 1
    stackoverflow.webgl.activeScene = stackoverflow.webgl.scene.default;
    
    结论
    这是我实现此效果的方法,但如果有更好或替代方法,请添加到讨论中并与大家分享。

    我很抱歉没有尽快回复您,感谢您提供此示例,我快速实现了,并通过在effect composer中切换场景来实现,正如您提到的,我可以使用多个EffectComposer,我只是想通过您的示例来形象化这将是什么样子,但使用EffectComposer的方法对我来说还是全新的。有没有可能提供一个小的代码片段来说明这一点。很多感谢我并不真正了解你的用例,所以很难提出关于架构的建议。您可以将composer附加到场景对象,这样您只需切换场景并始终使用
    activeScene.composer.render()
    进行渲染。关于特效作曲家本身的更多细节,我建议添加一个单独的问题(也可能有帮助:)是的,我认为activeScene.Composer就是我要找的。对于提示和编辑示例,我将在我的问题中添加我的解决方案:)请查看我的解决方案,以及许多TNX,以获得您的建议。和平:)我只想说谢谢你写了这么详细的答案。
    // again just change the vale of active scene to the scene you wish to change to
    
    // button 1 value will be something like this:
    stackoverflow.webgl.activeScene = stackoverflow.webgl.scene.test;
    
    // button 2 value will takes us back to scene 1
    stackoverflow.webgl.activeScene = stackoverflow.webgl.scene.default;