mirror of
https://github.com/galacean/engine.git
synced 2026-06-21 19:02:50 +08:00
126 lines
3.0 KiB
TypeScript
126 lines
3.0 KiB
TypeScript
/**
|
|
* @title Video Background
|
|
* @category Video
|
|
* @thumbnail https://mdn.alipayobjects.com/merchant_appfe/afts/img/A*8t0SSqZFaXcAAAAAAAAAAAAADiR2AQ/original
|
|
*/
|
|
import { OrbitControl } from "@galacean/engine-toolkit-controls";
|
|
import {
|
|
BackgroundMode,
|
|
Camera,
|
|
CompareFunction,
|
|
CullMode,
|
|
Engine,
|
|
Material,
|
|
PrimitiveMesh,
|
|
Script,
|
|
Shader,
|
|
Texture2D,
|
|
TextureFormat,
|
|
TextureUsage,
|
|
WebGLEngine,
|
|
} from "@galacean/engine";
|
|
|
|
WebGLEngine.create({ canvas: "canvas" }).then((engine) => {
|
|
engine.canvas.resizeByClientSize();
|
|
const scene = engine.sceneManager.activeScene;
|
|
const rootEntity = scene.createRootEntity();
|
|
const cameraEntity = rootEntity.createChild();
|
|
cameraEntity.transform.setPosition(0, 0, 10);
|
|
const camera = cameraEntity.addComponent(Camera);
|
|
camera.fieldOfView = 80;
|
|
const control = cameraEntity.addComponent(OrbitControl);
|
|
control.autoRotate = true;
|
|
control.autoRotateSpeed = 0.1;
|
|
engine.run();
|
|
|
|
// video skybox
|
|
Shader.create(
|
|
"video",
|
|
`
|
|
attribute vec3 POSITION;
|
|
attribute vec2 TEXCOORD_0;
|
|
varying vec2 v_uv;
|
|
|
|
uniform mat4 camera_VPMat;
|
|
|
|
void main() {
|
|
v_uv = TEXCOORD_0;
|
|
gl_Position = camera_VPMat * vec4( POSITION, 1.0 );
|
|
}
|
|
`,
|
|
`
|
|
uniform sampler2D u_texture;
|
|
varying vec2 v_uv;
|
|
|
|
void main(){
|
|
gl_FragColor = texture2D(u_texture, vec2(-v_uv.x,v_uv.y));
|
|
|
|
}
|
|
`
|
|
);
|
|
class VideoMaterial extends Material {
|
|
constructor(engine: Engine) {
|
|
super(engine, Shader.find("video"));
|
|
|
|
this.renderState.rasterState.cullMode = CullMode.Off;
|
|
this.renderState.depthState.compareFunction = CompareFunction.LessEqual;
|
|
}
|
|
|
|
get texture(): Texture2D {
|
|
return this.shaderData.getTexture("u_texture") as Texture2D;
|
|
}
|
|
|
|
set texture(v: Texture2D) {
|
|
this.shaderData.setTexture("u_texture", v);
|
|
}
|
|
}
|
|
|
|
class UpdateVideoScript extends Script {
|
|
video: HTMLVideoElement;
|
|
texture: Texture2D;
|
|
|
|
onUpdate() {
|
|
this.texture.setImageSource(this.video);
|
|
}
|
|
}
|
|
|
|
const dom: HTMLVideoElement = document.createElement("video");
|
|
const width = 3840;
|
|
const height = 1920;
|
|
dom.src =
|
|
"https://gw.alipayobjects.com/mdn/rms_7c464e/afts/file/A*p_f5QYjE_2kAAAAAAAAAAAAAARQnAQ";
|
|
dom.crossOrigin = "anonymous";
|
|
dom.loop = true;
|
|
dom.muted = true;
|
|
dom.playsInline = true;
|
|
dom.play();
|
|
|
|
// create video background
|
|
const texture = new Texture2D(
|
|
engine,
|
|
width,
|
|
height,
|
|
TextureFormat.R8G8B8,
|
|
false,
|
|
TextureUsage.Dynamic
|
|
);
|
|
const { background } = scene;
|
|
background.mode = BackgroundMode.Sky;
|
|
const skyMaterial = (background.sky.material = new VideoMaterial(engine));
|
|
background.sky.mesh = PrimitiveMesh.createSphere(engine, 2);
|
|
skyMaterial.texture = texture;
|
|
|
|
function updateVideo() {
|
|
texture.setImageSource(dom);
|
|
(dom as any).requestVideoFrameCallback(updateVideo);
|
|
}
|
|
|
|
if ("requestVideoFrameCallback" in dom) {
|
|
(dom as any).requestVideoFrameCallback(updateVideo);
|
|
} else {
|
|
const script = rootEntity.addComponent(UpdateVideoScript);
|
|
script.video = dom;
|
|
script.texture = texture;
|
|
}
|
|
});
|