我正在尝试在名为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)
}
})
`