diff --git a/packages/cloudrun/src/gcpInstaller/gcpInstaller.tar b/packages/cloudrun/src/gcpInstaller/gcpInstaller.tar
index b3bc46eb126..dce63200cf9 100644
Binary files a/packages/cloudrun/src/gcpInstaller/gcpInstaller.tar and b/packages/cloudrun/src/gcpInstaller/gcpInstaller.tar differ
diff --git a/packages/example/package.json b/packages/example/package.json
index 2aec7ba837a..38e3e2d32d3 100644
--- a/packages/example/package.json
+++ b/packages/example/package.json
@@ -21,7 +21,9 @@
"render": "remotion render react-svg",
"render-js": "remotion render src/entry.jsx framer",
"render-gif": "remotion render framer out/video.gif --codec=gif --every-nth-frame=2",
- "render-transparent": "remotion render --image-format=png --pixel-format=yuva420p --codec=vp8 react-svg out/video.webm"
+ "render-transparent": "remotion render --image-format=png --pixel-format=yuva420p --codec=vp8 react-svg out/video.webm",
+ "render-swangle": "remotion render GpuTesting out/swangle.mp4 --gl=swangle",
+ "render-angle": "remotion render GpuTesting out/angle.mp4 --gl=angle"
},
"dependencies": {
"@mdx-js/loader": "^2.3.0",
@@ -54,6 +56,7 @@
"@types/react": "18.0.26",
"@types/styled-components": "^5.1.26",
"@types/web": "0.0.78",
+ "@types/three": "^0.144.0",
"babel-loader": "^8.2.2",
"dotenv": "9.0.2",
"lottie-web": "5.12.2",
diff --git a/packages/example/public/1.mov b/packages/example/public/1.mov
new file mode 100644
index 00000000000..56b796a3b6e
Binary files /dev/null and b/packages/example/public/1.mov differ
diff --git a/packages/example/src/GpuTesting/index.tsx b/packages/example/src/GpuTesting/index.tsx
new file mode 100644
index 00000000000..aad5d1a6b6d
--- /dev/null
+++ b/packages/example/src/GpuTesting/index.tsx
@@ -0,0 +1,124 @@
+import {AbsoluteFill, staticFile, OffthreadVideo} from 'remotion';
+import {loadFont} from '@remotion/google-fonts/PlusJakartaSans';
+import {Scene} from './phone/Scene';
+
+const {fontFamily} = loadFont();
+
+const vid1 = staticFile('/1.mov');
+
+export const GpuTesting = () => {
+ return (
+
+
+ GPU TESTING
+
+
+
+
+
+ Box Shadow:{' '}
+
+
+
+
+
+ Drop Shadow:{' '}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/packages/example/src/GpuTesting/phone/Phone.tsx b/packages/example/src/GpuTesting/phone/Phone.tsx
new file mode 100644
index 00000000000..d94cf4195d6
--- /dev/null
+++ b/packages/example/src/GpuTesting/phone/Phone.tsx
@@ -0,0 +1,117 @@
+import {useThree} from '@react-three/fiber';
+import React, {useEffect, useMemo} from 'react';
+import {interpolate, spring, useCurrentFrame, useVideoConfig} from 'remotion';
+import {
+ CAMERA_DISTANCE,
+ getPhoneLayout,
+ PHONE_CURVE_SEGMENTS,
+ PHONE_SHININESS,
+} from './helpers/layout';
+import {roundedRect} from './helpers/rounded-rectangle';
+import {RoundedBox} from './RoundedBox';
+
+export const Phone: React.FC<{
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ videoTexture: any | null;
+ aspectRatio: number;
+ baseScale: number;
+ phoneColor: string;
+}> = ({aspectRatio, videoTexture, baseScale, phoneColor}) => {
+ const frame = useCurrentFrame();
+ const {fps, durationInFrames} = useVideoConfig();
+
+ const layout = useMemo(
+ () => getPhoneLayout(aspectRatio, baseScale),
+ [aspectRatio, baseScale],
+ );
+
+ // Place a camera and set the distance to the object.
+ // Then make it look at the object.
+ const camera = useThree((state) => state.camera);
+ useEffect(() => {
+ camera.position.set(0, 0, CAMERA_DISTANCE);
+ camera.near = 0.2;
+ camera.far = Math.max(5000, CAMERA_DISTANCE * 2);
+ camera.lookAt(0, 0, 0);
+ }, [camera]);
+
+ // Make the video fill the phone texture
+ useEffect(() => {
+ if (videoTexture) {
+ videoTexture.repeat.y = 1 / layout.screen.height;
+ videoTexture.repeat.x = 1 / layout.screen.width;
+ }
+ }, [aspectRatio, layout.screen.height, layout.screen.width, videoTexture]);
+
+ // During the whole scene, the phone is rotating.
+ // 2 * Math.PI is a full rotation.
+ const constantRotation = interpolate(
+ frame,
+ [0, durationInFrames],
+ [0, Math.PI * 6],
+ );
+
+ // When the composition starts, there is some extra
+ // rotation and translation.
+ const entranceAnimation = spring({
+ frame,
+ fps,
+ config: {
+ damping: 200,
+ mass: 3,
+ },
+ });
+
+ // Calculate the entrance rotation,
+ // doing one full spin
+ const entranceRotation = interpolate(
+ entranceAnimation,
+ [0, 1],
+ [-Math.PI, Math.PI],
+ );
+
+ // Calculating the total rotation of the phone
+ const rotateY = entranceRotation + constantRotation;
+
+ // Calculating the translation of the phone at the beginning.
+ // The start position of the phone is set to 4 "units"
+ const translateY = interpolate(entranceAnimation, [0, 1], [-4, 0]);
+
+ // Calculate a rounded rectangle for the phone screen
+ const screenGeometry = useMemo(() => {
+ return roundedRect({
+ width: layout.screen.width,
+ height: layout.screen.height,
+ radius: layout.screen.radius,
+ });
+ }, [layout.screen.height, layout.screen.radius, layout.screen.width]);
+
+ return (
+
+
+
+
+
+
+ {videoTexture ? (
+
+ ) : null}
+
+
+ );
+};
diff --git a/packages/example/src/GpuTesting/phone/RoundedBox.tsx b/packages/example/src/GpuTesting/phone/RoundedBox.tsx
new file mode 100644
index 00000000000..63e4f9ffb0e
--- /dev/null
+++ b/packages/example/src/GpuTesting/phone/RoundedBox.tsx
@@ -0,0 +1,43 @@
+import React, {useMemo} from 'react';
+import {roundedRect} from './helpers/rounded-rectangle';
+
+type Props = {
+ width: number;
+ height: number;
+ radius: number;
+ curveSegments: number;
+ depth: number;
+} & Omit;
+
+export const RoundedBox: React.FC = ({
+ width,
+ height,
+ radius,
+ curveSegments,
+ children,
+ depth,
+ ...otherProps
+}) => {
+ const shape = useMemo(
+ () => roundedRect({width, height, radius}),
+ [height, radius, width]
+ );
+
+ const params = useMemo(
+ () => ({
+ depth,
+ bevelEnabled: true,
+ bevelSize: 0,
+ bevelThickness: 0,
+ curveSegments,
+ }),
+ [curveSegments, depth]
+ );
+
+ return (
+
+
+ {children}
+
+ );
+};
diff --git a/packages/example/src/GpuTesting/phone/Scene.tsx b/packages/example/src/GpuTesting/phone/Scene.tsx
new file mode 100644
index 00000000000..01eaee44adf
--- /dev/null
+++ b/packages/example/src/GpuTesting/phone/Scene.tsx
@@ -0,0 +1,47 @@
+import {staticFile} from 'remotion';
+import {getVideoMetadata, VideoMetadata} from '@remotion/media-utils';
+import {ThreeCanvas, useVideoTexture} from '@remotion/three';
+import React, {useEffect, useRef, useState} from 'react';
+import {useVideoConfig, Video} from 'remotion';
+import {Phone} from './Phone';
+
+const videoStyle: React.CSSProperties = {
+ position: 'absolute',
+ opacity: 0,
+};
+
+export const Scene: React.FC = () => {
+ const phoneColor = 'rgba(110, 152, 191, 0.00)';
+ const baseScale = 1;
+
+ const videoRef = useRef(null);
+ const {width, height} = useVideoConfig();
+ const [videoData, setVideoData] = useState(null);
+
+ const videoSrc = staticFile('1.mov');
+
+ useEffect(() => {
+ getVideoMetadata(videoSrc)
+ .then((data) => setVideoData(data))
+ .catch((err) => console.log(err));
+ }, [videoSrc]);
+
+ const texture = useVideoTexture(videoRef);
+ return (
+
+
+ {videoData ? (
+
+
+
+
+
+ ) : null}
+
+ );
+};
diff --git a/packages/example/src/GpuTesting/phone/helpers/layout.ts b/packages/example/src/GpuTesting/phone/helpers/layout.ts
new file mode 100644
index 00000000000..6aac2b9cdef
--- /dev/null
+++ b/packages/example/src/GpuTesting/phone/helpers/layout.ts
@@ -0,0 +1,97 @@
+import {Vector3} from '@react-three/fiber';
+
+// The distance from which the camera is pointing to the phone.
+export const CAMERA_DISTANCE = 2.5;
+
+// A small number to avoid z-index flickering
+export const Z_FLICKER_PREVENTION = 0.001;
+
+// Shininess of the phone
+export const PHONE_SHININESS = 30;
+
+// In how many segments the phone rounded corners
+// are divided. Increase number for smoother phone
+export const PHONE_CURVE_SEGMENTS = 8;
+
+// Calculate phone size. Whichever side is smaller gets
+// normalized to the base scale.
+const getPhoneHeight = (aspectRatio: number, baseScale: number): number => {
+ if (aspectRatio > 1) {
+ return baseScale;
+ }
+ return baseScale / aspectRatio;
+};
+
+const getPhoneWidth = (aspectRatio: number, baseScale: number): number => {
+ if (aspectRatio < 1) {
+ return baseScale;
+ }
+ return baseScale * aspectRatio;
+};
+
+type Layout = {
+ position: Vector3;
+ height: number;
+ width: number;
+ radius: number;
+};
+
+type PhoneLayout = {
+ phone: Layout & {
+ thickness: number;
+ bevel: number;
+ };
+ screen: Layout;
+};
+
+export const getPhoneLayout = (
+ // I recommend building the phone layout based
+ // on the aspect ratio of the phone
+ aspectRatio: number,
+ // This value can be increased or decreased to tweak the
+ // base value of the phone.
+ baseScale: number
+): PhoneLayout => {
+ // The depth of the phone body
+ const phoneThickness = baseScale * 0.15;
+
+ // How big the border of the phone is.
+ const phoneBevel = baseScale * 0.04;
+
+ // The inner radius of the phone, aka the screen radius
+ const screenRadius = baseScale * 0.07;
+
+ const phoneHeight = getPhoneHeight(aspectRatio, baseScale);
+ const phoneWidth = getPhoneWidth(aspectRatio, baseScale);
+ const phonePosition: Vector3 = [-phoneWidth / 2, -phoneHeight / 2, 0];
+ const screenWidth = phoneWidth - phoneBevel * 2;
+ const screenHeight = phoneHeight - phoneBevel * 2;
+ const screenPosition: Vector3 = [
+ -screenWidth / 2,
+ -screenHeight / 2,
+ phoneThickness + Z_FLICKER_PREVENTION,
+ ];
+
+ // Define the outer radius of the phone.
+ // It looks better if the outer radius is a bit bigger than the screen radios,
+ // formula taken from https://twitter.com/joshwcomeau/status/134978208002102886
+ const phoneRadius =
+ screenRadius + (getPhoneWidth(aspectRatio, baseScale) - screenWidth) / 2;
+
+ return {
+ phone: {
+ position: phonePosition,
+ height: phoneHeight,
+ width: phoneWidth,
+ radius: phoneRadius,
+ thickness: phoneThickness,
+ bevel: phoneBevel,
+ },
+ screen: {
+ position: screenPosition,
+ height: screenHeight,
+ width: screenWidth,
+ radius: screenRadius,
+ },
+ };
+};
diff --git a/packages/example/src/GpuTesting/phone/helpers/rounded-rectangle.ts b/packages/example/src/GpuTesting/phone/helpers/rounded-rectangle.ts
new file mode 100644
index 00000000000..52e24dc6c30
--- /dev/null
+++ b/packages/example/src/GpuTesting/phone/helpers/rounded-rectangle.ts
@@ -0,0 +1,23 @@
+import {Shape} from 'three';
+
+export function roundedRect({
+ width,
+ height,
+ radius,
+}: {
+ width: number;
+ height: number;
+ radius: number;
+}): Shape {
+ const roundedRectShape = new Shape();
+ roundedRectShape.moveTo(0, radius);
+ roundedRectShape.lineTo(0, height - radius);
+ roundedRectShape.quadraticCurveTo(0, height, radius, height);
+ roundedRectShape.lineTo(width - radius, height);
+ roundedRectShape.quadraticCurveTo(width, height, width, height - radius);
+ roundedRectShape.lineTo(width, radius);
+ roundedRectShape.quadraticCurveTo(width, 0, width - radius, 0);
+ roundedRectShape.lineTo(radius, 0);
+ roundedRectShape.quadraticCurveTo(0, 0, 0, radius);
+ return roundedRectShape;
+}
diff --git a/packages/example/src/Root.tsx b/packages/example/src/Root.tsx
index 6e98c173b89..02438bbae03 100644
--- a/packages/example/src/Root.tsx
+++ b/packages/example/src/Root.tsx
@@ -47,6 +47,7 @@ import {StaticDemo} from './StaticServer';
import {StillZoom} from './StillZoom';
import {TenFrameTester} from './TenFrameTester';
import ThreeBasic from './ThreeBasic';
+import {GpuTesting} from './GpuTesting';
import {VideoOnCanvas} from './VideoOnCanvas';
import {Greenscreen} from './VideoOnCanvas/greenscreen';
import {VideoSpeed} from './VideoSpeed';
@@ -723,6 +724,14 @@ export const Index: React.FC = () => {
fps={30}
durationInFrames={600}
/>
+
{
];
}
+ if (renderer === 'angle') {
+ console.log('altered cmd');
+ return [`--use-gl=angle`, `--use-angle=gl-egl`];
+ }
+
if (renderer === null) {
return [];
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 504f8e1682f..1b7754c9b60 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -761,7 +761,7 @@ importers:
version: 2.3.0(react@18.2.0)
'@react-three/drei':
specifier: 9.79.4
- version: 9.79.4(@react-three/fiber@8.13.5)(@types/three@0.154.0)(react-dom@18.2.0)(react@18.2.0)(three@0.154.0)
+ version: 9.79.4(@react-three/fiber@8.13.5)(@types/three@0.144.0)(react-dom@18.2.0)(react@18.2.0)(three@0.154.0)
'@react-three/fiber':
specifier: 8.13.5
version: 8.13.5(react-dom@18.2.0)(react@18.2.0)(three@0.154.0)
@@ -840,6 +840,9 @@ importers:
'@types/styled-components':
specifier: ^5.1.26
version: 5.1.26
+ '@types/three':
+ specifier: ^0.144.0
+ version: 0.144.0
'@types/web':
specifier: 0.0.78
version: 0.0.78
@@ -7867,7 +7870,7 @@ packages:
resolution: {integrity: sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q==}
dev: false
- /@react-three/drei@9.79.4(@react-three/fiber@8.13.5)(@types/three@0.154.0)(react-dom@18.2.0)(react@18.2.0)(three@0.154.0):
+ /@react-three/drei@9.79.4(@react-three/fiber@8.13.5)(@types/three@0.144.0)(react-dom@18.2.0)(react@18.2.0)(three@0.154.0):
resolution: {integrity: sha512-Qyy2dPTLpEs3XfvLo2Nyneht0hRqIgIjel78A9MUxq3VxbCse79iCFZZ0xD8gIof33L4jfQOrGghKK988orNOA==}
peerDependencies:
'@react-three/fiber': '>=8.0'
@@ -7889,7 +7892,7 @@ packages:
lodash.clamp: 4.0.3
lodash.omit: 4.5.0
lodash.pick: 4.4.0
- maath: 0.6.0(@types/three@0.154.0)(three@0.154.0)
+ maath: 0.6.0(@types/three@0.144.0)(three@0.154.0)
meshline: 3.1.6(three@0.154.0)
react: 18.2.0
react-composer: 5.0.3(react@18.2.0)
@@ -8834,10 +8837,6 @@ packages:
resolution: {integrity: sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==}
dev: true
- /@tweenjs/tween.js@18.6.4:
- resolution: {integrity: sha512-lB9lMjuqjtuJrx7/kOkqQBtllspPIN+96OvTCeJ2j5FEzinoAXTdAMFnDAQT1KVPRlnYfBrqxtqP66vDM40xxQ==}
- dev: false
-
/@types/acorn@4.0.6:
resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==}
dependencies:
@@ -9360,10 +9359,6 @@ packages:
'@types/node': 18.14.6
dev: false
- /@types/stats.js@0.17.0:
- resolution: {integrity: sha512-9w+a7bR8PeB0dCT/HBULU2fMqf6BAzvKbxFboYhmDtDkKPiyXYbjoe2auwsXlEFI7CFNMF1dCv3dFH5Poy9R1w==}
- dev: false
-
/@types/styled-components@5.1.26:
resolution: {integrity: sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==}
dependencies:
@@ -9383,15 +9378,10 @@ packages:
resolution: {integrity: sha512-4YB+99Rgqq27EjiYTItEoZtdjLnTh8W9LxowgpC9eWsjaQJIL4Kn/ZcUKAnW3gB/jS4hqGN8iqmid+RcUZDzpA==}
dev: true
- /@types/three@0.154.0:
- resolution: {integrity: sha512-IioqpGhch6FdLDh4zazRn3rXHj6Vn2nVOziJdXVbJFi9CaI65LtP9qqUtpzbsHK2Ezlox8NtsLNHSw3AQzucjA==}
+ /@types/three@0.144.0:
+ resolution: {integrity: sha512-psvEs6q5rLN50jUYZ3D4pZMfxTbdt3A243blt0my7/NcL6chaCZpHe2csbCtx0SOD9fI/XnF3wnVUAYZGqCSYg==}
dependencies:
- '@tweenjs/tween.js': 18.6.4
- '@types/stats.js': 0.17.0
'@types/webxr': 0.5.2
- fflate: 0.6.10
- lil-gui: 0.17.0
- meshoptimizer: 0.18.1
dev: false
/@types/unist@2.0.6:
@@ -15354,10 +15344,6 @@ packages:
prelude-ls: 1.2.1
type-check: 0.4.0
- /lil-gui@0.17.0:
- resolution: {integrity: sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ==}
- dev: false
-
/lilconfig@2.1.0:
resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
engines: {node: '>=10'}
@@ -15551,13 +15537,13 @@ packages:
resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==}
hasBin: true
- /maath@0.6.0(@types/three@0.154.0)(three@0.154.0):
+ /maath@0.6.0(@types/three@0.144.0)(three@0.154.0):
resolution: {integrity: sha512-dSb2xQuP7vDnaYqfoKzlApeRcR2xtN8/f7WV/TMAkBC8552TwTLtOO0JTcSygkYMjNDPoo6V01jTw/aPi4JrMw==}
peerDependencies:
'@types/three': '>=0.144.0'
three: '>=0.144.0'
dependencies:
- '@types/three': 0.154.0
+ '@types/three': 0.144.0
three: 0.154.0
dev: false
@@ -15910,10 +15896,6 @@ packages:
three: 0.154.0
dev: false
- /meshoptimizer@0.18.1:
- resolution: {integrity: sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==}
- dev: false
-
/methods@1.1.2:
resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
engines: {node: '>= 0.6'}