Coder Social home page Coder Social logo

kevzettler / react-regl Goto Github PK

View Code? Open in Web Editor NEW
194.0 4.0 24.0 253.26 MB

React Fiber Reconciler Renderer for Regl WebGL

Home Page: http://kevzettler.com/react-regl/

JavaScript 4.55% TypeScript 94.68% HTML 0.77%
regl webgl react reconciler renderer 3d-graphics glsl shaders glsl-shaders regl-webgl

react-regl's Introduction

react-regl

This library enables Regl shader WebGL draw commands to be rendered directly as React components.

Stability npm version Build Status

Demos

View demos in the Storybook

There is a React Storybook included in the /docs directory with usage examples. The source for the Storybook is in the /stories directory and demonstrates how to create the examples.

Visit the Regl gallery page for more ideas on usage.

Install

Use your perferred package manager

npm

npm install --save react-regl

yarn

yarn add react-regl

Example Usage

There is a test app that demonstrates both modes of ussage in ./react-regl-test-app

Triangle.js

// Define a draw call for rendering a 2D triangle
const DrawTriangle = regl({
  // Shaders in regl are just strings.  You can use glslify or whatever you want
  // to define them.  No need to manually create shader objects.

  vert: `
          precision mediump float;
          attribute vec2 position;
          void main () {
            gl_Position = vec4(position, 0, 1);
          }`,

  frag:`
          precision mediump float;
          uniform vec4 color;
          void main () {
            gl_FragColor = color;
          }`,

  // Here we define the vertex attributes for the above shader
  attributes:{
    position: [
      [-1, 0],
      [0, -1],
      [1, 1]
    ]
    // regl automatically infers sane defaults for the vertex attribute pointers
  },

  uniforms:{
    // This defines a dynamic regl value that can bethat can be passed as a react prop
    color: regl.prop('color')
  },

  // This tells regl the number of vertices to draw in this command
  count: 3
});

export default DrawTriangle;

use in React App

import React from 'react';
import { createRoot } from 'react-dom/client';
import { ReglFrame } from 'react-regl';
import { DrawTriangle } from './DrawTriangle';

const container = document.getElementById('root');
const root = createRoot(container!);
root.render(
  <ReglFrame
    color={[0.40625, 0.94921, 0.996, 1]}>
    <DrawTriangle />
  </ReglFrame>
);

use in Standalone (Non-react) App

import reglInit from "regl";
import reactRegl from "react-regl";
import { DrawTriangle } from './DrawTriangle';

// Create a canvas
const canvas = document.createElement('canvas');
canvas.id = 'gameplay-canvas';
canvas.width = window.innerWidth;
canvas.height = window.innerHeight
canvas.style.width = '100%';
canvas.style.height = '100%';
document.body.appendChild(canvas);

// create a gl context
const gl = canvas.getContext("webgl", {
  alpha: false,
  antialias: false,
  stencil: false,
  preserveDrawingBuffer: false
});

// create a regl scope reference
const reglRef = reglInit({
  gl,
});

// pass the regl reference to reactRegl
reactRegl.setRegl(reglRef);

reglRef.clear({
  color: [0.40625, 0.94921, 0.996, 1],
  depth: 1
});

// render react regl components
DrawTriangle();

Design Goals

This libaray was developed as a byproduct of using regl for an HTML5 game engine rendering layer. The game engine has many views that render 3D content. Some of the game engine views need to be high performance with as little over head as possible like the realtime gameplay view. Other views are less performance demanding and are used for stateful UI e.g. inventory, store, character select views.

This libaray enables developers to write shader code in a Regl syntax style and then seamlesssly execute it as a regular Regl command or a React component.

This library brings a JSX interface to regl, enabling easy integration of Regl UI into existing react projects. react-regl Allows you to render regl draw commands as React components. You can define the Regl draw command as you would with raw regl but with react-regl you can pass and render it as React component.

This library was inspired by a discussion in the main regl repository: regl-project/regl#576

Caveats

This library uses some magic to 'deferr' WebGL resource and context creation. This library is not a 1-to-1 match with base regl functionality. There are some cases of breakage with the regl examples.

Alternative libraries

Because of the Caveats mentioned above we feel compled to mention alternative libraries. @psycobolt/react-regl is a purely React focused regl reconciler which seems to 100% cover the example cases of the base regl library. https://github.com/psychobolt/react-regl

Worldview is a higher level 3D engine (think Three.js or Babylon.js) abstraction on top of Regl with corporate backing from Crusie self driving. https://webviz.io/worldview/#/

Regl vs Other WebGL frameworks

