Coder Social home page Coder Social logo

pex-gl / pex-context Goto Github PK

View Code? Open in Web Editor NEW
156.0 9.0 12.0 24.14 MB

Modern WebGL state wrapper for PEX: allocate GPU resources (textures, buffers), setup state pipelines and passes, and combine them into commands.

Home Page: https://pex-gl.github.io/pex-context/examples/

License: MIT License

JavaScript 100.00%
webgl context texture buffer pipeline pex gpu

pex-context's Introduction

pex-context

Modern WebGL state wrapper for PEX. With pex-context you allocate GPU resources (textures, buffers), setup state pipelines and passes and combine them together into commands.

Example

const createContext = require('pex-context')
const createCube = require('primitive-cube')
const mat4 = require('pex-math/mat4')

const ctx = createContext({ width: 640, height: 480 })
const cube = createCube()

const clearCmd = {
  pass: ctx.pass({
    clearColor: [0, 0, 0, 1],
    clearDepth: 1
  })
}

const drawCmd = {
  pass: ctx.pass({
    clearColor: [0.2, 0.2, 0.2, 1],
    clearDepth: 1
  }),
  pipeline: ctx.pipeline({
    depthTest: true,
    vert: `
      attribute vec3 aPosition;
      attribute vec3 aNormal;
      uniform mat4 uProjectionMatrix;
      uniform mat4 uViewMatrix;
      varying vec3 vNormal;
      void main () {
        gl_Position = uProjectionMatrix * uViewMatrix * vec4(aPosition, 1.0);
        vNormal = aNormal;
      }
    `,
    frag: `
      precision mediump float;
      varying vec3 vNormal;
      void main () {
        gl_FragColor.rgb = vNormal;
        gl_FragColor.a = 1.0;
      }
    `
  }),
  attributes: {
    aPosition: ctx.vertexBuffer(cube.positions),
    aNormal: ctx.vertexBuffer(cube.normals)
  },
  indices: ctx.indexBuffer(cube.cells),
  uniforms: {
    uProjectionMatrix: mat4.perspective(
      mat4.create(),
      Math.PI / 4,
      640 / 480,
      0.1,
      100
    ),
    uViewMatrix: mat4.lookAt(mat4.create(), [2, 2, 5], [0, 0, 0], [0, 1, 0])
  }
}

ctx.frame(() => {
  ctx.submit(clearCmd)
  ctx.submit(drawCmd)
})

You can find runnable examples in the /examples folder in this repository. To run an example install Node.js, clone or download this repository and then run:

# go to the example folder
cd examples

# install examples dependencies
npm i

# run the example in your default browser window
npm start

API

Context

Creating gl context wrapper.

ctx = createContext(opts)

const createContext = require('pex-context')

// full window canvas
const ctx = createContext()

// creates gl context from existing canvas and keeps it's size
const ctx = createContext({ gl: gl })

// creates gl context from existing canvas and keeps it's size
const ctx = createContext({ canvas: canvas })

// creates new canvas with given width and height
const ctx = createContext({ width: Number, height: Number })

ctx.set(opts)

ctx.set({
  pixelRatio: 2,
  width: 1280,
  height: 720
})
property info default
pixelRatio canvas resolution, can't be bigger than window.devicePixelRatio 1
width canvas width -
height canvas height -

Note 1: The new size and resolution will be applied not immediately but before drawing the next frame to avoid flickering.

Note 2: Context's canvas doesn't resize automatically, even if you skip width/height on init and the canvas will be asigned dimensions of the window. To handle resizing use the following code:

window.addEventListener('resize', () => {
  ctx.set({
    width: window.innerWidth,
    height: window.innerWidth
  })
})

Render Loop

ctx.frame(cb)

  • cb: Function - Request Animation Frame callback

Commands

Commands are plain js objects with GPU resources needed to complete a draw call

const cmd = {
  pass: Pass
  pipeline: Pipeline,
  attributes: {
    name:  VertexBuffer,
    // or
    name: { buffer: VertexBuffer, offset: Number, stride: Number }
  },
  indices: IndexBuffer,
  // or
  indices: { buffer: IndexBuffer, offset: Number, count: Number },
  // or
  count: Number,
  instances: Number,
  uniforms: {
    name: Number,
    name: Array,
    name: Texture2D
  },
  viewport: [0, 0, 1920, 1080],
  scissor: [0, 0, 1920, 1080]
}
property info type
pass render pass info ctx.Pass
pipeline rendering pipeline info ctx.Pipeline
attributes vertex attributes map of :
attibuteName: ctx.VertexBuffer
attributeName: { buffer: VertexBuffer, offset: Number, stride: Number, divisor: Number }
indices indices either:
ctx.IndexBuffer
{ buffer: IndexBuffer, offset: Number, stride: Number }
count number of vertices to draw Integer
instances number instances to draw Integer
uniforms shader uniforms map of name: value
viewport drawing viewport bounds [x, y, w, h]
scissor scissor test bounds [x, y, w, h]

