AFrame在自定义组件中包含自定义着色器

时间:2020-05-11 03:40:07

标签: three.js shader aframe vimeo vimeo-api

我正在尝试在名为aframe-vimeo-component的自定义组件(2)内应用以下自定义着色器(1),称为aframe-chromakey-material。

着色器使视频的绿色部分透明(并与普通视频源一起使用)。 该组件从Vimeo加载视频。

基于自定义组件创建实体,然后将自定义着色器用作材质不起作用。

是否可以将自定义着色器直接包含到自定义组件中?

在下面的代码中,我尝试添加行

child.material.shader =抠像

将自定义着色器应用于Vimeo组件的videoTexture,但这不起作用。

`/* global THREE, AFRAME */
const Vimeo = require('./../ext/vimeo-threejs-player/dist/vimeo-threejs-player.min')

// (1) Chromakey Shader

AFRAME.registerShader('chromakey', {
  schema: {
    src: {type: 'map'},
    color: {default: {x: 0.1, y: 0.9, z: 0.2}, type: 'vec3', is: 'uniform'},
    transparent: {default: true, is: 'uniform'}
  },

  init: function (data) {
    var videoTexture = new THREE.VideoTexture(data.src)
    videoTexture.minFilter = THREE.LinearFilter
    this.material = new THREE.ShaderMaterial({
      uniforms: {
        color: {
          type: 'c',
          value: data.color
        },
        texture: {
          type: 't',
          value: videoTexture
        }
      },
      vertexShader: this.vertexShader,
      fragmentShader: this.fragmentShader
    })
  },

  update: function (data) {
    this.material.color = data.color
    this.material.src = data.src
    this.material.transparent = data.transparent
  },

  vertexShader: [
    'varying vec2 vUv;',
    'void main(void)',
    '{',
    'vUv = uv;',
    'vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );',
    'gl_Position = projectionMatrix * mvPosition;',
    '}'
  ].join('\n'),

  fragmentShader: [
    'uniform sampler2D texture;',
    'uniform vec3 color;',
    'varying vec2 vUv;',
    'void main(void)',
    '{',
    'vec3 tColor = texture2D( texture, vUv ).rgb;',
    'float a = (length(tColor - color) - 0.5) * 7.0;',
    'gl_FragColor = vec4(tColor, a);',
    '}'
  ].join('\n')
})

// (2) Vimeo Component

AFRAME.registerComponent('vimeo', {
  multiple: true,
  schema: {
    id: { type: 'number', default: 0 },
    autoplay: { type: 'bool', default: true },
    autoload: { type: 'bool', default: true },
    muted: { type: 'bool', default: false },
    loop: { type: 'bool', default: true },
    volume: { type: 'number', default: 1.0 },
    leftEye: { type: 'selector' },
    rightEye: { type: 'selector' },
    quality: { type: 'string', default: 'auto' }
  },
  init: function () {
    if (this.data.leftEye && this.data.rightEye) {
      this.isStereoSpherical = true
    }

    this.player = new Vimeo.Player(this.data.id, {
      autoplay: this.data.autoplay,
      autoload: this.data.autoload,
      muted: this.data.muted,
      loop: this.data.loop,
      quality: this.data.quality
    })

    // Once the video loads iterate over all objects nested under the <a-entity vimeo /> and assign the textures
    this.player.on('videoLoad', function (videoTexture) {
      this.player.setVolume(this.data.volume)
      if (this.isStereoSpherical) {
        // Create and configure the spheres for stereo webvr
        this.createAndAppendStereoSpheresToElement(this.data.leftEye, this.data.rightEye)
        this.traverseAndSetVideoTextures(this.data.leftEye.object3D, videoTexture)
        this.traverseAndSetVideoTextures(this.data.rightEye.object3D, videoTexture)
      } else {
        this.traverseAndSetVideoTextures(this.el.object3D, videoTexture)
      }
    }.bind(this))
  },
  load: function () {
    if (this.player) {
      this.player.load()
    }
  },
  play: function () {
    if (this.player.video.isLoaded()) {
      if (this.player.isPaused()) {
        this.player.play()
      }
    }
  },
  pause: function () {
    if (this.player.video.isLoaded()) {
      if (this.player.isPlaying()) {
        this.player.pause()
      }
    }
  },
  stop: function () {
    if (this.player.video.isLoaded()) {
      if (this.player.isPlaying()) {
        this.player.stop()
      }
    }
  },
  traverseAndSetVideoTextures: function (object, tex) {
    object.traverse(function (child) {
      if (child instanceof THREE.Mesh) {
        child.material.color = null
        child.material.shader = chromakey
        child.material.map = tex
        child.material.needsUpdate = true
      }
    })
  },
  traverseAndRemoveChildMeshes: function (object) {
    object.traverse(function (child) {
      if (child instanceof THREE.Mesh) {
        object.remove(child)
      }
    })
  },
  createAndAppendStereoSpheresToElement: function (leftEyeElm, rightEyeElm) {
    // If there is pre-existing geomtery in the eye components get rid of it, we will generate it
    if (leftEyeElm.object3D.children.length > 0) {
      this.traverseAndRemoveChildMeshes(leftEyeElm.object3D)
    }
    if (rightEyeElm.object3D.children.length > 0) {
      this.traverseAndRemoveChildMeshes(rightEyeElm.object3D)
    }

    // Build custom geomtery with split UVs for each eye
    var geometry = new THREE.SphereBufferGeometry(500, 60, 40)
    var material = new THREE.MeshBasicMaterial()

    // Left eye sphere
    geometry.scale(-1, 1, 1)
    var uvs = geometry.attributes.uv.array
    for (var i = 0; i < uvs.length; i += 2) {
      uvs[ i + 1 ] *= 0.5
    }
    var mesh = new THREE.Mesh(geometry, material)
    mesh.rotation.y = -Math.PI / 2
    leftEyeElm.object3D.add(mesh)
    leftEyeElm.object3D.layers.set(1)

    // Right eye sphere
    geometry = new THREE.SphereBufferGeometry(500, 60, 40)
    geometry.scale(-1, 1, 1)
    uvs = geometry.attributes.uv.array
    for (var j = 0; j < uvs.length; j += 2) {
      uvs[ j + 1 ] *= 0.5
      uvs[ j + 1 ] += 0.5
    }
    mesh = new THREE.Mesh(geometry, material)
    mesh.rotation.y = -Math.PI / 2
    rightEyeElm.object3D.add(mesh)
    rightEyeElm.object3D.layers.set(2)
  }
})
`

0 个答案:

没有答案
相关问题