Framebuffer: allow usage of texture arrays and changing type of depth texture.

This commit is contained in:
Alberto Torres 2024-09-10 00:59:16 +02:00
parent 17d6ccc32d
commit 67f009c157

View file

@ -44,11 +44,15 @@ proc newFramebuffer*(engine: MyouEngine,
depth_only = false, depth_only = false,
filter: TextureFilter = Linear, filter: TextureFilter = Linear,
tex_type: TextureType = Tex2D, tex_type: TextureType = Tex2D,
depth_filter: TextureFilter = Linear,
depth_tex_type: TextureType = Tex2D,
layer_count = 1,
texture: Texture = nil, texture: Texture = nil,
): Framebuffer ): Framebuffer
proc set_attachments(self: Framebuffer; layer, mipmap_level: int)
proc enable*(self: Framebuffer, rect = none((int32,int32,int32,int32)), proc enable*(self: Framebuffer, rect = none((int32,int32,int32,int32)),
layer = -1, mipmap_level = 0, mark_textures = true): Framebuffer {.discardable.} layer = -1, mipmap_level = 0, mark_textures = true): Framebuffer {.discardable.}
proc clear*(self: Framebuffer, color = vec4(0,0,0,0), clear_color = true, clear_depth = true) {.inline.} proc clear*(self: Framebuffer, color = vec4(0,0,0,0), clear_color = true, clear_depth = true, layer = -1) {.inline.}
proc disable*(self: Framebuffer) proc disable*(self: Framebuffer)
proc draw*(dest: Framebuffer, shader_mat: Material, inputs: seq[Texture], proc draw*(dest: Framebuffer, shader_mat: Material, inputs: seq[Texture],
rect = none((int32,int32,int32,int32)), layer = -1, mipmap_level = 0) rect = none((int32,int32,int32,int32)), layer = -1, mipmap_level = 0)
@ -79,8 +83,17 @@ proc newFramebuffer*(engine: MyouEngine,
depth_only = false, depth_only = false,
filter: TextureFilter = Linear, filter: TextureFilter = Linear,
tex_type: TextureType = Tex2D, tex_type: TextureType = Tex2D,
depth_filter: TextureFilter = Linear,
depth_tex_type: TextureType = Tex2D,
layer_count = 1,
texture: Texture = nil, texture: Texture = nil,
): Framebuffer = ): Framebuffer =
assert Tex3D notin [tex_type, depth_tex_type],
"Tex3D framebuffer not supported"
assert TexExternal notin [tex_type, depth_tex_type],
"TexExternal framebuffer not supported"
let self = new Framebuffer let self = new Framebuffer
# TODO: detect support for float textures and framebuffers in renderer # TODO: detect support for float textures and framebuffers in renderer
if width == 0 or height == 0: if width == 0 or height == 0:
@ -97,7 +110,8 @@ proc newFramebuffer*(engine: MyouEngine,
if self.texture != nil: if self.texture != nil:
# TODO: rely on destructor instead # TODO: rely on destructor instead
self.texture.destroy() self.texture.destroy()
self.texture = engine.newTexture("fb_tex", width, height, 1, format, tex_type=tex_type, filter=filter) self.texture = engine.newTexture("fb_tex", width, height,
layer_count, format, tex_type=tex_type, filter=filter)
# TODO: set as loaded only after having rendered something? # TODO: set as loaded only after having rendered something?
self.texture.loaded = true self.texture.loaded = true
self.texture.setExtrapolation Clamp self.texture.setExtrapolation Clamp
@ -113,24 +127,16 @@ proc newFramebuffer*(engine: MyouEngine,
self.depth_texture.destroy() self.depth_texture.destroy()
self.depth_texture = nil self.depth_texture = nil
if depth_type == DepthTexture: if depth_type == DepthTexture:
# TODO: configure depth tex type? self.depth_texture = engine.newTexture("fb_depth", width, height,
self.depth_texture = engine.newTexture("fb_depth", width, height, 1, depth_format, filter=Linear) layer_count, depth_format, tex_type=depth_tex_type,
filter=depth_filter)
self.depth_texture.loaded = true self.depth_texture.loaded = true
var fb, rb: GLuint var fb, rb: GLuint
glGenFramebuffers(1, fb.addr) glGenFramebuffers(1, fb.addr)
self.framebuffer = fb self.framebuffer = fb
glBindFramebuffer(GL_FRAMEBUFFER, fb) glBindFramebuffer(GL_FRAMEBUFFER, fb)
let target = case tex_type: self.set_attachments(0, 0)
of Tex2D: GL_TEXTURE_2D if depth_type == DepthRenderBuffer:
of TexCube: GL_TEXTURE_CUBE_MAP_POSITIVE_X
of Tex2DArray: GL_TEXTURE_2D_ARRAY
of Tex3D: raise ValueError.newException "Tex3D framebuffer not supported"
of TexExternal: raise ValueError.newException "TexExternal framebuffer not supported"
if self.texture != nil:
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, self.texture.storage.tex, 0)
if depth_type == DepthTexture:
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, self.depth_texture.storage.tex, 0)
elif depth_type == DepthRenderBuffer:
glGenRenderbuffers(1, rb.addr) glGenRenderbuffers(1, rb.addr)
self.render_buffer = rb self.render_buffer = rb
glBindRenderbuffer(GL_RENDERBUFFER, rb) glBindRenderbuffer(GL_RENDERBUFFER, rb)
@ -150,6 +156,23 @@ proc newFramebuffer*(engine: MyouEngine,
engine.all_framebuffers.add(self) engine.all_framebuffers.add(self)
return self return self
proc set_attachments(self: Framebuffer; layer, mipmap_level: int) =
let attachments = [GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT]
for i,tex in [self.texture, self.depth_texture]:
if tex != nil:
if tex.tex_type == Tex2DArray:
assert layer >= 0, "Texture array layer must be specified"
glFramebufferTextureLayer(GL_FRAMEBUFFER, attachments[i],
tex.storage.tex, mipmap_level.GLint, layer.GLint)
elif tex.tex_type == TexCube:
assert layer >= 0, "Texture cube side must be specified"
glFramebufferTexture2D(GL_FRAMEBUFFER, attachments[i],
(GL_TEXTURE_CUBE_MAP_POSITIVE_X.int + layer).GLenum,
tex.storage.tex, mipmap_level.GLint)
elif self.current_mipmap_level != mipmap_level:
glFramebufferTexture2D(GL_FRAMEBUFFER, attachments[i],
tex.storage.target, tex.storage.tex, mipmap_level.GLint)
proc enable*(self: Framebuffer, rect = none((int32,int32,int32,int32)), proc enable*(self: Framebuffer, rect = none((int32,int32,int32,int32)),
layer = -1, mipmap_level = 0, mark_textures = true): Framebuffer {.discardable.} = layer = -1, mipmap_level = 0, mark_textures = true): Framebuffer {.discardable.} =
self.has_mipmap = false self.has_mipmap = false
@ -174,14 +197,7 @@ proc enable*(self: Framebuffer, rect = none((int32,int32,int32,int32)),
when not defined(opengl_es): when not defined(opengl_es):
if self.use_sRGB: if self.use_sRGB:
glEnable(GL_FRAMEBUFFER_SRGB) glEnable(GL_FRAMEBUFFER_SRGB)
if self.texture != nil: self.set_attachments(layer, mipmap_level)
if layer != -1:
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
(GL_TEXTURE_CUBE_MAP_POSITIVE_X.int + layer).GLenum,
self.texture.storage.tex, mipmap_level.GLint)
elif self.current_mipmap_level != mipmap_level:
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
self.texture.storage.target, self.texture.storage.tex, mipmap_level.GLint)
self.current_mipmap_level = mipmap_level self.current_mipmap_level = mipmap_level
active_layer = layer active_layer = layer
glViewport(left, bottom, width, height) glViewport(left, bottom, width, height)
@ -199,8 +215,8 @@ proc enable*(self: Framebuffer, rect = none((int32,int32,int32,int32)),
# filters_should_blend = self.filters_should_blend # filters_should_blend = self.filters_should_blend
return self return self
proc clear*(self: Framebuffer, color = vec4(0,0,0,0), clear_color = true, clear_depth = true) {.inline.} = proc clear*(self: Framebuffer, color = vec4(0,0,0,0), clear_color = true, clear_depth = true, layer = -1) {.inline.} =
self.enable() self.enable(layer=layer)
var bits: uint32 var bits: uint32
if clear_color: if clear_color:
glClearColor(color.r, color.g, color.b, color.a) glClearColor(color.r, color.g, color.b, color.a)