Giter Club home page Giter Club logo

pex-context's Introduction

pex-gl

npm version stability-stable npm minzipped size dependencies types Conventional Commits styled with prettier linted with eslint license

Create a RenderingContext (2d, webgl, webgl2, bitmaprenderer, webgpu) for use in PEX.

Installation

npm install pex-gl

Usage

import createRenderingContext, { FALLBACKS } from "pex-gl";

// Creates a webgl context filling the window
const context = createRenderingContext();

// Creates a webgl context from an existing canvas and keeps its size
const context = createRenderingContext({ canvas });

// Creates a webgl context on a new canvas with given width and height
const context = createRenderingContext({ width, height });

// Creates a new canvas of type "webgpu"
const context = createRenderingContext({ type: "webgpu" });

// Creates a new canvas of type "webgl" or fallback to experimental-webgl in case it fails
const context = createRenderingContext({ type: "webgl" });

// Disable fallbacks for "webgl2"
FALLBACKS.webgl2 = [];
// Creates a new canvas of type "webgl2" and return null in case it fails
const context = createRenderingContext({ type: "webgl2" });

API

Constants

FALLBACKS

Context fallbacks map

Functions

createRenderingContext([opts])RenderingContext

Creates a rendering context.

Typedefs

Options : object

Options for context creation. All optional.

FALLBACKS

Context fallbacks map

Kind: global constant

createRenderingContext([opts]) ⇒ RenderingContext

Creates a rendering context.

Kind: global function

Param Type Default
[opts] Options {}

Options : object

Options for context creation. All optional.

Kind: global typedef Properties

Name Type Default Description
[width] number window.innerWidth Request an initial canvas width.
[height] number window.innerHeight Request an initial canvas height.
[pixelRatio] boolean 1 Multiply canvas dimensions with a given ratio.
[fullscreen] boolean !opts.width && !opts.height Make the canvas fullscreen.
[type] "2d" | "bitmaprenderer" | "webgl" | "webgl2" | "webgpu" "webgl" A "contextType" for getContext.
[element] HTMLElement document.body Element to append the canvas to.
[...contextAttributes] CanvasRenderingContext2DSettings | WebGLContextAttributes {} Attributes to be passed to getContext.

License

MIT. See license file.

pex-context's People

Contributors

automat avatar dependabot[bot] avatar dmnsgn avatar nkint avatar simonharrisco avatar vorg 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  avatar  avatar  avatar  avatar  avatar

pex-context's Issues

State save/restore for separate/unified stencil{Func,Op}, blend{Equation,Func} wrong

stencilFunc
https://github.com/pex-gl/pex-context/blob/master/Context.js#L146
Should be merged into stencilFuncSeparate and be:

this._stencilFuncSeparate = [
    //front
    this._gl.getParameter(this._gl.STENCIL_FUNC),
    this._gl.getParameter(this._gl.STENCIL_REF),
    this._gl.getParameter(this._gl.STENCIL_VALUE_MASK),
     //back
    this._gl.getParameter(this._gl.STENCIL_FUNC),
    this._gl.getParameter(this._gl.STENCIL_REF),
    this._gl.getParameter(this._gl.STENCIL_VALUE_MASK)
];

setStencilFunc then just sets both gl.FRONT and gl.BACK part of stencilFuncSeparate state.
Because this here doesnt work as expected: https://github.com/pex-gl/pex-context/blob/master/Context.js#L670.

ctx.setStencilFunc(gl.ALWAYS,1,1);
ctx.pushState(ctx.STENCIL_BIT);
//something
ctx.setStencilFuncSeparate(ctx.FRONT,gl.NEVER,0,1);
ctx.popState(ctx.STENCIL_BIT);
//restores stencil state based on stencilFuncSeparate state, but could differ from unified state set
//before push

also separate getter getStencilFuncSeparate(out) doesnt make sense here anymore, https://github.com/pex-gl/pex-context/blob/master/Context.js#L1058,
should be getStencilFuncSeparate(face,out)
and https://github.com/pex-gl/pex-context/blob/master/Context.js#L1031 should
return both gl.FRONT and gl.BACK state (see top)

