diff options
Diffstat (limited to 'chromium/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/video.js')
-rw-r--r-- | chromium/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/video.js | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/chromium/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/video.js b/chromium/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/video.js new file mode 100644 index 00000000000..50ed9d91250 --- /dev/null +++ b/chromium/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/video.js @@ -0,0 +1,145 @@ +// Copyright 2018 The Immersive Web Community Group +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +/* +Node for displaying 2D or stereo videos on a quad. +*/ + +import {Material} from '../core/material.js'; +import {Primitive, PrimitiveAttribute} from '../core/primitive.js'; +import {Node} from '../core/node.js'; +import {VideoTexture} from '../core/texture.js'; + +const GL = WebGLRenderingContext; // For enums + +class VideoMaterial extends Material { + constructor() { + super(); + + this.image = this.defineSampler('diffuse'); + + this.texCoordScaleOffset = this.defineUniform('texCoordScaleOffset', + [1.0, 1.0, 0.0, 0.0, + 1.0, 1.0, 0.0, 0.0], 4); + } + + get materialName() { + return 'VIDEO_PLAYER'; + } + + get vertexSource() { + return ` + uniform int EYE_INDEX; + uniform vec4 texCoordScaleOffset[2]; + attribute vec3 POSITION; + attribute vec2 TEXCOORD_0; + varying vec2 vTexCoord; + + vec4 vertex_main(mat4 proj, mat4 view, mat4 model) { + vec4 scaleOffset = texCoordScaleOffset[EYE_INDEX]; + vTexCoord = (TEXCOORD_0 * scaleOffset.xy) + scaleOffset.zw; + vec4 out_vec = proj * view * model * vec4(POSITION, 1.0); + return out_vec; + }`; + } + + get fragmentSource() { + return ` + uniform sampler2D diffuse; + varying vec2 vTexCoord; + + vec4 fragment_main() { + return texture2D(diffuse, vTexCoord); + }`; + } +} + +export class VideoNode extends Node { + constructor(options) { + super(); + + this._video = options.video; + this._displayMode = options.displayMode || 'mono'; + + this._video_texture = new VideoTexture(this._video); + } + + get aspectRatio() { + let width = this._video.videoWidth; + let height = this._video.videoHeight; + + switch (this._displayMode) { + case 'stereoTopBottom': height *= 0.5; break; + case 'stereoLeftRight': width *= 0.5; break; + } + + if (!height || !width) { + return 1; + } + + return width / height; + } + + onRendererChanged(renderer) { + let vertices = [ + -1.0, 1.0, 0.0, 0.0, 0.0, + 1.0, 1.0, 0.0, 1.0, 0.0, + 1.0, -1.0, 0.0, 1.0, 1.0, + -1.0, -1.0, 0.0, 0.0, 1.0, + ]; + let indices = [ + 0, 2, 1, + 0, 3, 2, + ]; + + let vertexBuffer = renderer.createRenderBuffer(GL.ARRAY_BUFFER, new Float32Array(vertices)); + let indexBuffer = renderer.createRenderBuffer(GL.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices)); + + let attribs = [ + new PrimitiveAttribute('POSITION', vertexBuffer, 3, GL.FLOAT, 20, 0), + new PrimitiveAttribute('TEXCOORD_0', vertexBuffer, 2, GL.FLOAT, 20, 12), + ]; + + let primitive = new Primitive(attribs, indices.length); + primitive.setIndexBuffer(indexBuffer); + primitive.setBounds([-1.0, -1.0, 0.0], [1.0, 1.0, 0.015]); + + let material = new VideoMaterial(); + material.image.texture = this._video_texture; + + switch (this._displayMode) { + case 'mono': + material.texCoordScaleOffset.value = [1.0, 1.0, 0.0, 0.0, + 1.0, 1.0, 0.0, 0.0]; + break; + case 'stereoTopBottom': + material.texCoordScaleOffset.value = [1.0, 0.5, 0.0, 0.0, + 1.0, 0.5, 0.0, 0.5]; + break; + case 'stereoLeftRight': + material.texCoordScaleOffset.value = [0.5, 1.0, 0.0, 0.0, + 0.5, 1.0, 0.5, 0.0]; + break; + } + + let renderPrimitive = renderer.createRenderPrimitive(primitive, material); + this.addRenderPrimitive(renderPrimitive); + } +} |