Regl follows the unix philosophy of "small sharp tools" or "do one thing and do it well". Regl has full test coverage and aims for stable non-breaking updates. Other popular WebGL frameworks encompass much more responsiblity, usually including heavy abstractions for: scene graphs, animation systems, input systems, and cross device compatibility. The large amount of responsiblity in these other libraries leads to unstable, breaking releases, and lacking documentation and support.

learn more in the official Why Regl? documentation.

Development

This repo is using yarn. You can build the module with yarn build Then in a seperate project you can require the dependency with a local file path like yarn add ../path/to/react-regl

Publishing

publish to npm with the version command and patch minor major, and pre versions or explicit tag 4.0.0-beta.2

npm version prerelease

npm version will create a git tag that needs to be pushed..

git push --tags

react-regl's People

Contributors

benwest avatar danrossli avatar dependabot[bot] avatar inokawa avatar kevzettler avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

react-regl's Issues

instanced-mesh example has bugged rendering in storybook

after the major version of 5.0.0 the instanced-mesh example has some rendering issues
Screen Shot 2023-01-28 at 1 25 44 PM

This appears to be a by product of storybook, or the camera module in the example. If you resize the storybook window there are frame pops where it renders correctly. If I disable the camera updates the bunnys render correctly. I verified on the main regl repository that this issue doesn't exist so its not caused the the update to regl latest version

Doesn't work with React 18

Hi, looks great, just what I need. I wonder why so few people use it, but needs an upgrade to React 18 in order to survive. The deferred regl also doesn't seem to be functional.

If you don't want to update it, can you explain the approach you have taken so it's easier for the next enthusiast to fix it? And perhaps update the readme.

I will manage to roll my own, but it's for a closed source company and a modified version of React.

Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue.

Hi, thanks for your great work. I get the above error message when trying the following:

app.js

import React, { Component } from 'react';
import Regl from 'react-regl';
import Triangle from './triangle.jsx';

class App extends Component {

render() {
    return (
        <div className="App">
            <h1>React Regl example</h1>
            <Regl width={window.innerWidth} height={window.innerHeight} color={[0,0,0,1]}>
                <Triangle color={[0.812, 0.792, 0.098, 1]} positions={[[-0.5, 0], [0, -0.5], [0.25, 1]]} />
            </Regl>
        </div>
    );
}

}

export default App;

and triangle.jsx:
`
import React,{Component} from 'react';
import {Draw} from 'react-regl';

class Triangle extends Component {
render(){
return (
<Draw
vert={`
precision mediump float;
attribute vec2 position;
void main(){
gl_Position=vec4(position,0,1)
}

    `}
        frag={`
        precision mediump float;
        uniform vec4 color;
        void main(){
            gl_FragColor=color;
        }
        `}
        attributes={{
            position:this.props.positions
        }}
        uniforms={{
            color: this.props.color
        }}
        count={3}
        />
    )
}

}

export default Triangle
`

How to access `regl.texture`

I was trying to replicate the Baboon texture example from http://regl.party/examples when I noticed that there is no simple way to reach regl.texture method in react-regl. Actually there is no way to reach the initialized regl object as far as I can tell. Am I missing something? Is there a built-in way to do this?

Shared global deferred regl causes issues with multiple ReglFrame instances and mounting/unmounting

The regl calls are deferred, they are not executed until the ReglFrame component mounts and passes a canvas draw context to the reglInit function and then passes a regl reference set method. This will then trigger all the deferred functions to execute. If ReglFrame is unmounted it will call regl.destroy and then when a new ReglFram is mounted it will reinitalize all the deferred functions with the new regl handle. This reinitialization of the deferred function seems to cause some some failures. This can be observed in the storybook by changing between the different stories. This causes a mount and unmount of the ReglFrame components. Which triggers the set/unset of the deferred regl components.

Further concerns are that the deferred resources are defined in shared global scope. So deferred resources that are not part of the ReglFrame component tree are re-initalized. In the story book this means that when you change between stories all of the resources for all other stories are reinitalized.

An idea for improvement here is ReglFrame should not call the global deferred set function which will execution all know deferred functions. Instead ReglFrame should execute a tree of the deferreds it will render. This will have some edge cases where a resources is defined in a scope out side of the render time tree but still used.

Module not found: Can't resolve 'react-regl'

Steps to reproduce:

npx create-react-app new_app
cd new_app
npm install --save react-regl

Then use this code in src/App.js:

import React from "react";
import ReactDOM from "react-dom";
import Regl from "react-regl";