Merge all separated states and update getters:
stencilFunc=>stencilFuncSeparate
stencilOp=>stencilOpSeparate
blendEquation=>blendEquationSeparate
blendFunc=> blendFuncSeparate

Verify pipeline parameters

E.g. this should crash

ctx.pipeline({
   blendSrcRGBFactor: ctx.SRC_ALPHA
})

as it should be ctx.BlendFactor.SrcAlpha

Disable logs

Switch to using 100% debug module so they can be enabled on demand

drawElements: attempt to access out of bounds arrays

I had problems rendering meshes where i used shaders with and without aTexCoord0 due to VertexArray locations being left enabled.

We don't unbind the unused vertex array locations so i experimented with VertexArray._unbindInternal but ideally we would disable only the locations not used by the next VertexArray.

This wouldn't happen if we had draw commands with both shaders and vertex arrays present at the same place so we can compare what's used and what's provided. We could also optimize these cases on the fly by using VAOs is the VA/Program pair is used multiple times.

Set depthFunc independently from depthTest

Right now the depthFunc will not change if depthTest was already enabled

if (pipeline.depthTest !== state.depthTest) {
        state.depthTest = pipeline.depthTest
        state.depthTest ? gl.enable(gl.DEPTH_TEST) : gl.disable(gl.DEPTH_TEST)

        // TODO: should we flip it only when depth is enabled?
        if (pipeline.depthFunc !== state.depthFunc) {
          state.depthFunc = pipeline.depthFunc
          gl.depthFunc(state.depthFunc)
        }
      }

Texture2D add mipmap support

Adding { mipmap: true } in options should set filtering to:

magFilter = gl.LINEAR;
minFilter = gl.LINEAR_MIPMAP_LINEAR;

and call

gl.generateMipmap(gl.TEXTURE_2D);

Add colorMask support

Btw. depthMask is called depthWrite. How are other engines handling it when it comes to passes? As color mask influences clearColor behaviour so should it be pipeline or pass?

Cache properties on state sub-object

Right now we cache state properties on

  1. state pipeline.blend !== state.blend
  2. defaultState if (self.defaultState.viewport[2] !== gl.drawingBufferWidth
  3. state.pipeline if (pipeline.colorMask[0] !== state.pipeline.colorMask[0]

Highlight non-ASCII characters in code editor

Sometimes my Safari / CodeMirror inserts invisible character into GLSL code preventing it from compiling. We can highlight it using the following option for CodeMirror. I haven't added it by default as it will probably break emojis in strings etc. Are we using them?

specialChars: /[^\x00-\x7F]/

Texture2D add anisotropic filtering

In WebGL

var anisoExt = gl.getExtension('EXT_texture_filter_anisotropic');
ctx.bindTexture(this.baseColorTex);
gl.texParameterf(gl.TEXTURE_2D, anisoExt.TEXTURE_MAX_ANISOTROPY_EXT, 4);

In Plask

#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF

Consider dropping debug module

Pros of debug:

  • message logs are namespaced by module / class
  • is disabled by default (dev and production)
  • can enable / filter logs globally from js or localStorage setting

Cons of debug:

  • ?

Invalid index buffer type

When using pex-renderer with uint32 the indices type was uint16 while cmd.indices.buffer.type was uint32 which causes glitches in rendering.
https://github.com/pex-gl/pex-context/blob/master/index.js#L761

var type = cmd.indices.type || indexBuffer.type

Test code. Is it because we are updating geometry?

ctx.gl.getExtension('OES_element_index_uint')
newGeo.cells = { buffer: ctx.indexBuffer(new Uint32Array(newGeo.cellsFlat)) }
pointCube.getComponent('Geometry').set(newGeo)

Constants naming in v2.0

// pex 0.3, PITA with extensions, e.g. gl.getExtension('half-float-oes').HALF_FLOAT
a) ctx.createTexture({ type: gl.FLOAT }) 

// pex 1, requires copying all the constants from gl. to pex
b) ctx.createTexture({ type: ctx.FLOAT }) 

// regl, need to guess what's the string, half-float, half float, float16, float32 etc
c) ctx.createTexture({ type: "float" })

// import, subnamespace, enum?
d) ctx.createTexture({ type: ctx.TextureType.Float })

Viewport size is undefined when rendering to a cubemap

