diff --git a/gpu/backend.go b/gpu/backend.go index 6006867d..88e30b9e 100644 --- a/gpu/backend.go +++ b/gpu/backend.go @@ -20,7 +20,7 @@ type Backend interface { IsTimeContinuous() bool NewTexture(format TextureFormat, width, height int, minFilter, magFilter TextureFilter, bindings BufferBinding) (Texture, error) DefaultFramebuffer() Framebuffer - NewFramebuffer(tex Texture) (Framebuffer, error) + NewFramebuffer(tex Texture, depthBits int) (Framebuffer, error) NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error) NewBuffer(typ BufferBinding, size int) (Buffer, error) NewProgram(vertexShader, fragmentShader ShaderSources) (Program, error) diff --git a/gpu/gl/backend.go b/gpu/gl/backend.go index 86ae539c..a5e38f27 100644 --- a/gpu/gl/backend.go +++ b/gpu/gl/backend.go @@ -54,11 +54,15 @@ type gpuTexture struct { backend *Backend obj Texture triple textureTriple + width int + height int } type gpuFramebuffer struct { - funcs Functions - obj Framebuffer + funcs Functions + obj Framebuffer + hasDepth bool + depthBuf Renderbuffer } type gpuBuffer struct { @@ -162,7 +166,7 @@ func (b *Backend) IsTimeContinuous() bool { return b.funcs.GetInteger(GPU_DISJOINT_EXT) == FALSE } -func (b *Backend) NewFramebuffer(tex gpu.Texture) (gpu.Framebuffer, error) { +func (b *Backend) NewFramebuffer(tex gpu.Texture, depthBits int) (gpu.Framebuffer, error) { glErr(b.funcs) gltex := tex.(*gpuTexture) fb := b.funcs.CreateFramebuffer() @@ -173,6 +177,24 @@ func (b *Backend) NewFramebuffer(tex gpu.Texture) (gpu.Framebuffer, error) { return nil, err } b.funcs.FramebufferTexture2D(FRAMEBUFFER, COLOR_ATTACHMENT0, TEXTURE_2D, gltex.obj, 0) + if depthBits > 0 { + size := Enum(DEPTH_COMPONENT16) + switch { + case depthBits > 24: + size = DEPTH_COMPONENT32F + case depthBits > 16: + size = DEPTH_COMPONENT24 + } + depthBuf := b.funcs.CreateRenderbuffer() + b.funcs.BindRenderbuffer(RENDERBUFFER, depthBuf) + b.funcs.RenderbufferStorage(RENDERBUFFER, size, gltex.width, gltex.height) + fbo.depthBuf = depthBuf + fbo.hasDepth = true + if err := glErr(b.funcs); err != nil { + fbo.Release() + return nil, err + } + } if st := b.funcs.CheckFramebufferStatus(FRAMEBUFFER); st != FRAMEBUFFER_COMPLETE { fbo.Release() return nil, fmt.Errorf("incomplete framebuffer, status = 0x%x, err = %d", st, b.funcs.GetError()) @@ -186,7 +208,7 @@ func (b *Backend) DefaultFramebuffer() gpu.Framebuffer { func (b *Backend) NewTexture(format gpu.TextureFormat, width, height int, minFilter, magFilter gpu.TextureFilter, binding gpu.BufferBinding) (gpu.Texture, error) { glErr(b.funcs) - tex := &gpuTexture{backend: b, obj: b.funcs.CreateTexture()} + tex := &gpuTexture{backend: b, obj: b.funcs.CreateTexture(), width: width, height: height} switch format { case gpu.TextureFormatFloat: tex.triple = b.floatTriple @@ -578,6 +600,9 @@ func (f *gpuFramebuffer) Invalidate() { func (f *gpuFramebuffer) Release() { f.funcs.DeleteFramebuffer(f.obj) + if f.hasDepth { + f.funcs.DeleteRenderbuffer(f.depthBuf) + } } func toTexFilter(f gpu.TextureFilter) int { diff --git a/gpu/gl/gl.go b/gpu/gl/gl.go index 51b34e82..8dcb757f 100644 --- a/gpu/gl/gl.go +++ b/gpu/gl/gl.go @@ -17,6 +17,8 @@ const ( DEPTH_BUFFER_BIT = 0x100 DEPTH_ATTACHMENT = 0x8d00 DEPTH_COMPONENT16 = 0x81a5 + DEPTH_COMPONENT24 = 0x81A6 + DEPTH_COMPONENT32F = 0x8CAC DEPTH_TEST = 0xb71 DST_COLOR = 0x306 ELEMENT_ARRAY_BUFFER = 0x8893 @@ -91,6 +93,7 @@ type Functions interface { BindAttribLocation(p Program, a Attrib, name string) BindBuffer(target Enum, b Buffer) BindFramebuffer(target Enum, fb Framebuffer) + BindRenderbuffer(target Enum, fb Renderbuffer) BindTexture(target Enum, t Texture) BlendEquation(mode Enum) BlendFunc(sfactor, dfactor Enum) @@ -104,12 +107,14 @@ type Functions interface { CreateFramebuffer() Framebuffer CreateProgram() Program CreateQuery() Query + CreateRenderbuffer() Renderbuffer CreateShader(ty Enum) Shader CreateTexture() Texture DeleteBuffer(v Buffer) DeleteFramebuffer(v Framebuffer) DeleteProgram(p Program) DeleteQuery(query Query) + DeleteRenderbuffer(r Renderbuffer) DeleteShader(s Shader) DeleteTexture(v Texture) DepthFunc(f Enum) @@ -134,6 +139,7 @@ type Functions interface { GetUniformLocation(p Program, name string) Uniform InvalidateFramebuffer(target, attachment Enum) LinkProgram(p Program) + RenderbufferStorage(target, internalformat Enum, width, height int) ShaderSource(s Shader, src string) TexImage2D(target Enum, level int, internalFormat int, width, height int, format, ty Enum, data []byte) TexParameteri(target, pname Enum, param int) diff --git a/gpu/path.go b/gpu/path.go index 72be166a..2ca2f892 100644 --- a/gpu/path.go +++ b/gpu/path.go @@ -213,7 +213,7 @@ func (s *fboSet) resize(ctx Backend, sizes []image.Point) { } tex, err := ctx.NewTexture(TextureFormatFloat, sz.X, sz.Y, FilterNearest, FilterNearest, BufferBindingTexture|BufferBindingFramebuffer) - fbo, err := ctx.NewFramebuffer(tex) + fbo, err := ctx.NewFramebuffer(tex, 0) if err != nil { panic(err) }