【问题标题】:Create a simplified reflective custom shader in A-FRAME在 A-FRAME 中创建简化的反射自定义着色器
【发布时间】:2017-02-09 16:00:05
【问题描述】:

所以我不可避免地走上了 A-FRAME 中自定义着色器的道路。在真正研究这个时,考虑到我可以被认为是这项技术的新手,我遇到了各种复杂且不太清晰的解决方案。

例如:https://rawgit.com/mrdoob/three.js/master/examples/webgl_materials_cubemap_balls_reflection.html,创建的问题比答案更多。

但是,当我访问此示例时:https://stemkoski.github.io/Three.js/Reflection.html,我确实注意到了一种不同的方法,它似乎更简化了一些。

这让我进一步研究了 CubeCameras 以及threejs 如何将其用作着色器以模拟反射率。

//Create cube camera
var cubeCamera = new THREE.CubeCamera( 1, 100000, 128 );
scene.add( cubeCamera );

//Create car
var chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeCamera.renderTarget } );
var car = new Mesh( carGeometry, chromeMaterial );
scene.add( car );

//Update the render target cube
car.setVisible( false );
cubeCamera.position.copy( car.position );
cubeCamera.updateCubeMap( renderer, scene );

//Render the scene
car.setVisible( true );
renderer.render( scene, camera );

现在的问题是,我怎样才能将其转化为 A-FRAME?我尝试了以下方法:

AFRAME.registerComponent('chromeThing', {
      schema: {
        ???
      },

      init: function () {
        var el = this.el;  // Entity.
        var cubeCam = document.querySelector('#cubeCam'); //There is an <a-entity camera id="cubeCam">
        var mirrorCubeMaterial = new THREE.MeshBasicMaterial( { envMap: cubeCam.renderTarget } );
        mirrorCube = new THREE.Mesh( el, mirrorCubeMaterial );

        el.setObject3D('mesh', mirrorCube);
      }
    });

您可能会注意到,我不确定这是什么方案。 另外,这应该是着色器还是组件? (我怎样才能最好地使用它)

编辑: 在@ngokevin 回复之后,我想出了这段代码,但仍然没有给我想要的结果。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Chrome box</title>
    <meta name="description" content="Physically-Based Materials - A-Frame">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <script src="https://aframe.io/releases/0.3.0/aframe.min.js"></script>
    <script src="https://rawgit.com/ngokevin/kframe/master/dist/kframe.min.js"></script>
    <script src="https://rawgit.com/ngokevin/kframe/master/components/reverse-look-controls/index.js"></script>
  </head>
  <body>
    <a-scene>
      <a-assets>
        <img id="equi1" crossorigin  src="https://rawgit.com/aframevr/aframe/master/examples/boilerplate/panorama/puydesancy.jpg" preload="auto">
      </a-assets>
        <!-- MAIN CAMERA -->
        <a-entity id="mainCam" camera="userHeight: 1.6" reverse-look-controls wasd-controls></a-entity>

        <!-- CMAERA FOR TEXTURE (?) -->
        <a-entity id="cubecamera" camera near="0.1" far="5000" fov="512"></a-entity>

        <!-- SKY DOME TO REFLECT ON BOX -->
        <a-sky src="#equi1"></sky>

        <!-- MAKE THIS BOX CHROME -->
        <a-box id="theCube" camera-envmap-material="#cubecamera" color="tomato" depth="2" height="4" width="5" position="0 0 -3" materials=""></a-box> 
        <!-- THIS BOX IS MOVING AND SHOULD REFLECT ON THE CHROME BOX -->
        <a-box id="reflector" color="red" position="0 0 20">
          <a-animation attribute="rotation" dur="10000" fill="forwards" to="0 360 0" repeat="indefinite"></a-animation>
        </a-box>
    </a-scene>
  </body>

 <script>

AFRAME.registerComponent('camera-envmap-material', {
  dependencies: ['material'],

  // Selector type so we do `<a-entity camera-envmap-material="#cubecamera">`.
  schema: {
    type: 'selector'
  },

  init: function () {
    var cameraEl = this.data;
    var material = this.el.getObject3D('mesh').material;

    // Set envmap on existing material.
    // This assumes you have a CubeCamera component that does `setObject3D('cube-camera', new THREE.CubeCamera)`.

    material.envMap = cameraEl.getObject3D('camera').renderTarget;
    material.needsUpdate = true;
  }
});

  </script>
</html>

更新 #2

根据@ngokevin 的建议,这里是我所在的位置,但是,我无法更新组件。问题似乎是将变量传递给tick:function(),我不断收到Uncaught TypeError: Cannot read property 'renderTarget' of undefined

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Chrome box</title>
    <meta name="description" content="Physically-Based Materials - A-Frame">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <script src="https://aframe.io/releases/0.3.0/aframe.min.js"></script>
    <script src="https://rawgit.com/ngokevin/kframe/master/dist/kframe.min.js"></script>
    <script src="https://rawgit.com/ngokevin/kframe/master/components/reverse-look-controls/index.js"></script>
  </head>
  <body>
