goxjs / gl

Go cross-platform OpenGL bindings.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unable to Get Current Frame Buffer In Webgl

tanema opened this issue · comments

There are points where I need to get the current frame buffer, bind another, then bind the first one however right now it is not really possible to do that in web gl. Normally I would call gl.GetInteger(gl.FRAMEBUFFER_BINDING) but that always returns 0 and wont allow me to bind to it. According to this https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindFramebuffer I would need to call getParameter on the context to get the current frame buffer. It is hard to name a solution to this since adding a GetCurrentFrameBuffer() method would change the whole api. Also I was thinking exposing the context so I can call any function on it but again that does not work for a uniform API.

Let me know if I have missed a solution, that could be possible as well.

gl.GetInteger(gl.FRAMEBUFFER_BINDING) should work. In the WebGL implementation, it just does gl.getParameter(gl.FRAMEBUFFER_BINDING);, see:

gl/gl_webgl.go

Lines 308 to 310 in f020688

func GetInteger(pname Enum) int {
return c.Call("getParameter", pname).Int()
}

Which seems to be what https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindFramebuffer recommends. Any ideas why it'd return 0?

I'll be able to look more into this later.

The actual error is Uncaught TypeError: Failed to execute 'bindFramebuffer' on 'WebGLRenderingContext': parameter 2 is not of type 'WebGLFramebuffer'. So I believe that is expecting an actual WebGLFramebuffer object instead of the int that I am trying to pass. When I run it in the browser manually I get this

gl.createFramebuffer() //-> WebGLFramebuffer {}

So I think passing in an int like that is not allowed. It calls the correct function yes but then it is cast to an int which will always be zero I imagine because objects don't cast to ints.

Right, BindFramebuffer (of WebGL implementation) expects a Framebuffer:

func BindFramebuffer(target Enum, fb Framebuffer) {
    c.Call("bindFramebuffer", target, fb.Object)
}

Which is what you get from CreateFramebuffer.

But to get the currently bound framebuffer, you'd need something like this (which currently doesn't exist):

func GetFramebufferParameter(pname Enum) Framebuffer {
    return Framebuffer{Object: c.Call("getParameter", pname)}
}

If possible, you could just use/remember the value from CreateFramebuffer... Othewise, I need to think about how be able to expose getting currently bound framebuffer in a non-webgl-specific API.

Keeping track of the bound frame buffer does not allow you to get the initial/default frame buffer which I use for unbinding frame buffers. However I wouldn't say I am an expert with opengl so maybe that is not normal usage.

This is a divergence between WebGL and OpenGL (ES) APIs. OpenGL uses integer IDs for framebuffers, so you can get a current one with glGetInteger(GL_FRAMEBUFFER_BINDING) which is good to use with glBindFramebuffer. In WebGL, you do gl.getParameter(gl.FRAMEBUFFER_BINDING); which gives you a WebGLFramebuffer object, which is good to use with gl.bindFramebuffer.

The only cross-platform solution I see is to add new custom methods to get bound objects. E.g.:

// WebGL implementation.
func GetBoundFramebuffer() Framebuffer {
    return Framebuffer{Object: c.Call("getParameter", FRAMEBUFFER_BINDING)}
}

// OpenGL ES implementation.
func GetBoundFramebuffer() Framebuffer {
    var b Framebuffer
    gl.GetIntegerv(FRAMEBUFFER_BINDING, &b.Value)
    return b
}

And similar methods for other structs in https://github.com/goxjs/gl/blob/master/types_webgl.go.

Can anyone thing of any better ways to resolve this?

Seems like a reasonable solution, however a solution that would require some documentation on the readme for Gotchyas or something like that.

Would having those methods in godoc not be enough?

Do you want to make it a PR?

Re: Docs, It's up to you I guess, I just figured that since the api has been consistent with openGL and this has been the only exception that it might bear mentioning on the project page.

I will create a pull request tonight after work for this. Regarding that I was going to make a PR for the webgl method that was confirmed to work. Do you mind if I put that in this PR too or do you want it separate for commit log reasons?

I just figured that since the api has been consistent with openGL and this has been the only exception that it might bear mentioning on the project page.

Makes sense. I just couldn't think of how to phrase this section eloquently, and I prefer to keep the docs high quality. I don't consider this a "gotcha", it's just a part of the cross-platform GL API.

Single PR is fine. I can split it into separate commits when merging if I want. Feel free to do what's easier for you. Thanks!