Note: either indices or count need to be specified when drawing geometry Note: scissor region is by default set to null and scissor test disabled

Submitting commands to the GPU

ctx.submit(cmd)

ctx.submit({
  pass: ctx.pass({
    clearColor: [1, 0, 0, 1]
  }),
  pipeline: ctx.pipeline({
    vert: '...',
    frag: '...'
  }),
  attributes: {...},
  indices: indexBuffer,
  uniforms: {...},
  ...
})

ctx.submit(cmd, opts)

Submit partially updated command without modifying the original one

// E.g. draw mesh with custom color
ctx.submit(cmd, {
  uniforms: {
    uColor: [1, 0, 0, 0]
  }
})

ctx.submit(cmd, [opts1, opts2, opts3...])

Submit a batch of commands differences in opts.

// E.g. draw same mesh twice with different material and position
ctx.submit(cmd, [
  { pipeline: material1, uniforms: { uModelMatrix: position1 },
  { pipeline: material2, uniforms: { uModelMatrix: position2 }
])

Subcommands

ctx.submit(cmd, cb)

Submit command while preserving state from another command.

This approach allows to simulate state stack with automatic cleanup at the end of callback.

// E.g. render to texture
ctx.submit(renderToFboCmd, () => {
  ctx.submit(drawMeshCmd)
})

Resources

All resources are plain js object and once constructed their properties can be accessed directly. Please note those props are read only. To set new values or upload new data to GPU see updating resources.

const 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

Pass

Passes are responsible for setting render targets (textures) and their clearing values. FBOs are created internally and automatically by pex-context.

pass = ctx.pass(opts)

const pass = ctx.pass({
  color: [Texture2D, ...]
  color: [{ texture: Texture2D | TextureCube, target: CubemapFace }, ...]
  depth: Texture2D
  clearColor: Array,
  clearDepth: Number
})
property info type default
color color render target Array of Texture2D or { texture, target} pairs null
depth depth render target Texture2D null
clearColor clear color value Array null
clearDepth clear depth value Number null

Pipeline

Pipelines represent the state of the GPU rendering pipeline (shaders, blending, depth test etc).

pipeline = ctx.pipeline(opts)

const pipeline = ctx.pipeline({
  vert: String,
  frag: String,
  depthWrite: Boolean,
  depthTest: Boolean,
  depthFunc: DepthFunc,
  blend: Boolean,
  blendSrcRGBFactor: BlendFactor,
  blendSrcAlphaFactor: BlendFactor,
  blendDstRGBFactor: BlendFactor,
  blendDstAlphaFactor: BlendFactor,
  cullFace: Boolean,
  cullFaceMode: Face,
  colorMask: Array,
  primitive: Primitive
})
property info type default
vert vertex shader code String null
frag fragment shader code String null
depthWrite depth write mask Boolean true
depthTest depth test on/off Boolean false
depthFunc depth test function DepthFunc LessEqual
blend blending on/off Boolean false
blendSrcRGBFactor blending source color factor BlendFactor One
blendSrcAlphaFactor blending source alpha factor BlendFactor One
blendDstRGBFactor blending destination color factor BlendFactor One
blendDstAlphaFactor blending destination alpha factor BlendFactor One
cullFace face culling on/off Boolean false
cullFaceMode face culling mode Face Back
colorMask color write mask for [r, g, b, a] Array of Boolean [true, true, true, true]
primitive geometry primitive Primitive Triangles

Texture

Textures represent pixel data uploaded to the GPU.

texture = ctx.texture2D(opts)

const tex = ctx.texture2D({
  data: [255, 255, 255, 255, 0, 0, 0, 255],
  width: 2,
  height: 1,
  pixelFormat: ctx.PixelFormat.RGB8,
  encoding: ctx.Encoding.Linear,
  wrap: ctx.Wrap.Repeat
})
property info type default
data pixel data Array, Uint8Array, Float32Array, HTMLCanvas, HTMLImage, HTMLVideo null
width texture width Number/Int 0
height texture height Number/Int 0
pixelFormat pixel data format ctx.PixelFormat ctx.PixelFormat.RGB8
encoding pixel data encoding ctx.Encoding ctx.Encoding.Linear
wrapS wrapS mode ctx.Wrap ctx.Wrap.ClampToEdge
wrapT wrapT mode ctx.Wrap ctx.Wrap.ClampToEdge
wrap combines wrapS and wrapT ctx.Wrap ctx.Wrap.ClampToEdge
min min filtering mode ctx.Filter ctx.Filter.Nearest
mag mag filtering mode ctx.Filter ctx.Filter.Nearest
aniso aniso level 1 Number/Int 0
mipmap generate mipmaps on update 2 Boolean false
flipY flip pixel data on upload Boolean false
name texture name for debugging String ''
target texture target 3 gl enum gl.TEXTURE_2D or gl.TEXTURE_CUBE

1 requries EXT_texture_filter_anisotropic 2 requires min to be set to ctx.Filter.LinearMipmapLinear or similar 3 read only

texture = ctx.textureCube(opts)

  • opts: Object - see ctx.texture2D(opts)
  • opts.data: Array of Images or TypedArrays - 6 images, one for each face +X, -X, +Y, -Y, +Z, -Z
const tex = ctx.textureCube({
  data: [ posx, negx, posy, negy, posz, negz ],
  width: 64,
  height: 64
])

Renderbuffer

Renderbuffers represent pixel data store for rendering operations

renderbuffer = ctx.renderbuffer(opts)

const tex = ctx.renderbuffer({
  width: 1280,
  height: 720,
  pixelFormat: ctx.PixelFormat.Depth16
})
property info type default
width renderbuffer width Number/Int 0
height renderbuffer height Number/Int 0
pixelFormat pixel data format1 ctx.PixelFormat null

1 only PixelFormat.Depth16 equal to gl.DEPTH_COMPONENT16 is currently supported for use as render pass depth storage (e.g. ctx.pass({ depth: renderbuffer})) for platforms with no WEBGL_depth_texture support.

Buffer

Buffers store vertex and index data in the GPU memory.

buffer = ctx.vertexBuffer(opts)

buffer = ctx.indexBuffer(opts)

const buf = ctx.vertexBuffer({ data: Array }) // aka Attribute Buffer

const buf = ctx.indexBuffer({ data: Array }) // aka Index Buffer
property info type default
data pixel data Array, Uint8Array, Float32Array null
type data type ctx.DataType ctx.DataType.Float32
usage buffer usage ctx.Usage ctx.Usage.StaticDraw
offset data offset in the buffer (update only) Number/Int undefined

Query

Queries are used for GPU timers.

query = ctx.query(opts)

Note: Requires EXT_disjoint_timer_query

const query = ctx.query({
  target: QueryTarget
})
property info type default
target query type ctx.QueryTarget ctx.QueryTarget.TimeElapsed
state query state ctx.QueryState ctx.QueryState.Ready
result result of the measurement Number null

ctx.beginQuery(q)

Begin the query measurement.

Note: There can be only one query running at the time.

ctx.endQuery(q)

End the query measurement.

Note: The result is not available immediately and will be null until the state changes from ctx.QueryState.Pending to ctx.QueryState.Ready

Updating resources

ctx.update(res, opts)

Update a resource.

ctx.update(res, { data: [] })

const tex = ctx.texture2D({...})
ctx.update(tex, {
  width: 1,
  height: 1,
  data: new Uint8Array([255, 0, 0, 255])
})
property info type
res resource to be updated ctx.Buffer, ctx.Framebuffer, ctx.Pass, ctx.Pipeline, ctx.Program, ctx.Query, ctx.Texture
opts whatever data the given resource accepts in constructor Object

Disposing resources

ctx.dispose()

Delete all allocated resources and stop render loop. Disposed context is no longer valid to use.

ctx.dispose()

ctx.dispose(res)

Delete a resource. Disposed resource is no longer valid for use.

const tex = ctx.texture2D({})
...
ctx.dispose(tex)
property info type
res resource to be deleted ctx.Buffer, ctx.Framebuffer, ctx.Pass, ctx.Pipeline, ctx.Program, ctx.Query, ctx.Texture

Note: Framebuffers are ref counted and released by Pass, Programs are also ref counted and released by Pipeline

Capabilities

Get capabilities and extensions availability.

const maxTextureSize = ctx.maxTextureSize
property info type
maxColorAttachments gl.getParameter('MAX_COLOR_ATTACHMENTS') or gl.getParameter(ext.MAX_COLOR_ATTACHMENTS_WEBGL) Number
maxTextureImageUnits gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) Number
maxVertexTextureImageUnits gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS) Number
maxTextureSize gl.getParameter(gl.MAX_TEXTURE_SIZE) Number
maxCubeMapTextureSize gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE) Number
instancedArrays false Boolean
instancing false (deprecated) Boolean
elementIndexUint32 !!gl.getExtension('OES_element_index_uint') Boolean
standardDerivatives !!gl.getExtension('OES_standard_derivatives') Boolean
depthTexture !!gl.getExtension('WEBGL_depth_texture') Boolean
shaderTextureLod !!gl.getExtension('EXT_shader_texture_lod') Boolean
textureFloat !!gl.getExtension('OES_texture_float') Boolean
textureFloatLinear !!gl.getExtension('OES_texture_float_linear') Boolean
textureHalfFloat !!gl.getExtension('OES_texture_half_float') Boolean
textureHalfFloatLinear !!gl.getExtension('OES_texture_half_float_linear') Boolean
textureFilterAnisotropic !!gl.getExtension('EXT_texture_filter_anisotropic') Boolean

