summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaviya Vivekkumar Dineshbhai <vivek.javiya@collabora.com>2024-07-01 15:41:04 +0530
committerSzymon Kłos <szymon.klos@collabora.com>2024-07-03 23:26:36 +0200
commit776a0116b77175bf416625dc2a6913fdc8bcea19 (patch)
treed4752fb1253509ea62dd63d2014a87bfb2fd24b1
parentConvert SlideShowPresenter to TS (diff)
downloadonline-776a0116b77175bf416625dc2a6913fdc8bcea19.tar.gz
online-776a0116b77175bf416625dc2a6913fdc8bcea19.zip
Add 2d Fade transition
Signed-off-by: Javiya Vivekkumar Dineshbhai <vivek.javiya@collabora.com> Change-Id: I4745b6e8d747e68cc8e0264a534ba9bf87d90df8
-rw-r--r--browser/Makefile.am4
-rw-r--r--browser/src/slideshow/transition/FadeTransition.ts104
-rw-r--r--browser/src/slideshow/transition/Transition2d.ts225
-rw-r--r--browser/src/slideshow/transition/shader/2dVertexShader.glsl9
-rw-r--r--browser/src/slideshow/transition/shader/fadeFragmentShader.glsl36
5 files changed, 378 insertions, 0 deletions
diff --git a/browser/Makefile.am b/browser/Makefile.am
index b9895112e7..0c1769a364 100644
--- a/browser/Makefile.am
+++ b/browser/Makefile.am
@@ -411,6 +411,8 @@ COOL_JS_LST =\
src/control/Ruler.js \
src/control/VRuler.ts \
src/slideshow/SlideShowPresenter.ts \
+ src/slideshow/transition/Transition2d.ts \
+ src/slideshow/transition/FadeTransition.ts \
src/dom/PosAnimation.js \
src/map/anim/Map.PanAnimation.js \
src/dom/PosAnimation.Timer.js \
@@ -844,6 +846,8 @@ pot:
src/control/jsdialog/Widget.Timefield.js \
src/control/jsdialog/Widget.TreeView.js \
src/slideshow/SlideShowPresenter.ts \
+ src/slideshow/transition/Transition2d.ts \
+ src/slideshow/transition/FadeTransition.ts \
src/core/Socket.js \
src/core/Debug.js \
src/docstate.js \
diff --git a/browser/src/slideshow/transition/FadeTransition.ts b/browser/src/slideshow/transition/FadeTransition.ts
new file mode 100644
index 0000000000..06ae6f132f
--- /dev/null
+++ b/browser/src/slideshow/transition/FadeTransition.ts
@@ -0,0 +1,104 @@
+/*
+ * Copyright the Collabora Online contributors.
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+class FadeTransition extends Transition2d {
+ private effectTransition: number = 0;
+ constructor(
+ canvas: HTMLCanvasElement,
+ vertexShaderSource: string,
+ fragmentShaderSource: string,
+ image1: HTMLImageElement,
+ image2: HTMLImageElement,
+ ) {
+ super(canvas, vertexShaderSource, fragmentShaderSource, image1, image2);
+ this.prepareTransition();
+ this.animationTime = 1500;
+ }
+
+ public renderUniformValue(): void {
+ this.gl.uniform1i(
+ this.gl.getUniformLocation(this.program, 'effectType'),
+ this.effectTransition,
+ );
+ }
+
+ public start(selectedEffectType: number): void {
+ this.effectTransition = selectedEffectType;
+ this.startTransition();
+ }
+}
+
+app.definitions.FadeTransition = function () {
+ const canvas = document.getElementById(
+ 'fullscreen-canvas',
+ ) as HTMLCanvasElement;
+ const vertexShaderSource = `#version 300 es
+in vec4 a_position;
+in vec2 a_texCoord;
+out vec2 v_texCoord;
+
+void main() {
+ gl_Position = a_position;
+ v_texCoord = a_texCoord;
+}
+`;
+
+ const fragmentShaderSource = `#version 300 es
+precision mediump float;
+
+uniform sampler2D leavingSlideTexture;
+uniform sampler2D enteringSlideTexture;
+uniform float time;
+uniform int effectType; // 0: Fade through black, 1: Fade through white, 2: Smooth fade
+
+in vec2 v_texCoord;
+out vec4 outColor;
+
+void main() {
+ vec4 color0 = texture(leavingSlideTexture, v_texCoord);
+ vec4 color1 = texture(enteringSlideTexture, v_texCoord);
+ vec4 transitionColor;
+
+ if (effectType == 0) {
+ // Fade through black
+ transitionColor = vec4(0.0, 0.0, 0.0, 1.0);
+ } else if (effectType == 1) {
+ // Fade through white
+ transitionColor = vec4(1.0, 1.0, 1.0, 1.0);
+ }
+
+ if (effectType == 2) {
+ // Smooth fade
+ float smoothTime = smoothstep(0.0, 1.0, time);
+ outColor = mix(color0, color1, smoothTime);
+ } else {
+ if (time < 0.5) {
+ outColor = mix(color0, transitionColor, time * 2.0);
+ } else {
+ outColor = mix(transitionColor, color1, (time - 0.5) * 2.0);
+ }
+ }
+}`;
+
+ const image1 = new Image();
+ const image2 = new Image();
+ console.log("I'm in fade function");
+
+ image1.src = 'images/columnline_52x60.svg';
+ image2.src = 'images/columnline_52x60.svg';
+
+ return new FadeTransition(
+ canvas,
+ vertexShaderSource,
+ fragmentShaderSource,
+ image1,
+ image2,
+ );
+};
diff --git a/browser/src/slideshow/transition/Transition2d.ts b/browser/src/slideshow/transition/Transition2d.ts
new file mode 100644
index 0000000000..c1027d8c60
--- /dev/null
+++ b/browser/src/slideshow/transition/Transition2d.ts
@@ -0,0 +1,225 @@
+/*
+ * Copyright the Collabora Online contributors.
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+class Transition2d {
+ public canvas: HTMLCanvasElement;
+ public gl: WebGL2RenderingContext;
+ public program: WebGLProgram;
+ public animationTime: number = 1500;
+ private vao!: WebGLVertexArrayObject | null;
+ private textures: WebGLTexture[];
+ private time: number;
+ private startTime: number | null;
+
+ constructor(
+ canvas: HTMLCanvasElement,
+ vertexShaderSource: string,
+ fragmentShaderSource: string,
+ image1: HTMLImageElement,
+ image2: HTMLImageElement,
+ ) {
+ this.canvas = canvas;
+ this.gl = this.canvas.getContext('webgl2') as WebGL2RenderingContext;
+ if (!this.gl) {
+ console.error('WebGL2 not supported');
+ throw new Error('WebGL2 not supported');
+ }
+
+ const vertexShader = this.createShader(
+ this.gl.VERTEX_SHADER,
+ vertexShaderSource,
+ );
+ const fragmentShader = this.createShader(
+ this.gl.FRAGMENT_SHADER,
+ fragmentShaderSource,
+ );
+ this.program = this.createProgram(vertexShader, fragmentShader);
+
+ this.textures = this.loadTextures([image1, image2]);
+ this.time = 0;
+ this.startTime = null;
+ }
+
+ public prepareTransition(): void {
+ this.initBuffers();
+ this.initUniforms();
+ }
+
+ public startTransition(): void {
+ this.startTime = performance.now();
+ requestAnimationFrame(this.render.bind(this));
+ }
+
+ public initBuffers(): void {
+ const positions = new Float32Array([
+ -1.0, -1.0, 0, 0, 1, 1.0, -1.0, 0, 1, 1, -1.0, 1.0, 0, 0, 0, 1.0, 1.0, 0,
+ 1, 0,
+ ]);
+
+ const buffer = this.gl.createBuffer();
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
+ this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.STATIC_DRAW);
+
+ this.vao = this.gl.createVertexArray();
+ this.gl.bindVertexArray(this.vao);
+
+ const positionLocation = this.gl.getAttribLocation(
+ this.program,
+ 'a_position',
+ );
+ const texCoordLocation = this.gl.getAttribLocation(
+ this.program,
+ 'a_texCoord',
+ );
+
+ this.gl.enableVertexAttribArray(positionLocation);
+ this.gl.vertexAttribPointer(
+ positionLocation,
+ 3,
+ this.gl.FLOAT,
+ false,
+ 5 * 4,
+ 0,
+ );
+
+ this.gl.enableVertexAttribArray(texCoordLocation);
+ this.gl.vertexAttribPointer(
+ texCoordLocation,
+ 2,
+ this.gl.FLOAT,
+ false,
+ 5 * 4,
+ 3 * 4,
+ );
+ }
+
+ public initUniforms(): void {
+ this.gl.useProgram(this.program);
+ }
+
+ public render(): void {
+ if (!this.startTime) this.startTime = performance.now();
+ this.time =
+ (performance.now() - this.startTime) /
+ (this.animationTime > 0 ? this.animationTime : 1500);
+
+ this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
+ this.gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ this.gl.clear(this.gl.COLOR_BUFFER_BIT);
+
+ this.gl.useProgram(this.program);
+ this.gl.uniform1f(
+ this.gl.getUniformLocation(this.program, 'time'),
+ this.time,
+ );
+
+ this.gl.activeTexture(this.gl.TEXTURE0);
+ this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures[0]);
+ this.gl.uniform1i(
+ this.gl.getUniformLocation(this.program, 'leavingSlideTexture'),
+ 0,
+ );
+
+ this.gl.activeTexture(this.gl.TEXTURE1);
+ this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures[1]);
+ this.gl.uniform1i(
+ this.gl.getUniformLocation(this.program, 'enteringSlideTexture'),
+ 1,
+ );
+
+ this.renderUniformValue();
+
+ this.gl.bindVertexArray(this.vao);
+ this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
+
+ if (this.time < 1) {
+ requestAnimationFrame(this.render.bind(this));
+ } else {
+ console.log('Transition completed');
+ }
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
+ public renderUniformValue(): void {}
+
+ private loadTextures(images: HTMLImageElement[]): WebGLTexture[] {
+ return images.map((image, index) => {
+ const texture = this.gl.createTexture();
+ if (!texture) {
+ throw new Error('Failed to create texture');
+ }
+ this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
+ this.gl.texImage2D(
+ this.gl.TEXTURE_2D,
+ 0,
+ this.gl.RGBA,
+ this.gl.RGBA,
+ this.gl.UNSIGNED_BYTE,
+ image,
+ );
+ this.gl.texParameteri(
+ this.gl.TEXTURE_2D,
+ this.gl.TEXTURE_MIN_FILTER,
+ this.gl.LINEAR,
+ );
+ this.gl.texParameteri(
+ this.gl.TEXTURE_2D,
+ this.gl.TEXTURE_WRAP_S,
+ this.gl.CLAMP_TO_EDGE,
+ );
+ this.gl.texParameteri(
+ this.gl.TEXTURE_2D,
+ this.gl.TEXTURE_WRAP_T,
+ this.gl.CLAMP_TO_EDGE,
+ );
+ console.log(`Texture ${index + 1} loaded:`, image.src);
+ return texture;
+ });
+ }
+
+ public createShader(type: number, source: string): WebGLShader {
+ const shader = this.gl.createShader(type);
+ if (!shader) {
+ throw new Error('Failed to create shader');
+ }
+ this.gl.shaderSource(shader, source);
+ this.gl.compileShader(shader);
+ if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
+ const info = this.gl.getShaderInfoLog(shader);
+ this.gl.deleteShader(shader);
+ throw new Error(`Could not compile shader: ${info}`);
+ }
+ console.log(
+ 'Shader compiled successfully:',
+ type === this.gl.VERTEX_SHADER ? 'VERTEX' : 'FRAGMENT',
+ );
+ return shader;
+ }
+
+ public createProgram(
+ vertexShader: WebGLShader,
+ fragmentShader: WebGLShader,
+ ): WebGLProgram {
+ const program = this.gl.createProgram();
+ if (!program) {
+ throw new Error('Failed to create program');
+ }
+ this.gl.attachShader(program, vertexShader);
+ this.gl.attachShader(program, fragmentShader);
+ this.gl.linkProgram(program);
+ if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
+ const info = this.gl.getProgramInfoLog(program);
+ this.gl.deleteProgram(program);
+ throw new Error(`Could not link program: ${info}`);
+ }
+ console.log('Program linked successfully');
+ return program;
+ }
+}
diff --git a/browser/src/slideshow/transition/shader/2dVertexShader.glsl b/browser/src/slideshow/transition/shader/2dVertexShader.glsl
new file mode 100644
index 0000000000..9254aefe3f
--- /dev/null
+++ b/browser/src/slideshow/transition/shader/2dVertexShader.glsl
@@ -0,0 +1,9 @@
+#version 300 es
+in vec4 a_position;
+in vec2 a_texCoord;
+out vec2 v_texCoord;
+
+void main() {
+ gl_Position = a_position;
+ v_texCoord = a_texCoord;
+}
diff --git a/browser/src/slideshow/transition/shader/fadeFragmentShader.glsl b/browser/src/slideshow/transition/shader/fadeFragmentShader.glsl
new file mode 100644
index 0000000000..1e5e47ae49
--- /dev/null
+++ b/browser/src/slideshow/transition/shader/fadeFragmentShader.glsl
@@ -0,0 +1,36 @@
+#version 300 es
+precision mediump float;
+
+uniform sampler2D leavingSlideTexture;
+uniform sampler2D enteringSlideTexture;
+uniform float time;
+uniform int effectType; // 0: Fade through black, 1: Fade through white, 2: Smooth fade
+
+in vec2 v_texCoord;
+out vec4 outColor;
+
+void main() {
+ vec4 color0 = texture(leavingSlideTexture, v_texCoord);
+ vec4 color1 = texture(enteringSlideTexture, v_texCoord);
+ vec4 transitionColor;
+
+ if (effectType == 0) {
+ // Fade through black
+ transitionColor = vec4(0.0, 0.0, 0.0, 1.0);
+ } else if (effectType == 1) {
+ // Fade through white
+ transitionColor = vec4(1.0, 1.0, 1.0, 1.0);
+ }
+
+ if (effectType == 2) {
+ // Smooth fade
+ float smoothTime = smoothstep(0.0, 1.0, time);
+ outColor = mix(color0, color1, smoothTime);
+ } else {
+ if (time < 0.5) {
+ outColor = mix(color0, transitionColor, time * 2.0);
+ } else {
+ outColor = mix(transitionColor, color1, (time - 0.5) * 2.0);
+ }
+ }
+}