【问题标题】:Toggle between multiple THREE.EffectComposer scenes using the same renderer in three.js在 three.js 中使用相同的渲染器在多个 THREE.EffectComposer 场景之间切换
【发布时间】:2017-05-29 19:11:32
【问题描述】:

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

Two scene example

根据我对作曲家工作原理的理解,您可以创建它的一个实例,然后像这样应用渲染通道:

    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); 

然后像这样应用作曲家渲染:

    this.composer.render();

所以我的问题是,如果我有一个作曲家实例的第二个场景,那么我该怎么做:

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

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    您可以从一个 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();
    

    如果您愿意,您甚至应该能够重用某些渲染通道。

    【讨论】:

    • 我很抱歉没有尽快回复你,谢谢你的例子,我做了一个快速的实现,它通过在效果器中切换场景来工作,正如你提到的我可以使用多个效果器我我只是想通过您的示例来形象化它的外观,但使用效果器的方法对我来说还是全新的。是否可以提供一个小代码 sn-p 来说明它的外观。非常感谢
    • 我不太了解您的用例,因此很难提出有关架构的建议。您可以将作曲家附加到场景对象,因此您只需要切换场景并始终使用activeScene.composer.render() 进行渲染。有关 Effect-Composer 本身的更多详细信息,我建议添加一个单独的问题(另外,也许这会有所帮助:github.com/hughsk/three-effectcomposer
    • 是的,我认为 activeScene.composer 是我正在寻找的。感谢提示并编辑示例,我将在我的问题中添加我的解决方案:)
    • 请看一下我的解决方案,以及许多 tnxs 的建议。和平:)
    【解决方案2】:

    因此,在我开始之前,我只想向 Martin Schuhfuß 大声疾呼,他提供了对此解决方案的见解。

    免责声明

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

    架构

    我在这个例子中使用的是 OOP 方法,你应该能够根据你使用的任何方法来操作解决方案。

    方法

    因此,根据 Martin 当前的示例,您可以看到我们能够将 composer 属性/对象添加到我们的场景对象中,这意味着场景可以继承相同的 composer 效果,这非常棒,但是在我的情况下,我有很多不同的场景作曲家效果,所以我需要重新考虑这个问题。

    1.创建一个 Composer 对象。

    所以我创建了一个对象来放入作曲家对象,并在引用我的效果时保持良好的“作曲家”名称约定。

    This.composer = {};
    

    2。创建一个函数以使用相关场景初始化 RenderPass。

    所以重要的是要记住,在调用我们的作曲家之前,我们需要先定义和初始化 RenderPass。 RenderPasses 允许我们将我们想要的效果属性(知道有着色器)。在我的示例中,我有两个场景,因此我需要创建:

    1. 两个渲染通道。
    2. 一个 RenderPass 复制了场景。
    3. 另一个 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 渲染方法

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

    stackoverflow.webgl.activeScene.composer.render();
    

    请注意,“activecScene”部分参考了当时使用的实际场景。正是这一点让我们可以改变场景。

    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;
    

    结论 这是我实现这种效果的方法,但如果有更好或替代的方法,请加入讨论并分享。

    【讨论】:

    • 只是想说谢谢你写了这么详细的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    • 1970-01-01
    相关资源
    最近更新 更多