Enums

ctx.BlendFactor

const BlendFactor = {
  One: gl.ONE,
  Zero: gl.ZERO,
  SrcAlpha: gl.SRC_ALPHA,
  OneMinusSrcAlpha: gl.ONE_MINUS_SRC_ALPHA,
  DstAlpha: gl.DST_ALPHA,
  OneMinusDstAlpha: gl.ONE_MINUS_DST_ALPHA,
  SrcColor: gl.SRC_COLOR,
  OneMinusSrcColor: gl.ONE_MINUS_SRC_COLOR,
  DstColor: gl.DST_COLOR,
  OneMinusDstColor: gl.ONE_MINUS_DST_COLOR
}

ctx.CubemapFace

const CubemapFace = {
  PositiveX: gl.TEXTURE_CUBE_MAP_POSITIVE_X,
  NegativeX: gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
  PositiveY: gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
  NegativeY: gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
  PositiveZ: gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
  NegativeZ: gl.TEXTURE_CUBE_MAP_NEGATIVE_Z
}

ctx.DataType

const DataType = {
  Float32: gl.FLOAT,
  Uint8: gl.UNSIGNED_BYTE,
  Uint16: gl.UNSIGNED_SHORT,
  Uint32: gl.UNSIGNED_INT
}

ctx.DepthFunc