<a-scene>
      <a-assets>
        <img id="equi1" crossorigin src="https://rawgit.com/aframevr/aframe/master/examples/boilerplate/panorama/puydesancy.jpg" preload="auto">
      </a-assets>
        <!-- MAIN CAMERA -->
        <a-entity id="mainCam" camera="userHeight: 1.6" reverse-look-controls wasd-controls></a-entity>

        <!-- SKY DOME TO REFLECT ON BOX -->
        <a-sky src="#equi1"></sky>

        <!-- MAKE THIS BOX CHROME -->
        <a-box id="theCube" camera-envmap-material depth="2" height="4" width="5" position="0 0 -3" metalness="1">
        </a-box>
        <!-- MAKE THIS ROTATE AND REFLECT ON CHROME --> 
        <a-box id="reflector" color="red" position="0 0 10">
        <a-animation attribute="rotation" dur="10000" fill="forwards" to="0 360 0" repeat="indefinite"></a-animation>
        </a-box>
     </a-scene>
  </body>

 <script>
AFRAME.registerComponent('camera-envmap-material', {
  dependencies: ['material'],

  init: function(data) {
    this.cameraEl = this.data;
    this.material = this.el.getObject3D('mesh').material;
    this.theElement = this.el;
    this.theScene = this.theElement.sceneEl;

    if (!this.theScene.renderStarted) {
      this.theScene.addEventListener('renderstart', this.init.bind(this));
      return;
    }
    this.cubeCamera = new THREE.CubeCamera( 0.1, 5000, 512);
    this.cubeCamera.position.set(5, 2, 4);
    this.cubeCamera.updateCubeMap( this.theScene.renderer, this.theScene.object3D );
    this.theElement.setObject3D('cube-camera', this.cubeCamera);
    this.material.envMap = this.cubeCamera.renderTarget;
    this.material.needsUpdate = true;
  },
  tick:function(){
    this.material.envMap = this.cubeCamera.renderTarget;
    this.material.needsUpdate = true;
  }
});
  </script>
</html>

【问题讨论】:

    标签: webgl shader aframe webvr


    【解决方案1】:

    组件可以在现有材料上设置属性。着色器更多用于注册着色器/材质,但 A-Frame 已经具有基本/标准材质。并且您想要架构中的选择器属性。:

    AFRAME.registerComponent('camera-envmap-material', {
      dependencies: ['material'],
    
      // Selector type so we do `<a-entity camera-envmap-material="#cubecamera">`.
      schema: {
        type: 'selector'
      },
    
      init: function () {
        var cameraEl = this.data;
        var material = this.el.getObject3D('mesh').material;
    
        // Set envmap on existing material.
        // This assumes you have a CubeCamera component that does `setObject3D('cube-camera', new THREE.CubeCamera)`.
    
        material.envMap = cameraEl.getObject3D('camera').renderTarget;
        material.needsUpdate = true;
      }
    });
    

    更新

    AFRAME.registerComponent('camera-envmap-material', {
      dependencies: ['material'],
    
      init: function () {
        var cameraEl = this.data;
        var material = this.el.getObject3D('mesh').material;
    
        if (!this.el.sceneEl.renderStarted) {
          this.el.sceneEl.addEventListener('renderstart', this.init.bind(this));
          return;
        }
    
          var cubeCamera = new THREE.CubeCamera( 1, 100000, 128 );
        cubeCamera.position.set(5, 2, 4);
        cubeCamera.updateCubeMap( this.el.sceneEl.renderer, this.el.sceneEl.object3D );
        this.el.setObject3D('cube-camera', cubeCamera);
        material.envMap = cubeCamera.renderTarget;
        material.needsUpdate = true;
      }
    });
    

    【讨论】:

    • 感谢@ngokevin,我已经编辑了我的原始帖子以显示完整的代码。我在控制台中没有收到任何错误,但该框仍然没有使用 chrome 进行纹理化。关于这里缺少什么的任何想法。
    • 这似乎是我搞砸的地方:“这假设你有一个 CubeCamera 组件,它执行setObject3D('cube-camera', new THREE.CubeCamera)。”
    • 是的,这或多或少是代码的结构/骨架,你需要填写一些东西,比如创建一个 CubeCamera 组件(或者在组件中创建一个,如果这也是现在很多)。
    • codepen.io? codepen.io/jonalex/pen/ORxjJk 我添加了 var camera = new THREE.CubeCamera(1, 100000, 128);到 init(),但不确定如何将其实际添加到场景中并在您提供的组件中使用它。
    • codepen.io/team/mozvr/pen/bwoAAz 我有点搞定了。您使用el.setObject3D 添加到场景中。还必须等待渲染器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 2018-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    相关资源
    最近更新 更多