Add support for MSAA, both in the OpenGL context and in any framebuffer.
This commit is contained in:
parent
a38138582e
commit
6f21f9fa87
9 changed files with 159 additions and 19 deletions
|
@ -48,6 +48,7 @@ proc newFramebuffer*(engine: MyouEngine,
|
||||||
depth_tex_type: TextureType = Tex2D,
|
depth_tex_type: TextureType = Tex2D,
|
||||||
layer_count = 1,
|
layer_count = 1,
|
||||||
texture: Texture = nil,
|
texture: Texture = nil,
|
||||||
|
samples = 1,
|
||||||
): Framebuffer
|
): Framebuffer
|
||||||
proc set_attachments(self: Framebuffer; layer, mipmap_level: int)
|
proc set_attachments(self: Framebuffer; layer, mipmap_level: int)
|
||||||
proc set_texture*(self: Framebuffer, texture: Texture)
|
proc set_texture*(self: Framebuffer, texture: Texture)
|
||||||
|
@ -57,10 +58,14 @@ proc clear*(self: Framebuffer, color = vec4(0,0,0,0), clear_color = true, clear_
|
||||||
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)
|
||||||
|
proc blit_to*(self: Framebuffer, dest: Framebuffer,
|
||||||
|
src_rect = none((int32,int32,int32,int32)),
|
||||||
|
dst_rect = none((int32,int32,int32,int32)))
|
||||||
proc get_framebuffer_status_string*(self: Framebuffer): string
|
proc get_framebuffer_status_string*(self: Framebuffer): string
|
||||||
proc generate_mipmap*(self: Framebuffer, custom_shader: Material = nil)
|
proc generate_mipmap*(self: Framebuffer, custom_shader: Material = nil)
|
||||||
proc destroy*(self: Framebuffer, remove_from_context: bool = true)
|
proc destroy*(self: Framebuffer, remove_from_context: bool = true)
|
||||||
proc newMainFramebuffer*(engine: MyouEngine): Framebuffer
|
proc newMainFramebuffer*(engine: MyouEngine): Framebuffer
|
||||||
|
proc resize*(self: Framebuffer, width, height: int, samples = 0)
|
||||||
# End forward declarations
|
# End forward declarations
|
||||||
|
|
||||||
import std/strformat
|
import std/strformat
|
||||||
|
@ -88,6 +93,7 @@ proc newFramebuffer*(engine: MyouEngine,
|
||||||
depth_tex_type: TextureType = Tex2D,
|
depth_tex_type: TextureType = Tex2D,
|
||||||
layer_count = 1,
|
layer_count = 1,
|
||||||
texture: Texture = nil,
|
texture: Texture = nil,
|
||||||
|
samples = 1,
|
||||||
): Framebuffer =
|
): Framebuffer =
|
||||||
|
|
||||||
assert Tex3D notin [tex_type, depth_tex_type],
|
assert Tex3D notin [tex_type, depth_tex_type],
|
||||||
|
@ -104,11 +110,17 @@ proc newFramebuffer*(engine: MyouEngine,
|
||||||
self.height = height
|
self.height = height
|
||||||
self.layer_count = layer_count
|
self.layer_count = layer_count
|
||||||
self.format = format
|
self.format = format
|
||||||
|
self.depth_format = depth_format
|
||||||
self.depth_type = depth_type
|
self.depth_type = depth_type
|
||||||
|
self.samples = samples
|
||||||
var tex_type = tex_type
|
var tex_type = tex_type
|
||||||
# self.filters_should_blend = false
|
# self.filters_should_blend = false
|
||||||
|
if samples > 1:
|
||||||
|
assert depth_type != DepthTexture,
|
||||||
|
"You can't use DepthTexture with a multisample framebuffer"
|
||||||
|
|
||||||
if not depth_only:
|
if not depth_only:
|
||||||
if texture == nil:
|
if texture == nil and samples <= 1:
|
||||||
if self.texture != nil:
|
if self.texture != nil:
|
||||||
# TODO: rely on destructor instead
|
# TODO: rely on destructor instead
|
||||||
self.texture.destroy()
|
self.texture.destroy()
|
||||||
|
@ -137,14 +149,24 @@ proc newFramebuffer*(engine: MyouEngine,
|
||||||
glGenFramebuffers(1, fb.addr)
|
glGenFramebuffers(1, fb.addr)
|
||||||
self.framebuffer = fb
|
self.framebuffer = fb
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fb)
|
glBindFramebuffer(GL_FRAMEBUFFER, fb)
|
||||||
self.set_attachments(0, 0)
|
if not depth_only and texture == nil and samples > 1:
|
||||||
|
glGenRenderbuffers(1, self.color_render_buffer.addr)
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, self.color_render_buffer)
|
||||||
|
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples.GLsizei, format.toInternalFormat, width.GLsizei, height.GLsizei)
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, self.color_render_buffer)
|
||||||
if depth_type == DepthRenderBuffer:
|
if depth_type == DepthRenderBuffer:
|
||||||
glGenRenderbuffers(1, rb.addr)
|
glGenRenderbuffers(1, rb.addr)
|
||||||
self.render_buffer = rb
|
self.depth_render_buffer = rb
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, rb)
|
glBindRenderbuffer(GL_RENDERBUFFER, rb)
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, depth_format.toInternalFormat, width.GLsizei, height.GLsizei)
|
if samples > 1:
|
||||||
|
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples.GLsizei, depth_format.toInternalFormat, width.GLsizei, height.GLsizei)
|
||||||
|
else:
|
||||||
|
glRenderbufferStorage(GL_RENDERBUFFER, depth_format.toInternalFormat, width.GLsizei, height.GLsizei)
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb)
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb)
|
||||||
|
self.current_mipmap_level = -1 # force attachment with the call below
|
||||||
|
self.set_attachments(0, 0)
|
||||||
self.is_complete = glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE
|
self.is_complete = glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE
|
||||||
|
doAssert self.is_complete, "Error creating framebuffer: " & self.get_framebuffer_status_string
|
||||||
self.has_mipmap = false
|
self.has_mipmap = false
|
||||||
# self.last_viewport = nil
|
# self.last_viewport = nil
|
||||||
if self.texture != nil:
|
if self.texture != nil:
|
||||||
|
@ -163,17 +185,24 @@ proc set_attachments(self: Framebuffer; layer, mipmap_level: int) =
|
||||||
for i,tex in [self.texture, self.depth_texture]:
|
for i,tex in [self.texture, self.depth_texture]:
|
||||||
if tex != nil:
|
if tex != nil:
|
||||||
if tex.tex_type == Tex2DArray:
|
if tex.tex_type == Tex2DArray:
|
||||||
|
assert self.samples == 1, "unsupported"
|
||||||
assert layer >= 0, "Texture array layer must be specified"
|
assert layer >= 0, "Texture array layer must be specified"
|
||||||
glFramebufferTextureLayer(GL_FRAMEBUFFER, attachments[i],
|
glFramebufferTextureLayer(GL_FRAMEBUFFER, attachments[i],
|
||||||
tex.storage.tex.GLuint, mipmap_level.GLint, layer.GLint)
|
tex.storage.tex.GLuint, mipmap_level.GLint, layer.GLint)
|
||||||
elif tex.tex_type == TexCube:
|
elif tex.tex_type == TexCube:
|
||||||
assert layer >= 0, "Texture cube side must be specified"
|
assert layer >= 0, "Texture cube side must be specified"
|
||||||
|
assert self.samples == 1, "unsupported"
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachments[i],
|
glFramebufferTexture2D(GL_FRAMEBUFFER, attachments[i],
|
||||||
(GL_TEXTURE_CUBE_MAP_POSITIVE_X.int + layer).GLenum,
|
(GL_TEXTURE_CUBE_MAP_POSITIVE_X.int + layer).GLenum,
|
||||||
tex.storage.tex.GLuint, mipmap_level.GLint)
|
tex.storage.tex.GLuint, mipmap_level.GLint)
|
||||||
elif self.current_mipmap_level != mipmap_level:
|
elif self.current_mipmap_level != mipmap_level:
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachments[i],
|
if self.samples > 1:
|
||||||
tex.storage.target, tex.storage.tex.GLuint, mipmap_level.GLint)
|
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, attachments[i],
|
||||||
|
tex.storage.target, tex.storage.tex.GLuint, mipmap_level.GLint,
|
||||||
|
self.samples.GLsizei)
|
||||||
|
else:
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, attachments[i],
|
||||||
|
tex.storage.target, tex.storage.tex.GLuint, mipmap_level.GLint)
|
||||||
|
|
||||||
proc set_texture*(self: Framebuffer, texture: Texture) =
|
proc set_texture*(self: Framebuffer, texture: Texture) =
|
||||||
if active_buffer == self:
|
if active_buffer == self:
|
||||||
|
@ -291,14 +320,27 @@ proc draw*(dest: Framebuffer, shader_mat: Material, inputs: seq[Texture],
|
||||||
if ubo.name == "EffectShaderInputs":
|
if ubo.name == "EffectShaderInputs":
|
||||||
ubo.unbind()
|
ubo.unbind()
|
||||||
|
|
||||||
|
proc blit_to*(self: Framebuffer, dest: Framebuffer,
|
||||||
|
src_rect = none((int32,int32,int32,int32)),
|
||||||
|
dst_rect = none((int32,int32,int32,int32))) =
|
||||||
|
dest.enable()
|
||||||
|
let (x1, y1, w1, h1) = src_rect.get((0'i32, 0'i32, self.width.int32, self.height.int32))
|
||||||
|
let (x2, y2, w2, h2) = dst_rect.get((0'i32, 0'i32, dest.width.int32, dest.height.int32))
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, self.framebuffer);
|
||||||
|
glBlitFramebuffer(x1, y1, x1+w1, y1+h1, x2, y2, x2+w2, y2+h2,
|
||||||
|
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
proc get_framebuffer_status_string*(self: Framebuffer): string =
|
proc get_framebuffer_status_string*(self: Framebuffer): string =
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, self.framebuffer)
|
glBindFramebuffer(GL_FRAMEBUFFER, self.framebuffer)
|
||||||
let status = glCheckFramebufferStatus(GL_FRAMEBUFFER)
|
let status = glCheckFramebufferStatus(GL_FRAMEBUFFER)
|
||||||
result = case status:
|
result = case status:
|
||||||
of GL_FRAMEBUFFER_COMPLETE: "GL_FRAMEBUFFER_COMPLETE"
|
of GL_FRAMEBUFFER_COMPLETE: "COMPLETE"
|
||||||
of GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"
|
of GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: "INCOMPLETE ATTACHMENT"
|
||||||
of GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"
|
of GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: "INCOMPLETE DIMENSIONS"
|
||||||
of GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"
|
of GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: "INCOMPLETE MISSING ATTACHMENT"
|
||||||
|
of GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: "INCOMPLETE MULTISAMPLE"
|
||||||
|
of GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: "INCOMPLETE LAYER TARGETS"
|
||||||
else:
|
else:
|
||||||
&"Unknown status {status.GLint}"
|
&"Unknown status {status.GLint}"
|
||||||
self.disable()
|
self.disable()
|
||||||
|
@ -351,8 +393,10 @@ proc destroy*(self: Framebuffer, remove_from_context: bool = true) =
|
||||||
self.texture.destroy()
|
self.texture.destroy()
|
||||||
if self.depth_texture != nil:
|
if self.depth_texture != nil:
|
||||||
self.depth_texture.destroy()
|
self.depth_texture.destroy()
|
||||||
if self.render_buffer != 0:
|
if self.color_render_buffer != 0:
|
||||||
glDeleteRenderbuffers(1, self.render_buffer.addr)
|
glDeleteRenderbuffers(1, self.color_render_buffer.addr)
|
||||||
|
if self.depth_render_buffer != 0:
|
||||||
|
glDeleteRenderbuffers(1, self.depth_render_buffer.addr)
|
||||||
glDeleteFramebuffers(1, self.framebuffer.addr)
|
glDeleteFramebuffers(1, self.framebuffer.addr)
|
||||||
if remove_from_context:
|
if remove_from_context:
|
||||||
var index = self.engine.all_framebuffers.find(self)
|
var index = self.engine.all_framebuffers.find(self)
|
||||||
|
@ -365,3 +409,46 @@ proc newMainFramebuffer*(engine: MyouEngine): Framebuffer =
|
||||||
result.framebuffer = 0
|
result.framebuffer = 0
|
||||||
result.is_complete = true
|
result.is_complete = true
|
||||||
result.use_sRGB = not engine.use_glsl_tone_mapping
|
result.use_sRGB = not engine.use_glsl_tone_mapping
|
||||||
|
result.samples = 1
|
||||||
|
|
||||||
|
proc resize*(self: Framebuffer, width, height: int, samples = 0) =
|
||||||
|
if self.framebuffer == 0:
|
||||||
|
# It's the main framebuffer, just update width and height
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
return
|
||||||
|
let samples = if samples != 0: samples else: self.samples
|
||||||
|
if width == self.width and height == self.height and samples == self.samples:
|
||||||
|
# No change needed
|
||||||
|
return
|
||||||
|
|
||||||
|
var depth_only = false
|
||||||
|
var filter = Linear
|
||||||
|
var tex_type = Tex2D
|
||||||
|
var depth_filter = Linear
|
||||||
|
var depth_tex_type = Tex2D
|
||||||
|
if self.texture != nil:
|
||||||
|
filter = self.texture.filter
|
||||||
|
tex_type = self.texture.tex_type
|
||||||
|
elif self.color_render_buffer == 0:
|
||||||
|
depth_only = true
|
||||||
|
if self.depth_texture != nil:
|
||||||
|
depth_filter = self.depth_texture.filter
|
||||||
|
depth_tex_type = self.depth_texture.tex_type
|
||||||
|
|
||||||
|
let new_FB = newFramebuffer(
|
||||||
|
self.engine,
|
||||||
|
width, height, self.format,
|
||||||
|
depth_type = self.depth_type,
|
||||||
|
depth_format = self.depth_format,
|
||||||
|
depth_only = depth_only,
|
||||||
|
filter = filter,
|
||||||
|
tex_type = tex_type,
|
||||||
|
depth_filter = depth_filter,
|
||||||
|
depth_tex_type = depth_tex_type,
|
||||||
|
layer_count = self.layer_count,
|
||||||
|
samples = samples,
|
||||||
|
)
|
||||||
|
self[] = move new_FB[]
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
import ../types
|
import ../types
|
||||||
import ../platform/gl
|
import ../platform/gl
|
||||||
|
import ../postprocessing/effect_shaders
|
||||||
import arr_ref
|
import arr_ref
|
||||||
import vmath except Quat, quat
|
import vmath except Quat, quat
|
||||||
|
|
||||||
|
@ -231,12 +232,19 @@ proc draw_all*(self: RenderManager) =
|
||||||
continue
|
continue
|
||||||
discard screen.platform_switch_screen()
|
discard screen.platform_switch_screen()
|
||||||
screen.pre_draw(screen)
|
screen.pre_draw(screen)
|
||||||
|
let fb = if screen.framebuffer_multisample != nil:
|
||||||
|
screen.framebuffer_multisample
|
||||||
|
else:
|
||||||
|
screen.framebuffer
|
||||||
for viewport in screen.viewports:
|
for viewport in screen.viewports:
|
||||||
let scene = viewport.camera.scene
|
let scene = viewport.camera.scene
|
||||||
if not scene.enabled:
|
if not scene.enabled:
|
||||||
continue
|
continue
|
||||||
# TODO: effect chains which contain effects and passes
|
# TODO: effect chains which contain effects and passes
|
||||||
self.draw_viewport(viewport, viewport.rect_pix, screen.framebuffer, @[0, 1])
|
self.draw_viewport(viewport, viewport.rect_pix, fb, @[0, 1])
|
||||||
|
if fb != screen.framebuffer:
|
||||||
|
fb.blit_to screen.framebuffer
|
||||||
|
|
||||||
screen.post_draw(screen)
|
screen.post_draw(screen)
|
||||||
glUseProgram(0)
|
glUseProgram(0)
|
||||||
glBindVertexArray(0)
|
glBindVertexArray(0)
|
||||||
|
|
|
@ -65,6 +65,7 @@ proc newMyouEngine*(
|
||||||
opengl_es = default_gl_es,
|
opengl_es = default_gl_es,
|
||||||
glsl_version = "",
|
glsl_version = "",
|
||||||
use_glsl_tone_mapping = true,
|
use_glsl_tone_mapping = true,
|
||||||
|
context_msaa_samples = 1,
|
||||||
): MyouEngine
|
): MyouEngine
|
||||||
proc get_builtin_shader_library*(use_cubemap_prefiltering = true): string
|
proc get_builtin_shader_library*(use_cubemap_prefiltering = true): string
|
||||||
proc get_builtin_shader_textures*(): Table[string, Texture]
|
proc get_builtin_shader_textures*(): Table[string, Texture]
|
||||||
|
@ -92,6 +93,7 @@ proc newMyouEngine*(
|
||||||
opengl_es = default_gl_es,
|
opengl_es = default_gl_es,
|
||||||
glsl_version = "",
|
glsl_version = "",
|
||||||
use_glsl_tone_mapping = true,
|
use_glsl_tone_mapping = true,
|
||||||
|
context_msaa_samples = 1,
|
||||||
): MyouEngine =
|
): MyouEngine =
|
||||||
## Creates a Myou Engine instance. You need to call this before you can use
|
## Creates a Myou Engine instance. You need to call this before you can use
|
||||||
## the engine. You also need to call `run <#run,MyouEngine>`_ at the end of
|
## the engine. You also need to call `run <#run,MyouEngine>`_ at the end of
|
||||||
|
@ -137,9 +139,9 @@ proc newMyouEngine*(
|
||||||
# this will call result.renderer.initialize() now or later
|
# this will call result.renderer.initialize() now or later
|
||||||
# but first it will ensure a screen can be created
|
# but first it will ensure a screen can be created
|
||||||
when not defined(nimdoc):
|
when not defined(nimdoc):
|
||||||
init_graphics(result, width, height, title, opengl_version, opengl_es)
|
init_graphics(result, width, height, title, opengl_version, opengl_es, context_msaa_samples)
|
||||||
discard result.newScreen(width, height, title)
|
discard result.newScreen(width, height, title)
|
||||||
|
|
||||||
registerBlendLoader(result)
|
registerBlendLoader(result)
|
||||||
|
|
||||||
proc get_builtin_shader_library*(use_cubemap_prefiltering = true): string =
|
proc get_builtin_shader_library*(use_cubemap_prefiltering = true): string =
|
||||||
|
|
|
@ -147,7 +147,9 @@ var max_messages = 0
|
||||||
proc init_graphics*(engine1: MyouEngine, width, height: int32, title: string,
|
proc init_graphics*(engine1: MyouEngine, width, height: int32, title: string,
|
||||||
opengl_version = 330,
|
opengl_version = 330,
|
||||||
opengl_es = false,
|
opengl_es = false,
|
||||||
|
samples = 1,
|
||||||
) =
|
) =
|
||||||
|
assert samples == 1, "Samples != 1 not supported on this platform yet"
|
||||||
|
|
||||||
engine = engine1
|
engine = engine1
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,9 @@ var max_messages = 0
|
||||||
proc init_graphics*(engine: MyouEngine, width, height: int32, title: string,
|
proc init_graphics*(engine: MyouEngine, width, height: int32, title: string,
|
||||||
opengl_version = 330,
|
opengl_version = 330,
|
||||||
opengl_es = false,
|
opengl_es = false,
|
||||||
|
samples = 1,
|
||||||
) =
|
) =
|
||||||
|
assert samples == 1, "Samples != 1 not supported on this platform yet"
|
||||||
|
|
||||||
let major = opengl_version div 100
|
let major = opengl_version div 100
|
||||||
let minor = opengl_version mod 100 div 10
|
let minor = opengl_version mod 100 div 10
|
||||||
|
|
|
@ -227,7 +227,9 @@ var max_messages = 0
|
||||||
proc init_graphics*(engine: MyouEngine, width, height: int32, title: string,
|
proc init_graphics*(engine: MyouEngine, width, height: int32, title: string,
|
||||||
opengl_version = 330,
|
opengl_version = 330,
|
||||||
opengl_es = false,
|
opengl_es = false,
|
||||||
|
samples = 1,
|
||||||
) =
|
) =
|
||||||
|
assert samples == 1, "Samples != 1 not supported on this platform yet"
|
||||||
assert window != nil
|
assert window != nil
|
||||||
|
|
||||||
let major = opengl_version div 100
|
let major = opengl_version div 100
|
||||||
|
|
|
@ -177,6 +177,7 @@ var max_messages = 0
|
||||||
proc init_graphics*(engine: MyouEngine, width, height: int32, title: string,
|
proc init_graphics*(engine: MyouEngine, width, height: int32, title: string,
|
||||||
opengl_version = 330,
|
opengl_version = 330,
|
||||||
opengl_es = false,
|
opengl_es = false,
|
||||||
|
samples = 1,
|
||||||
) =
|
) =
|
||||||
|
|
||||||
# TODO!! Option to delay this to simulate the situation in mobile platforms
|
# TODO!! Option to delay this to simulate the situation in mobile platforms
|
||||||
|
@ -196,6 +197,8 @@ proc init_graphics*(engine: MyouEngine, width, height: int32, title: string,
|
||||||
# ignored for ES
|
# ignored for ES
|
||||||
glfw.windowHint(OPENGL_PROFILE, OPENGL_CORE_PROFILE)
|
glfw.windowHint(OPENGL_PROFILE, OPENGL_CORE_PROFILE)
|
||||||
glfw.windowHint(OPENGL_FORWARD_COMPAT, 1)
|
glfw.windowHint(OPENGL_FORWARD_COMPAT, 1)
|
||||||
|
if samples > 1:
|
||||||
|
glfw.windowHint(SAMPLES.cint, samples.cint)
|
||||||
|
|
||||||
let window = make_window(width, height, title)
|
let window = make_window(width, height, title)
|
||||||
window.makeContextCurrent()
|
window.makeContextCurrent()
|
||||||
|
|
|
@ -41,7 +41,7 @@ import ./types
|
||||||
# Forward declarations
|
# Forward declarations
|
||||||
proc newScreen*(engine: MyouEngine, width, height: int32, title: string): Screen
|
proc newScreen*(engine: MyouEngine, width, height: int32, title: string): Screen
|
||||||
proc newFramebufferScreen*(engine: MyouEngine, fb: Framebuffer): Screen
|
proc newFramebufferScreen*(engine: MyouEngine, fb: Framebuffer): Screen
|
||||||
proc newTextureScreen*(engine: MyouEngine, texture: Texture, depth_type: FramebufferDepthType = DepthRenderBuffer, depth_format = Depth_u24): Screen
|
proc newTextureScreen*(engine: MyouEngine, texture: Texture, depth_type: FramebufferDepthType = DepthRenderBuffer, depth_format = Depth_u24, samples = 1): Screen
|
||||||
proc setTexture*(self: Screen, texture: Texture)
|
proc setTexture*(self: Screen, texture: Texture)
|
||||||
proc destroy*(self: Screen)
|
proc destroy*(self: Screen)
|
||||||
proc resize*(self: Screen, width, height: int32, orientation = self.orientation)
|
proc resize*(self: Screen, width, height: int32, orientation = self.orientation)
|
||||||
|
@ -98,7 +98,7 @@ proc newFramebufferScreen*(engine: MyouEngine, fb: Framebuffer): Screen =
|
||||||
result.frame_interval = 1
|
result.frame_interval = 1
|
||||||
result.display_scale = 1.0
|
result.display_scale = 1.0
|
||||||
|
|
||||||
proc newTextureScreen*(engine: MyouEngine, texture: Texture, depth_type: FramebufferDepthType = DepthRenderBuffer, depth_format = Depth_u24): Screen =
|
proc newTextureScreen*(engine: MyouEngine, texture: Texture, depth_type: FramebufferDepthType = DepthRenderBuffer, depth_format = Depth_u24, samples = 1): Screen =
|
||||||
## Creates a new virtual screen from a texture to render to it.
|
## Creates a new virtual screen from a texture to render to it.
|
||||||
|
|
||||||
# TODO: check that it's not a compressed texture
|
# TODO: check that it's not a compressed texture
|
||||||
|
@ -109,6 +109,7 @@ proc newTextureScreen*(engine: MyouEngine, texture: Texture, depth_type: Frameb
|
||||||
texture = texture,
|
texture = texture,
|
||||||
depth_type = depth_type,
|
depth_type = depth_type,
|
||||||
depth_format = depth_format,
|
depth_format = depth_format,
|
||||||
|
samples = samples,
|
||||||
)
|
)
|
||||||
|
|
||||||
proc setTexture*(self: Screen, texture: Texture) =
|
proc setTexture*(self: Screen, texture: Texture) =
|
||||||
|
@ -133,6 +134,10 @@ proc resize*(self: Screen, width, height: int32, orientation = self.orientation)
|
||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
self.orientation = orientation
|
self.orientation = orientation
|
||||||
|
if self.framebuffer.nonNil:
|
||||||
|
self.framebuffer.resize(width, height)
|
||||||
|
if self.framebuffer_multisample.nonNil:
|
||||||
|
self.framebuffer_multisample.resize(width, height)
|
||||||
for vp in self.viewports:
|
for vp in self.viewports:
|
||||||
let (x,y,w,h) = vp.rect
|
let (x,y,w,h) = vp.rect
|
||||||
# TODO: verify this doesn't leave gaps/overlaps
|
# TODO: verify this doesn't leave gaps/overlaps
|
||||||
|
@ -292,3 +297,26 @@ proc emulateMouseWithTouch*(screen: Screen, touch: int32, ending: bool, x, y: fl
|
||||||
proc switch*(self: Screen): bool {.discardable.} =
|
proc switch*(self: Screen): bool {.discardable.} =
|
||||||
self.platform_switch_screen()
|
self.platform_switch_screen()
|
||||||
|
|
||||||
|
proc set_MSAA_samples*(self: Screen, samples: int) =
|
||||||
|
# TODO: remove or add depth of main buffer
|
||||||
|
if samples == 1:
|
||||||
|
# if we're not using MSAA or scaling, we don't need it
|
||||||
|
if self.framebuffer_multisample != nil:
|
||||||
|
self.framebuffer_multisample.destroy()
|
||||||
|
self.framebuffer_multisample = nil
|
||||||
|
else:
|
||||||
|
# var max_samples: GLint
|
||||||
|
# glGetIntegerv(GL_MAX_SAMPLES, addr max_samples)
|
||||||
|
# let samples = min(samples, max_samples)
|
||||||
|
if self.framebuffer_multisample == nil:
|
||||||
|
# TODO: configurable color and depth formats
|
||||||
|
self.framebuffer_multisample = self.engine.newFramebuffer(
|
||||||
|
self.width, self.height,
|
||||||
|
format = RGBA_u8,
|
||||||
|
depth_type = DepthRenderBuffer,
|
||||||
|
depth_format = Depth_u24,
|
||||||
|
samples = samples,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.framebuffer_multisample.resize(self.width, self.height, samples)
|
||||||
|
|
||||||
|
|
|
@ -682,7 +682,7 @@ type
|
||||||
Framebuffer* = ref object of RootObj
|
Framebuffer* = ref object of RootObj
|
||||||
engine* {.cursor.}: MyouEngine
|
engine* {.cursor.}: MyouEngine
|
||||||
width*, height*, layer_count*: int
|
width*, height*, layer_count*: int
|
||||||
format*: TextureFormat
|
format*, depth_format*: TextureFormat
|
||||||
depth_type*: FramebufferDepthType
|
depth_type*: FramebufferDepthType
|
||||||
texture*, depth_texture*: Texture
|
texture*, depth_texture*: Texture
|
||||||
is_complete*: bool
|
is_complete*: bool
|
||||||
|
@ -690,8 +690,10 @@ type
|
||||||
current_width*, current_height*: int
|
current_width*, current_height*: int
|
||||||
current_mipmap_level*: int
|
current_mipmap_level*: int
|
||||||
use_sRGB*: bool
|
use_sRGB*: bool
|
||||||
|
samples*: int
|
||||||
# API objects
|
# API objects
|
||||||
framebuffer*, render_buffer*: GLuint
|
framebuffer*: GLuint ## private
|
||||||
|
color_render_buffer*, depth_render_buffer*: GLuint ## private
|
||||||
|
|
||||||
TexturePixels* = object
|
TexturePixels* = object
|
||||||
pixels*: ArrRef[float32]
|
pixels*: ArrRef[float32]
|
||||||
|
@ -913,6 +915,10 @@ type
|
||||||
frame_inset*: FrameInset
|
frame_inset*: FrameInset
|
||||||
display_scale*: float
|
display_scale*: float
|
||||||
|
|
||||||
|
# this is here temporarily,
|
||||||
|
# we want it in the post processing stack instead
|
||||||
|
framebuffer_multisample*: Framebuffer
|
||||||
|
|
||||||
PlatformEvent* = enum
|
PlatformEvent* = enum
|
||||||
PlatformPause
|
PlatformPause
|
||||||
PlatformResume
|
PlatformResume
|
||||||
|
|
Loading…
Reference in a new issue