const DepthFunc = {
  Never: gl.NEVER,
  Less: gl.LESS,
  Equal: gl.EQUAL,
  LessEqual: gl.LEQUAL,
  Greater: gl.GREATER,
  NotEqual: gl.NOTEQUAL,
  GreaterEqual: gl.GEQUAL,
  Always: gl.ALWAYS
}

ctx.Face

const Face = {
  Front: gl.FRONT,
  Back: gl.BACK,
  FrontAndBack: gl.FRONT_AND_BACK
}

ctx.PixelFormat

const PixelFormat = {
  RGBA8: 'rgba8', // gl.RGBA + gl.UNSIGNED_BYTE
  RGBA32F: 'rgba32f', // gl.RGBA + gl.FLOAT
  RGBA16F: 'rgba16f', // gl.RGBA + gl.HALF_FLOAT
  R32F: 'r32f', // gl.ALPHA + gl.FLOAT
  R16F: 'r16f', // gl.ALPHA + gl.HALF_FLOAT
  Depth: 'depth', // gl.DEPTH_COMPONENT + gl.UNSIGNED_SHORT
  Depth16: 'depth16', // gl.DEPTH_COMPONENT + gl.UNSIGNED_SHORT
  Depth24: 'depth24' // gl.DEPTH_COMPONENT + gl.UNSIGNED_INT
}

ctx.Primitive

const Primitive = {
  Points: gl.POINTS,
  Lines: gl.LINES,
  LineStrip: gl.LINE_STRIP,
  Triangles: gl.TRIANGLES,
  TriangleStrip: gl.TRIANGLE_STRIP
}

ctx.Encoding

const Encoding = {
  Linear: 1,
  Gamma: 2,
  SRGB: 3,
  RGBM: 4
}

ctx.Usage

const Usage = {
  StaticDraw: gl.STATIC_DRAW,
  DynamicDraw: gl.DYNAMIC_DRAW,
  StreamDraw: gl.STREAM_DRAW
}

ctx.Wrap

const Wrap = {
  ClampToEdge: gl.CLAMP_TO_EDGE,
  Repeat: gl.REPEAT
}

ctx.QueryTarget

const QueryTarget = {
  TimeElapsed: gl.TIME_ELAPSED
}

ctx.QueryState

const QueryState = {
  Ready: 'ready',
  Active: 'active',
  Pending: 'pending'
}

License

MIT, see LICENSE.md for details.

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

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]

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.

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]/

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:

  • ?

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)
})

Disable logs

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

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
    })

Verify command props

E.g. it should be illegal to call

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

as primitive belongs to pipeline

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

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 })

Verify pipeline parameters

E.g. this should crash

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

as it should be ctx.BlendFactor.SrcAlpha

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

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

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)

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)
        }
      }

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.

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.

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?

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?

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?

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.