Skip to content

Problematic to bind NULL values in webgl #20

@ptxmac

Description

@ptxmac

A typical pattern in WebGL is to bind a "null" value.

E.g.

gl.bindFramebuffer(gl.FRAMEBUFFER, null);

According to the documentation, this is how to reset the current FBO back to the canvas:

framebuffer
A WebGLFramebuffer object to bind, or null for binding the Canvas or OffscreenCanvas object associated with the rendering context.

Because of how the types are implemented in WebGL, this is not elegant to do

Preferred pattern:

gl.BindFramebuffer(webgl.FRAMEBUFFER, webgl.FramebufferFromJS(js.Null()))

Unfortunately this will panic

Problem

From webgl_js.go:

// FramebufferFromJS is casting a js.Value into Framebuffer.
func FramebufferFromJS(value js.Value) *Framebuffer {
	if typ := value.Type(); typ == js.TypeNull || typ == js.TypeUndefined {
		return nil
	}
	ret := &Framebuffer{}
	ret.Value_JS = value
	return ret
}

In the case of js.Null() this returns a nil pointer, which we try to pass to BindFramebuffer

func (_this *RenderingContext) BindFramebuffer(target uint, framebuffer *Framebuffer) {
	var (
		_args [2]interface{}
		_end  int
	)
	_p0 := target
	_args[0] = _p0
	_end++
	_p1 := framebuffer.JSValue()
	_args[1] = _p1
	_end++
	_this.Value_JS.Call("bindFramebuffer", _args[0:_end]...)
	return
}

Unfortunately, this code expected a non-nil Framebuffer, and will panic

Workaround

It's possible to work around it by manually creating the Framebuffer object, but it's not elegant:

nullFBO := &webgl.Framebuffer{Object: webgl.Object{
	Value_JS: js.Null(),
}}
gl.BindFramebuffer(webgl.FRAMEBUFFER, nullFBO)

Solutions

I can think of a couple of solutions:

  1. Simple remove the IsNull check from the *FromJS methods and allow the creation of null objects.
    gl.BindFramebuffer(webgl.FRAMEBUFFER, webgl.FramebufferFromJS(js.Null()))
  2. Create global Null versions of objects.
    gl.BindFramebuffer(webgl.FRAMEBUFFER, webgl.NullFramebuffer)
  3. Change the bind methods and convert nil to js.Null
    gl.BindFramebuffer(webgl.FRAMEBUFFER, nil)

Notes

From my OpenGL understanding this pattern is used for all objects. I.e. all Bind* and Use* methods (gl.bindTexture/gl.useProgram/gl.bindBuffer etc)

The mozdev webgl documentation is unfortunately a little lacking, and only framebuffers are explicitly mentioned to be null - but I assume it also holds true for any other objects

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions