From 421e4ed45cbc57acfbb9468b45d5c2ba166d31d8 Mon Sep 17 00:00:00 2001 From: Brian Zinn Date: Mon, 30 Mar 2020 15:21:40 -0700 Subject: [PATCH] And observerable for start of Engine runRenderLoop(). Fix PIXI demo (update readme links to new storybook). (#58) --- .storybook/main.js | 10 +- README.md | 93 +++++++------- src/Engine.tsx | 4 + src/generatedCode.ts | 40 ------ .../Integrations/pixi-render.stories.js | 121 ++++++++++-------- .../babylonjs/Integrations/shaders/index.js | 14 +- 6 files changed, 129 insertions(+), 153 deletions(-) diff --git a/.storybook/main.js b/.storybook/main.js index 8b141a96..3b771db3 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -1,9 +1,11 @@ +const path = require('path'); + module.exports = { stories: ['../stories/**/*.stories.[tj]s'], addons: [ - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addon-storysource', + '@storybook/addon-actions/register', + '@storybook/addon-links/register', + '@storybook/addon-storysource/register', ], webpackFinal: async (config, { configType }) => { config.module.rules.push({ @@ -11,7 +13,7 @@ module.exports = { loaders: [require.resolve('@storybook/source-loader')], enforce: 'pre', }); - console.log('added source loader to webpack config') + console.log(`added source loader to '${configType}' webpack config`); // Return the altered config return config; }, diff --git a/README.md b/README.md index 63030502..ec3fd887 100644 --- a/README.md +++ b/README.md @@ -30,15 +30,15 @@ With declarative (TSX/JSX) coding and HMR, you experience the same development w ![BabylonJS HMR](https://raw.githubusercontent.com/brianzinn/react-babylonjs/master/media/react-babylonjs-hmr.gif) -# BabylonJS API Support +# @babylonjs/core API Support 1. **Node -> Mesh** - abstractMesh, mesh, node, transformNode 2. **Cameras** - anaglyphArcRotateCamera, anaglyphFreeCamera, anaglyphGamepadCamera, anaglyphUniversalCamera, arcFollowCamera, arcRotateCamera, camera, deviceOrientationCamera, flyCamera, followCamera, freeCamera, gamepadCamera, stereoscopicArcRotateCamera, stereoscopicFreeCamera, stereoscopicGamepadCamera, stereoscopicUniversalCamera, targetCamera, touchCamera, universalCamera, virtualJoysticksCamera, vrDeviceOrientationArcRotateCamera, vrDeviceOrientationFreeCamera, vrDeviceOrientationGamepadCamera, webVrFreeCamera, webXrCamera -3. **Geometries (meshes)** - box, cylinder, dashedLines, decal, disc, extrudePolygon, extrudeShape, extrudeShapeCustom, ground, groundFromHeightMap, icoSphere, lathe, lines, lineSystem, plane, babylon-polygon, polyhedron, ribbon, sphere, tiledBox, tiledGround, tiledPlane, torus, torusKnot, tube +3. **Geometries (meshes)** - box, cylinder, dashedLines, decal, disc, extrudePolygon, extrudeShape, extrudeShapeCustom, ground, groundFromHeightMap, icoSphere, lathe, lines, lineSystem, plane, babylon-polygon/Polygon, polyhedron, ribbon, sphere, tiledBox, tiledGround, tiledPlane, torus, torusKnot, tube > note: `babylon-polygon` instead of `polygon` due to JSX conflict with `React.SVGProps` -4. **Materials** - backgroundMaterial, fluentMaterial, material, multiMaterial, pbrBaseMaterial, pbrBaseSimpleMaterial, pbrMaterial, pbrMetallicRoughnessMaterial, pbrSpecularGlossinessMaterial, pushMaterial, shaderMaterial, standardMaterial +4. **Materials** - backgroundMaterial, fluentMaterial, material, multiMaterial, nodeMaterial, pbrBaseMaterial, pbrBaseSimpleMaterial, pbrMaterial, pbrMetallicRoughnessMaterial, pbrSpecularGlossinessMaterial, pushMaterial, shaderMaterial, standardMaterial 5. **Lights** - directionalLight, hemisphericLight, light, pointLight, shadowLight, spotLight @@ -46,9 +46,11 @@ With declarative (TSX/JSX) coding and HMR, you experience the same development w 7. **EffectLayers** - effectLayer, glowLayer, highlightLayer -8. **Others** - dynamicTerrain, environmentHelper, physicsImpostor, shadowGenerator, vrExperienceHelper +8. **Behaviors** - autoRotationBehavior, bouncingBehavior, framingBehavior, attachToBoxBehavior, fadeInOutBehavior, multiPointerScaleBehavior, pointerDragBehavior, sixDofDragBehavior -## GUI +9. **Others** - environmentHelper, physicsImpostor, shadowGenerator, vrExperienceHelper + +## @babylonjs/gui 1. GUI3DManager 2. **2D Controls** - scrollViewerWindow, baseSlider, babylon-button/Button, checkbox, colorPicker, container, control, displayGrid, babylon-ellipse/Ellipse, grid, babylon-image/Image, imageBasedSlider, imageScrollBar, inputPassword, inputText, babylon-line/Line, multiLine, radioButton, rectangle, scrollBar, scrollViewer, selectionPanel, slider, stackPanel, textBlock, virtualKeyboard > note: 'babylon-*' for `button`, `ellipse`, `image` & `line` due to JSX conflict with `React.SVGProps`, otherwise use the ProperCase equavalent, but you miss editor auto-completion. @@ -56,7 +58,7 @@ With declarative (TSX/JSX) coding and HMR, you experience the same development w 3. **3D Controls** - abstractButton3D, button3D, container3D, control3D, cylinderPanel, holographicButton, meshButton3D, planePanel, scatterPanel, spherePanel, stackPanel3D, volumeBasedPanel ## Extensions (new in 2.0) -1. DynamicTerrain +1. dynamicTerrain # Examples live demo: [default playground declarative](https://brianzinn.github.io/react-babylonjs/?path=/story/babylon-basic--default-playground) @@ -89,11 +91,11 @@ class WithProps extends React.Component return ( - - - + + + - + ) @@ -105,49 +107,44 @@ OK, optional code needed for rotating model via interactions! live demo: [VR + 3D model](https://brianzinn.github.io/react-babylonjs/?path=/story/with-vr--simple-vr) -inspiration playground: https://playground.babylonjs.com/#TAFSN0#2 +[inspiration playground](https://playground.babylonjs.com/#TAFSN0#2) Click on the IcoSpheres to rotate the Ghetto Blaster different directions. You can also use prop flow direct to components if you update state externally. The **<vrExperienceHelper />** tag adds button to view in VR headsets! ```jsx -class WithVR extends React.Component -{ - render() { - return ( - - - - - - - - - - - - - - ... - - - - - ) - } -} +const WithVR = (props) => ( + + + + + + + + + + + + + + ... + + + + +) ``` ## 2D/3D UI -Write declaratively your UI structure. You can dynamically add/remove in React, but use key property if you do. Here in GUI is where declarative excels over imperative -- `react-babylonjs` takes care of addControl()/removeControl() order of 3D GUI operations (with manager) and updating based on props/state (ie: text) seamlessly. +Write declaratively your UI structure. You can dynamically add/remove in React, but use key property if you do. Here in GUI is where declarative excels over imperative :) `react-babylonjs` takes care of addControl()/removeControl() and order of 3D GUI operations (with manager) and updating based on props/state. -Full example: [with 2D UI](https://brianzinn.github.io/react-babylonjs/?path=/story/with-vr--simple-2d-gui) +Full example: [2D UI to Plane](https://brianzinn.github.io/react-babylonjs/?path=/story/gui--with-2-dui) ```jsx @@ -205,7 +202,7 @@ function NonDeclarative() { ``` ## Hooks, Shadows and Physics (and optionally TypeScript, too) -You can declaratively use many features together - here only the button click handler actually has any code - and we have declarative Physics, GUI, Lighting and Shadows. demo: [Bouncy demo](https://brianzinn.github.io/react-babylonjs/?path=/story/physics-and-hooks--bouncy-playground) +You can declaratively use many features together - here only the button click handler actually has any code - and we have declarative Physics, GUI, Lighting and Shadows. demo: [Bouncy demo](https://brianzinn.github.io/react-babylonjs/?path=/story/physics-and-hooks--bouncy-playground-story) ```jsx import React, { useCallback } from 'react'; /// full code at https://github.com/brianzinn/create-react-app-typescript-babylonjs @@ -276,6 +273,8 @@ const App: React.FC = () => { > v2.0.1 (2019-10-09) - Switch to @babylonjs/* NPM. Add intrinsic elements, physics and dynamic terrain. +> v2.1.0 (2020-03-21) - NPM distro reduced size has only module. Add behaviors, effects and more demos (ie: custom props [chroma.js](https://brianzinn.github.io/react-babylonjs/?path=/story/integrations--chroma-js-props)). + ## Breaking Changes > 0.x to 1.0 ([List](breaking-changes-0.x-to-1.0.md)) @@ -290,8 +289,8 @@ const App: React.FC = () => { ## Contributors Huge shout out to [Konsumer](https://github.com/konsumer) that brought this project to the next level. The ideas and code sandboxes from issue #6 inspired the code generation and HOC + Context API integration. -Thanks to [seacloud9](https://github.com/seacloud9) for adding storybook (and [GSAP demo](https://brianzinn.github.io/react-babylonjs/?path=/story/babylon-basic--model-atom-gsap-tween)). Also for adding [dynamic terrain](https://brianzinn.github.io/react-babylonjs/?path=/story/babylon-basic--dynamic-terrain). +Thanks to [seacloud9](https://github.com/seacloud9) for adding storybook (and [GSAP demo](https://brianzinn.github.io/react-babylonjs/?path=/story/integrations--gsap-timeline)). Also for adding [dynamic terrain](https://brianzinn.github.io/react-babylonjs/?path=/story/babylon-basic--dynamic-terrain). Ported a branch of his into a [PIXI demo](https://brianzinn.github.io/react-babylonjs/?path=/story/integrations--pixi-story). -Lots of contributions from [hookex](https://github.com/hookex) :) Proper texture handling [demo](https://brianzinn.github.io/react-babylonjs/?path=/story/textures--image-texture), Node parenting [demo](https://brianzinn.github.io/react-babylonjs/?path=/story/babylon-basic--transformnode) Full Screen GUI [demo](https://brianzinn.github.io/react-babylonjs/?path=/story/gui--gui), Effect Layers [glow demo](https://brianzinn.github.io/react-babylonjs/?path=/story/special-fx--glow-layer). Additionally help upgrading to 4.1 and reconciler bug fix. +Lots of contributions from [hookex](https://github.com/hookex) :) Proper texture handling [demo](https://brianzinn.github.io/react-babylonjs/?path=/story/textures--image-texture), Node parenting [demo](https://brianzinn.github.io/react-babylonjs/?path=/story/babylon-basic--transform-node) Full Screen GUI [demo](https://brianzinn.github.io/react-babylonjs/?path=/story/gui--gui-full-screen), Effect Layers [glow demo](https://brianzinn.github.io/react-babylonjs/?path=/story/special-fx--glow-layer) and behaviors [demo](https://brianzinn.github.io/react-babylonjs/?path=/story/behaviors--pointer-drag-behavior). Made with ♥ by Brian Zinn diff --git a/src/Engine.tsx b/src/Engine.tsx index e3326ccc..e6bd414a 100644 --- a/src/Engine.tsx +++ b/src/Engine.tsx @@ -78,6 +78,7 @@ class Engine extends React.Component { private _engine?: Nullable = null; private _canvas: Nullable = null; + public onBeforeRenderLoopObservable: Observable = new Observable(); public onEndRenderLoopObservable: Observable = new Observable(); constructor(props: EngineProps) { @@ -97,6 +98,9 @@ class Engine extends React.Component { ) this._engine.runRenderLoop(() => { + if (this.onBeforeRenderLoopObservable.hasObservers()) { + this.onBeforeRenderLoopObservable.notifyObservers(this._engine!); + } this._engine!.scenes.forEach(scene => { scene.render() }) diff --git a/src/generatedCode.ts b/src/generatedCode.ts index 44dc1b3e..156dbb2d 100644 --- a/src/generatedCode.ts +++ b/src/generatedCode.ts @@ -5595,16 +5595,13 @@ export class FiberStandardMaterialPropsHandler implements PropsHandler { checkPrimitiveDiff(oldProps.DragMovementThreshold, newProps.DragMovementThreshold, 'DragMovementThreshold', 'number', changedProps) checkPrimitiveDiff(oldProps.dumpNextRenderTargets, newProps.dumpNextRenderTargets, 'dumpNextRenderTargets', 'boolean', changedProps) checkTextureDiff(oldProps.environmentBRDFTexture, newProps.environmentBRDFTexture, 'environmentBRDFTexture', 'BabylonjsCoreBaseTexture', changedProps) - // not found (default): 'BabylonjsCoreBaseTexture' property (not coded) BabylonjsCoreScene.environmentBRDFTexture. checkPrimitiveDiff(oldProps.environmentIntensity, newProps.environmentIntensity, 'environmentIntensity', 'number', changedProps) checkTextureDiff(oldProps.environmentTexture, newProps.environmentTexture, 'environmentTexture', 'BabylonjsCoreBaseTexture', changedProps) - // not found (default): 'BabylonjsCoreBaseTexture' property (not coded) BabylonjsCoreScene.environmentTexture. checkPrimitiveDiff(oldProps.ExclusiveDoubleClickMode, newProps.ExclusiveDoubleClickMode, 'ExclusiveDoubleClickMode', 'boolean', changedProps) checkColor3Diff(oldProps.fogColor, newProps.fogColor, 'fogColor', 'BabylonjsCoreColor3', changedProps) checkPrimitiveDiff(oldProps.fogDensity, newProps.fogDensity, 'fogDensity', 'number', changedProps) diff --git a/stories/babylonjs/Integrations/pixi-render.stories.js b/stories/babylonjs/Integrations/pixi-render.stories.js index b5e22c55..81b089a5 100644 --- a/stories/babylonjs/Integrations/pixi-render.stories.js +++ b/stories/babylonjs/Integrations/pixi-render.stories.js @@ -1,18 +1,20 @@ import React, { useRef, useCallback, useState, useEffect } from 'react'; import * as PIXI from 'pixi.js'; -import { Vector2, Vector3, Color3, PBRMaterial, Mesh } from '@babylonjs/core'; +import { Vector2, Vector3, Color3, Mesh } from '@babylonjs/core'; import { render as PixiRender, Text } from '@inlet/react-pixi' -import { Engine, Scene, useBabylonScene, useAfterRender } from '../../../dist/react-babylonjs'; +import { Engine, Scene, useBabylonScene } from '../../../dist/react-babylonjs'; import '../../style.css'; import {postSpectacularGradient, retroGoldGradient} from './pixi-styles'; -import {shaderToyMaterial, shaderToyProcText} from './shaders'; +import './shaders'; // side-effect of registering a pixel shader export default { title: 'Integrations' }; +let customProceduralTexture = null; +let time = 0; + /** - * This PIXI demo was copied from a seacloud9 fork + branch of this repo - * Seacloud9 added storybook, GSAP demo, etc to react-babylonjs. + * This PIXI demo was modified (PIXI 5 and more declarative) from a seacloud9 fork + branch of this repo * https://github.com/seacloud9/react-babylonjs/tree/pixi-babylonv4.1-alpha-16 */ function ScenePIXI(props) { @@ -28,7 +30,7 @@ function ScenePIXI(props) { clearBeforeRender: false, context: engine._gl, // ._gl is public **hidden** height: engine.getRenderHeight(), - // roundPixels: true, available is PIXI < 5.0 + // roundPixels: true, available PIXI < 5.0 view: engine.getRenderingCanvas(), width: engine.getRenderWidth() } @@ -39,12 +41,16 @@ function ScenePIXI(props) { } } - console.log('pixi props:', props); useEffect(() => { + // NOTE: to render PIXI in the background (BabylonJS in foreground) do 2 things differently: + // 1. use onBeforeRenderLoopObservable() + // 2. scene.autoClear = false; const observer = props.onEndRenderLoopObservable.add(engine => { engine.wipeCaches(true); - pixiRefs.current.renderer.reset(); - pixiRefs.current.renderer.render(pixiRefs.current.stage); + const { renderer } = pixiRefs.current; + renderer.reset(); + renderer.render(pixiRefs.current.stage); + renderer.reset(); // need to reset again :) }) return () => { @@ -52,10 +58,19 @@ function ScenePIXI(props) { } }) - // NOTE: this doesn't work - the post effect from shader have effects on PIXI stage - // useAfterRender((scene) => { - // const engine = scene.getEngine(); - // }) + useEffect(() => { + const observable = scene.onBeforeRenderObservable.add((scene) => { + if (scene !== null && customProceduralTexture !== null) { + time += scene.getEngine().getDeltaTime(); + // 'time' is a uniform on the shader + customProceduralTexture.setFloat("time", time); + } + }) + + return () => { + scene.onBeforeRenderObservable.remove(observable); + } + }) // not "rendering" using a different reconciler! PixiRender( @@ -69,51 +84,55 @@ function ScenePIXI(props) { return null; } -let customProcText; - -const onCreatedMirrorBall = (e) => { - e.position = new Vector3(0, 0, 0); - // Create materials - const glass = new PBRMaterial("glass", e._scene); - glass.reflectionTexture = customProcText; - glass.refractionTexture = customProcText; - glass.linkRefractionWithTransparency = true; - glass.indexOfRefraction = 0.52; - glass.alpha = 0; - glass.directIntensity = 0.0; - glass.environmentIntensity = 0.7; - glass.cameraExposure = 0.66; - glass.cameraContrast = 1.66; - glass.microSurface = 1; - glass.reflectivityColor = new Color3(0.2, 0.2, 0.2); - glass.albedoColor = new Color3(0.85, 0.85, 0.85); - e.material = glass; +const onCustomProceduralTextureCreated = (cpt) => { + customProceduralTexture = cpt; // assigning to reflection/refraction of mirrorball } -const onCreatedVaporware = (e) => { - e.billboardMode = Mesh.BILLBOARDMODE_ALL; - const customMaterial = shaderToyMaterial(e._scene); - customProcText = shaderToyProcText(e._scene); - customProcText.setVector2("resolution", new Vector2(1, 1)); - customMaterial.diffuseTexture = customProcText; - e.material = customMaterial; - let time = 0; - e._scene.registerBeforeRender(() => { - // falseCam.update(); - time += e._scene.getEngine().getDeltaTime(); - customProcText.setFloat("time", time); - }); - } +const onMirrorBallMaterialCreated = (mat) => { + mat.reflectionTexture = customProceduralTexture; + mat.refractionTexture = customProceduralTexture; +} const SceneBabylonJS = (props) => <> - + - - + + + + + + + + -const insertCoin = "Insert Coins"; +const insertCoins = "Insert Coins"; const postText = "P05T 5P3CTACU1AR DEMOSCENE"; let engine = undefined; export const PIXIStory = () => { @@ -129,7 +148,7 @@ export const PIXIStory = () => { - + diff --git a/stories/babylonjs/Integrations/shaders/index.js b/stories/babylonjs/Integrations/shaders/index.js index 7218e449..63b49c68 100644 --- a/stories/babylonjs/Integrations/shaders/index.js +++ b/stories/babylonjs/Integrations/shaders/index.js @@ -1,5 +1,5 @@ -import {Effect, StandardMaterial, CustomProceduralTexture} from "@babylonjs/core"; -// shader toy fragment example +import {Effect} from "@babylonjs/core"; +// register shader toy fragment example // https://www.shadertoy.com/view/4l2XWh Effect.ShadersStore.shaderToyPixelShader = ` uniform float time; @@ -170,12 +170,4 @@ Effect.ShadersStore.shaderToyPixelShader = ` } gl_FragColor = vec4(color, 1); } -`; - -export const shaderToyMaterial = (scene) => { - return new StandardMaterial("shaderToyMat", scene); -}; - -export const shaderToyProcText = (scene) => { - return new CustomProceduralTexture("shaderToytext", "shaderToy", 512, scene); -}; \ No newline at end of file +`; \ No newline at end of file