export default class App extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidCatch(e, info) {
    console.log(e, info);
  }

  render() {
    return <Regl width={500} height={500} color={[0.5, 0.5, 0.5, 1]} />;
  }
}

Then:
npm run start

What I do wrong?

Immediately accessing props passed to regl JSX?

There may already be a way to do this, but I haven't been able to find it in any of the examples:

I'm trying to modify my shader code by passing in a '#define' value for an array length. As far as I know I can't use the regular "uniforms" method of passing these values to my shader, so I typically use '#define' or const with a hard-coded value that I feed into my shader string.

Ideally this value would be a prop that I can pass to my React component and it would modify the shader code. I tried passing a value as a 'prop' (which seems very clean and React-friendly). But when I try to access the value on regl.prop - it returns a deferred-regl function expecting (context, props) and I'm not sure whether I can access the value at that point.

Is there a way to do this currently? If not, it would be a really helpful feature.

FWIW I noticed three.js uses a 'defines' object to abstract this further - but I don't think regl exposes that in the same way.

const frag = (nArr) => {
    // language=GLSL
    return `
        precision mediump float;

        #define N_ARR ${nArr}
        #define MAX_STACK 2
       ...
const ColorizerRegl = regl({
    vert,
    frag: frag(regl.prop('nArr')),
    attributes: {
        position: [
            0, 4,
            -4, -4,
            4, -4,
        ]
    },

    uniforms: {
        textureReference: regl.prop('reference'),
        textureData: regl.prop('data'),
        textureCurrent: regl.prop('current'),
        dataWidth: regl.prop('dataWidth'),
    },

    count: 3
});
<ColorizerRegl nArr={metaData.nArr}
       reference={images.reference}
       data={images.data}
       current={images.current}
       dataWidth={metaData.dataWidth}/>

Basic triangle example 5.0.0 fails to render in React.StrictMode tree

during testing of #43 on a new create-react-app Noticed that the basic triangle example fails to render. Narrowed this down to find that the app was wrapped in the React.StrictMode component and removing the StrictMode the ReglFrame tree would render successfully.

https://beta.reactjs.org/reference/react/StrictMode
The StrictMode docs claim that it intentionally causes double rendering to find any impure behavior. There is definitly some impure behavior going on with the deferrred state hacks in react-regl. Going to have to investigate further to see if there is any guard to implement for a more pure interaction.

Unable to reproduce basic example with React 16.6+

Hi,

Thanks for putting together this library. I've been trying to get a basic example running using the minimal "draw a canvas, and shade it" example from the storybook. I was getting the same error as reported in #7 when developing locally in a storybook. Here's the same code sample running in a sandbox.

import React from "react";
import ReactDOM from "react-dom";
import Regl from "react-regl";

class App extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidCatch(e, info) {
    console.log(e, info);
  }

  render() {
    return <Regl width={500} height={500} color={[0.5, 0.5, 0.5, 1]} />;
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

https://codesandbox.io/s/nn4x2nx6ml

An error comes out in the console about having difficulty with accessing the store prop:

**Warning: Failed child context type: Cannot read property 'store' of undefined**

Downgrading to older React 16.1.1 for both react and react-dom fixes the issue. However, that version is missing some features that I want to use in a current project (hooks, etc), so I'd like to try to find a workaround that lets me use the latest react together with this library.

ReglFrame color not persisting across React redraw calls

I'm testing the basic triangle example and noticed that the background color (green in this example) is respected when I render the react component for the first time, but if I change the react component color prop (e.g. on a button click to trigger a re-render in react), the triangle color changes as expected, but the ReglFrame background color turns black (instead of green).

 <ReglFrame width={width} height={height} color={[0, 1, 0, 1]}>
    <Triangle color={props.color}/>
</ReglFrame>

Also, this may be a separate issue, but alpha in ReglFrame's color doesn't affect anything in the frame background. Is there a way to enable alpha support?

Invalid JSX error

I'm trying to follow the basic triangle example, but I'm getting JSX errors. I've tried to see if I can change anything in the tsconfig file to work around this, but I can't see anything that you're doing different.

What am I missing?

'Triangle' cannot be used as a JSX component.
  Its return type 'IDregl<Regl>' is not a valid JSX element.
    Type 'IDregl<Regl>' is missing the following properties from type 'ReactElement<any, any>': type, props, key  TS2786

    36 |         <ReglFrame
    37 |             color={[0.40625, 0.94921, 0.996, 1]}>
  > 38 |             <Triangle />
       |              ^
    39 |         </ReglFrame>
    40 |     );
    41 | };

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.