My viewport sniffing code doing pass.opts.color[0].width was failing as i need to handle pass.opts.color[0].texture.width as well normally i would access framebuffer.color[0].texture as it normalizes both cases to the same format (first one would expand to { texture: imageTex, target: imageTex.target } but as i tried explain yesterday with shared FBO we update the color attachments when the command is submitted (and after i was checking for viewport). So I was getting viewport [0, 0, undefined, undefined] so skybox wasn’t rendering.

Verify command props

E.g. it should be illegal to call

ctx.submit({
 pipeline: {},
 primitive: ctx.Primitive.Lines
})

as primitive belongs to pipeline

Move from manual bind/draw to CommandQueue

I've started a CommandQueue class inspired by Vulkan and regl

https://github.com/pex-gl/pex-renderer/blob/master/Skybox.js#L21

this._drawCommand = cmdQueue.createDrawCommand({
    depthTest: false,
    program: this._skyboxProgram,
    mesh: this._fsqMesh,
    uniforms: {
      uEnvMap: this._envMap,
      uFlipEnvMap: this._envMap.getFlipEnvMap ? this._envMap.getFlipEnvMap() : -1
    }
  })

This could form a base of [email protected] with state and matrix stack removed (with maybe just the most recent state for temporary bindings like texture uploads or buffer updates.

Open poblems

Specifying FBO attachments

https://github.com/pex-gl/pex-renderer/blob/master/local_modules/pex-render-to-cubemap/index.js

//ugly
framebuffer: fbo,
framebufferColorAttachments: {
  '0': { target: ctx.TEXTURE_CUBE_MAP_POSITIVE_X + sideIndex, handle: cubemap.getHandle(), level: level }
},

Texture content uploads (after initial creation)

createUpdateCommand?

State stack via subcommands

Inspired by regl

var renderCmd = cmdList.createCommand({
  framebuffer: fbo
})

cmdQueue.submit(renderCmd, {}, function() {
   // render your scene to the FBO
   cmdQueue.submit(drawCubeCmd)
})

What's next in 2.0.0?

  • CommandQueue #10
  • Remove pushState, pushModelMatrix etc
  • Remove normal, model, view, projection matrix injection (they are automatically set on draw if shader contains a given uniform e.g. uProjectionMatrix, overrriding whatever you have set yourself)

More?

Cubemap orientation

In three.js

Dynamic cube maps need to have flip uniforms (flipEnvMap / tFlip) set to 1, static cube maps to -1 (default).
mrdoob/three.js@addb3a1

Can we somehow render dynamic ones to the same layout as static ones to avoid this flipping?

Improve inline examples

Before

var pass = ctx.pass({
  color: [Texture2D, ...]
  color: [{ texture: Texture2D | TextureCube, target: CubemapFace }, ...]
  depth: Texture2D
  clearColor: Array,
  clearDepth: Number
})

After

var depthMap = ctx.texture2D({ width: 128, height: 128, pixelFormat: ctx.PixelFormat.DEPTH })
var pass = ctx.pass({
  color: [ ctx.texture2D({}), ... ],
  color: [{ texture: ctx.textureCube({}), target: ctx.CubemapFace.PositiveX }, ...],
  depth: ctx.texture2D({}),
  depth: depthMap,
  clearColor: [1, 0, 0, 1],
  clearDepth: 1
})

Add support for mipmap generation on update

Currently we need two update calls to make it work

    ctx.update(texture.value, {
      data: textureImage,
      flipY: false,
      min: ctx.Filter.LinearMipmapLinear
      //mipmap: true,
    })
    ctx.update(texture.value, {
      mipmap: true
    })

Draw loop crash

If I compile invalid shader the render loop crashes and I'm not able to restart it no matter what.

Chrome shows:

glDrawElements: Source and destination textures of the draw are the same.

Firefox complains about feedback loop.

Add note about resources being plain objects

So it's obvious that

var tex = ctx.texture2D({
  width: 256,
  pixelFormat: ctx.PixelFormat.RGBA8
})

tex.width //256
tex.pixelFormat //'rgba8'

//but also those properties has been added
tex.type //gl.UNSIGNED_BYTE
tex.internalFormat //gl.RGBA

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.