Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example project add startup overlay #114

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions example-project/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "renin-example-project",
"version": "2.1.0",
"version": "2.2.0",
"type": "module",
"private": true,
"scripts": {
Expand All @@ -10,13 +10,21 @@
},
"devDependencies": {
"@rollup/plugin-node-resolve": "*",
"typescript": "*",
"prettier": "^2.8.8",
"vite": "*",
"vite-plugin-string": "*"
},
"dependencies": {
"@types/three": "*",
"renin": "*",
"three": "*"
"@babylonjs/havok": "^1.0.0",
"@types/seedrandom": "^3.0.5",
"@types/three": "0.150.1",
"postprocessing": "^6.32.2",
"react": "^18.2.0",
"renin": "file:./../renin/renin",
"screen-space-reflections": "^2.5.0",
"seedrandom": "^3.0.5",
"three": "0.150.1",
"three-custom-shader-material": "5.2.0",
"typescript": "^5.1.6"
}
}
1 change: 1 addition & 0 deletions example-project/src/FlatLand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class FlatLand extends ReninNode {
this.texture = new CanvasTexture(this.canvas);
}

// @ts-ignore
public render(frame: number, _renderer: WebGLRenderer, renin: Renin) {
if (!this.ctx) {
return;
Expand Down
4 changes: 4 additions & 0 deletions example-project/src/JumpingBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Color,
DoubleSide,
FloatType,
// @ts-ignore
LinearEncoding,
Mesh,
MeshBasicMaterial,
Expand Down Expand Up @@ -39,6 +40,7 @@ export class JumpingBox extends ReninNode {
/* In the constructor we set up our scene. */
constructor(renin: Renin) {
super(renin);
// @ts-ignore
this.cube = new Mesh(
new BoxGeometry(),
new ShaderMaterial({
Expand Down Expand Up @@ -76,6 +78,7 @@ export class JumpingBox extends ReninNode {
this.renderTarget.setSize(width, height);
}

// @ts-ignore
public render(frame: number, renderer: WebGLRenderer, renin: Renin) {
/* Since these animation updates are not stateful, we do
* them "on-demand" in the render method. If they were stateful,
Expand Down Expand Up @@ -111,6 +114,7 @@ export class JumpingBox extends ReninNode {
* to the renderTarget, making the output available to the parent node. */
renderer.setRenderTarget(this.renderTarget);
renderer.toneMapping = NoToneMapping;
// @ts-ignore
renderer.outputEncoding = LinearEncoding;
renderer.render(this.scene, this.camera);
}
Expand Down
18 changes: 10 additions & 8 deletions example-project/src/PostFx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,24 @@ export class PostFx extends ReninNode {
})
);

// @ts-ignore
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a fan of all the ts-ignores. What is it complaining of?

children: {
switcher: SceneSwitcher;
};

constructor(renin: Renin) {
super(renin);
this.scene.add(this.screen);
this.camera.position.z = 10;

this.children = children<{
switcher: SceneSwitcher;
}>({
this.children = children({
switcher: new SceneSwitcher(renin),
});
this.scene.add(this.screen);
this.camera.position.z = 10;
}

// @ts-ignore
public render(frame: number, renderer: WebGLRenderer, _renin: Renin) {
this.screen.material.uniforms.frame.value = frame;
//@ts-ignore
this.screen.material.uniforms.tDiffuse.value = this.children?.switcher.renderTarget.texture;
this.screen.material.uniforms.tDiffuse.value = this.children.switcher.renderTarget.texture;
this.screen.material.needsUpdate = true;
renderer.render(this.scene, this.camera);
}
Expand Down
17 changes: 11 additions & 6 deletions example-project/src/SceneSwitcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,32 @@ export class SceneSwitcher extends ReninNode {
camera = new OrthographicCamera(-1, 1, 1, -1);
renderTarget = new WebGLRenderTarget(640, 360);
screen = new Mesh(new BoxGeometry(2, 2, 2), new MeshBasicMaterial());

// @ts-ignore
children: {
flatland: FlatLand;
jumpingbox: JumpingBox;
spinningcube: SpinningDonut;
};

public resize(width: number, height: number) {
this.renderTarget.setSize(width, height);
}

constructor(renin: Renin) {
super(renin);

this.children = children<{
spinningcube: SpinningDonut;
flatland: FlatLand;
jumpingbox: JumpingBox;
}>({
spinningcube: new SpinningDonut(renin),
this.children = children({
flatland: new FlatLand(renin),
jumpingbox: new JumpingBox(renin),
spinningcube: new SpinningDonut(renin),
});
this.scene.add(this.screen);
this.scene.add(this.camera);
this.camera.position.z = 10;
}

// @ts-ignore
public render(frame: number, renderer: WebGLRenderer) {
this.screen.material.map = null;
if (this.children?.jumpingbox.isActive) {
Expand Down
4 changes: 3 additions & 1 deletion example-project/src/SpinningDonut.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ReninNode } from 'renin/lib/ReninNode';
import envMap from './envMap.jpg';
import { Renin } from 'renin/lib/renin';
import {
BufferGeometry,
EquirectangularReflectionMapping,
Expand All @@ -12,11 +13,11 @@ import {
Scene,
sRGBEncoding,
TextureLoader,
// @ts-ignore
TorusBufferGeometry,
WebGLRenderer,
WebGLRenderTarget,
} from 'three';
import { Renin } from 'renin/lib/renin';

export class SpinningDonut extends ReninNode {
/* The frame range this node will be active. */
Expand Down Expand Up @@ -66,6 +67,7 @@ export class SpinningDonut extends ReninNode {
this.renderTarget.setSize(width, height);
}

// @ts-ignore
public render(frame: number, renderer: WebGLRenderer) {
/* Since these animation updates are not stateful, we do
* them "on-demand" in the render method. If they were stateful,
Expand Down
146 changes: 146 additions & 0 deletions example-project/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { Renin } from 'renin/lib/renin';
import { PostFx } from './PostFx';

export const renin = new Renin({
// @ts-ignore
music: {
src: music,
bpm: 114,
subdivision: 12,
beatOffset: 4,
},
// @ts-ignore
root: PostFx,
productionMode: import.meta.env.PROD,
rendererOptions: {
Expand All @@ -17,4 +19,148 @@ export const renin = new Renin({
aspectRatio: 16.0/9,
});

var enableStartupOverlay = true;
if(enableStartupOverlay) {
// This enables an overlay, so that when you run in production/release mode (by starting a http server in the dist folder),
// you get a screen showing a start button demo enjoyers can click, instead of them having to know to press space to run.
// You also get goodies like fullscreen being automatically set, and some more production info showing up at the start while it's warming up!
const overlay = document.createElement("div");
overlay.style.position = "absolute";
overlay.style.left = "0px";
overlay.style.right = "0px";
overlay.style.top = "0px";
overlay.style.bottom = "0px";
overlay.style.background = "#f2de8d"; // This is the background of the splash screen
overlay.style.display = "flex";
overlay.style.alignItems = "center";
overlay.style.justifyContent = "center";
document.body.appendChild(overlay);

if (import.meta.env.PROD) {
// @ts-ignore
const aspectRatio = renin.aspectRatio; // Would probably be more efficient to just write 1.7778, but this happens only once, is cheap, and more readable this way

var demoName = "Example Project";
var crew = "Demo Group";
var party = "Demo Party";
var releasedTime = "Now!";

const delay = (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms));
(async () => {
overlay.innerHTML = `
<div style="line-height:1.3;text-align:center;color:#1f1502;width:100%;max-width:500px;
font-size:20px;
font-weight: 100;
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;"
>
<div style="font-size:64px;margin-bottom:32px;
font-family: Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid Serif, Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
"><div style="font-size:24px">${demoName}</div></div>
<div style=margin-bottom:32px>by</div>
<div style=margin-bottom:64px>${crew}</div>

<button style="visibility:hidden; padding: 4px 16px; font-size:48px;
font-family: Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid Serif, Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
">Start</button>
<div id=loading>Loading, please wait... (could take a while, hang in there!)</div>


<div style="bottom:16px;position:absolute;bottom:16px;left:0;right:0">Released at ${party} ${releasedTime}.</div>
</div>
`;
await delay(50);
renin.isFullscreen = true;
let width = window.innerWidth * 2;
let height = window.innerHeight * 2;
if (width / height >= aspectRatio) {
width = height * aspectRatio;
} else {
height = width / aspectRatio;
}
renin.resize(width, height);

var warmupScenes = false;
if(warmupScenes)
{
// This is awesome for performance when running the final built version of your demo, but wrecks everything if your scenes are stateful.
// Enable with care!

for (let i = 0; i < 150 * 4; i++) {
await delay(1);
renin.jumpToFrame(i * 25);
renin.update(i * 25);
renin.render();
console.log("warmup", i);
}

// Put special frames you know you want warmed up, like scene transitions, here.
const specialFrames = [
0,
];
for (const frame of specialFrames) {
await delay(1);
renin.jumpToFrame(frame);
renin.update(frame);
renin.render();
console.log("special warmup", frame);
}

await delay(100);
}

renin.jumpToFrame(0);

await delay(100);
renin.resize(width, height);
const loading = document.querySelector("#loading");
// @ts-ignore
loading.style.visibility = "hidden";
const button = document.querySelector("button");
button?.addEventListener("click", async () => {
document.body.requestFullscreen();
delay(1000);
let width = window.innerWidth;
let height = window.innerHeight;
if (width / height >= aspectRatio) {
width = height * aspectRatio;
} else {
height = width / aspectRatio;
}
renin.renderer.domElement.width = width;
renin.renderer.domElement.height = height;

renin.renderer.domElement.style.width = width + "px";
renin.renderer.domElement.style.height = height + "px";

/* position domElement in the center of the screen */
renin.renderer.domElement.style.position = "absolute";
renin.renderer.domElement.style.left = "50%";
renin.renderer.domElement.style.top = "50%";
renin.renderer.domElement.style.transform = "translate(-50%, -50%)";

renin.resize(width, height);
renin.renderer.setPixelRatio(1);
const subtitleValue = document.querySelector("select")?.value;
//@ts-ignore
renin.subtitlePlacement = subtitleValue;
await delay(200);
for (let i = 0; i < 100; i++) {
await delay(1);
// @ts-ignore
overlay.style.opacity = 1 - i / 100;
}
overlay.remove();
await delay(1500);
overlay.remove();
renin.music.play();
});
// @ts-ignore
button.style.visibility = "visible";
})();
} else {
overlay.remove();
}
}

renin.loop();
2 changes: 1 addition & 1 deletion example-project/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"moduleResolution": "Node",
"strict": true,
"strict": false,
"sourceMap": true,
"isolatedModules": true,
"esModuleInterop": true,
Expand Down
31 changes: 25 additions & 6 deletions example-project/vite.config.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,35 @@
import { defineConfig } from 'vite';
import vitePluginString from 'vite-plugin-string';
import reninPlugin from 'renin/lib/ui/vite.mjs';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import { defineConfig } from "vite";
import path from "path";
import * as url from "url";
import vitePluginString from "vite-plugin-string";
import reninPlugin from "renin/lib/ui/vite.mjs";
import { nodeResolve } from "@rollup/plugin-node-resolve";

const dir = url.fileURLToPath(new URL(".", import.meta.url));

export default defineConfig({
base: '',
build: {
target: "esnext",
},
base: "",
plugins: [
reninPlugin(),
nodeResolve(),
vitePluginString.default({
include: ['**/*.vs', '**/*.fs', '**/*.vert', '**/*.frag', '**/*.glsl'],
include: [
"**/*.vs",
"**/*.fs",
"**/*.vert",
"**/*.frag",
"**/*.glsl",
// "**/*.wasm"
],
compress: false,
}),
],
resolve: {
alias: {
"@": path.resolve(dir, "src"),
},
},
});
Loading