Ver código fonte

wip, framebuffer, renderbuffer for render-target

Alexander Rose 6 anos atrás
pai
commit
663fd039f0

+ 10 - 0
src/mol-gl/webgl/context.ts

@@ -61,11 +61,16 @@ type Extensions = {
 export interface Context {
     gl: WebGLRenderingContext
     extensions: Extensions
+
     shaderCache: ShaderCache
     programCache: ProgramCache
+
     bufferCount: number
+    framebufferCount: number
+    renderbufferCount: number
     textureCount: number
     vaoCount: number
+
     readPixels: (x: number, y: number, width: number, height: number, buffer: Uint8Array) => void
     unbindFramebuffer: () => void
     destroy: () => void
@@ -95,11 +100,16 @@ export function createContext(gl: WebGLRenderingContext): Context {
     return {
         gl,
         extensions: { angleInstancedArrays, standardDerivatives, oesElementIndexUint, oesVertexArrayObject },
+
         shaderCache,
         programCache,
+
         bufferCount: 0,
+        framebufferCount: 0,
+        renderbufferCount: 0,
         textureCount: 0,
         vaoCount: 0,
+
         readPixels: (x: number, y: number, width: number, height: number, buffer: Uint8Array) => {
             if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) {
                 gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buffer)

+ 43 - 0
src/mol-gl/webgl/framebuffer.ts

@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Context } from './context'
+import { idFactory } from 'mol-util/id-factory';
+
+const getNextFramebufferId = idFactory()
+
+export interface Framebuffer {
+    readonly id: number
+
+    bind: () => void
+    destroy: () => void
+}
+
+export function createFramebuffer (ctx: Context): Framebuffer {
+    const { gl } = ctx
+    const _framebuffer = gl.createFramebuffer()
+    if (_framebuffer === null) {
+        throw new Error('Could not create WebGL framebuffer')
+    }
+
+    let destroyed = false
+    ctx.framebufferCount += 1
+
+    return {
+        id: getNextFramebufferId(),
+
+        bind: () => {
+            gl.bindFramebuffer(gl.FRAMEBUFFER, _framebuffer)
+        },
+
+        destroy: () => {
+            if (destroyed) return
+            gl.deleteFramebuffer(_framebuffer)
+            destroyed = true
+            ctx.framebufferCount -= 1
+        }
+    }
+}

+ 69 - 0
src/mol-gl/webgl/render-target.ts

@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Context } from './context'
+import { idFactory } from 'mol-util/id-factory';
+import { createTexture } from './texture';
+import { createFramebuffer } from './framebuffer';
+// import { createRenderbuffer } from './renderbuffer';
+
+const getNextRenderTargetId = idFactory()
+
+export interface RenderTarget {
+    readonly id: number
+
+    bind: () => void
+    setSize: (width: number, height: number) => void
+    readPixels: (x: number, y: number, width: number, height: number, buffer: Uint8Array) => void
+    destroy: () => void
+}
+
+export function createRenderTarget (ctx: Context, _width: number, _height: number): RenderTarget {
+    const { gl } = ctx
+
+    const targetTexture = createTexture(ctx, 'rgba', 'ubyte')
+    targetTexture.setSize(_width, _height)
+
+    const framebuffer = createFramebuffer(ctx)
+    framebuffer.bind()
+
+    // attach the texture as the first color attachment
+    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, targetTexture.texture, 0);
+
+    // const depthRenderbuffer = createRenderbuffer(ctx)
+    // depthRenderbuffer.bind()
+    // // make a depth buffer and the same size as the targetTexture
+    // gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, targetTexture.width, targetTexture.height);
+    // gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRenderbuffer);
+
+    let destroyed = false
+
+    return {
+        id: getNextRenderTargetId(),
+
+        bind: () => {
+            framebuffer.bind()
+            gl.viewport(0, 0, _width, _height);
+        },
+        setSize: (width: number, height: number) => {
+            _width = width
+            _height = height
+            targetTexture.setSize(_width, _height)
+        },
+        readPixels: (x: number, y: number, width: number, height: number, buffer: Uint8Array) => {
+            framebuffer.bind()
+            ctx.readPixels(x, y, width, height, buffer)
+            ctx.unbindFramebuffer()
+        },
+        destroy: () => {
+            if (destroyed) return
+            targetTexture.destroy()
+            framebuffer.destroy()
+            // depthRenderbuffer.destroy()
+            destroyed = true
+        }
+    }
+}

+ 43 - 0
src/mol-gl/webgl/renderbuffer.ts

@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Context } from './context'
+import { idFactory } from 'mol-util/id-factory';
+
+const getNextRenderbufferId = idFactory()
+
+export interface Renderbuffer {
+    readonly id: number
+
+    bind: () => void
+    destroy: () => void
+}
+
+export function createRenderbuffer (ctx: Context): Renderbuffer {
+    const { gl } = ctx
+    const _renderbuffer = gl.createRenderbuffer()
+    if (_renderbuffer === null) {
+        throw new Error('Could not create WebGL renderbuffer')
+    }
+
+    let destroyed = false
+    ctx.renderbufferCount += 1
+
+    return {
+        id: getNextRenderbufferId(),
+
+        bind: () => {
+            gl.bindRenderbuffer(gl.RENDERBUFFER, _renderbuffer)
+        },
+
+        destroy: () => {
+            if (destroyed) return
+            gl.deleteRenderbuffer(_renderbuffer)
+            destroyed = true
+            ctx.framebufferCount -= 1
+        }
+    }
+}