diff --git a/src/graphics/framebuffer.nim b/src/graphics/framebuffer.nim index fbaf0f9..3393b37 100644 --- a/src/graphics/framebuffer.nim +++ b/src/graphics/framebuffer.nim @@ -50,6 +50,7 @@ proc newFramebuffer*(engine: MyouEngine, texture: Texture = nil, ): Framebuffer proc set_attachments(self: Framebuffer; layer, mipmap_level: int) +proc set_texture*(self: Framebuffer, texture: Texture) proc enable*(self: Framebuffer, rect = none((int32,int32,int32,int32)), 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, layer = -1) {.inline.} @@ -174,6 +175,12 @@ proc set_attachments(self: Framebuffer; layer, mipmap_level: int) = glFramebufferTexture2D(GL_FRAMEBUFFER, attachments[i], tex.storage.target, tex.storage.tex.GLuint, mipmap_level.GLint) +proc set_texture*(self: Framebuffer, texture: Texture) = + if active_buffer == self: + self.disable() + self.texture = texture + self.current_mipmap_level = -1 # this forces attachment + proc enable*(self: Framebuffer, rect = none((int32,int32,int32,int32)), layer = -1, mipmap_level = 0, mark_textures = true): Framebuffer {.discardable.} = self.has_mipmap = false diff --git a/src/screen.nim b/src/screen.nim index 02754d8..5785e93 100644 --- a/src/screen.nim +++ b/src/screen.nim @@ -30,10 +30,19 @@ # License. If you do not delete the provisions above, a recipient may use your # version of this file under either the CPAL or the [AGPL-3] License. +## In the engine, a screen represents e.g. a screen, a window, a canvas, or a +## render-to-texture framebuffer, with one or more viewports where stuff is drawn +## from the perspective of a camera in a scene. +## +## If it's a screen, window or canvas, it's also the receiver of user events. + import ./types # Forward declarations proc newScreen*(engine: MyouEngine, width, height: int32, title: string): Screen +proc newFramebufferScreen*(engine: MyouEngine, fb: Framebuffer): Screen +proc newTextureScreen*(engine: MyouEngine, texture: Texture, depth_type: FramebufferDepthType = DepthRenderBuffer, depth_format = Depth_u24): Screen +proc setTexture*(self: Screen, texture: Texture) proc destroy*(self: Screen) proc resize*(self: Screen, width, height: int32, orientation = self.orientation) proc add_viewport*(self: Screen, camera: Camera) @@ -73,6 +82,42 @@ proc newScreen*(engine: MyouEngine, width, height: int32, title: string): Screen result.frame_interval = 1 result.display_scale = 1.0 +proc newFramebufferScreen*(engine: MyouEngine, fb: Framebuffer): Screen = + ## Creates a new virtual screen from a framebuffer to render to it. + + result = new Screen + result.engine = engine + result.width = fb.width.int32 + result.height = fb.height.int32 + result.framebuffer = fb + result.enabled = true + engine.screens.add result + result.resize(result.width, result.height) + result.pre_draw = proc(self: Screen) = discard + result.post_draw = proc(self: Screen) = discard + result.frame_interval = 1 + result.display_scale = 1.0 + +proc newTextureScreen*(engine: MyouEngine, texture: Texture, depth_type: FramebufferDepthType = DepthRenderBuffer, depth_format = Depth_u24): Screen = + ## Creates a new virtual screen from a texture to render to it. + + # TODO: check that it's not a compressed texture + assert texture.tex_type == Tex2D, "Only 2D textures are supported" + return engine.newFramebufferScreen engine.newFramebuffer( + texture.width, texture.height, + format = texture.format, + texture = texture, + depth_type = depth_type, + depth_format = depth_format, + ) + +proc setTexture*(self: Screen, texture: Texture) = + ## Change the texture of a render-to-texture screen. + + assert texture != nil + assert self.framebuffer.texture != nil + self.framebuffer.set_texture texture + proc destroy*(self: Screen) = ## Destroys the screen/window and all its resources. If you destroy the main ## screen, the first screen created after it will become the main screen. If @@ -117,7 +162,8 @@ proc add_viewport*(self: Screen, camera: Camera) = proc `vsync=`*(self: Screen, vsync: bool) = ## Change the vsync setting of the screen/window. - cast[Window](self.window).set_vsync vsync + if self.window != nil: + cast[Window](self.window).set_vsync vsync proc get_ray_direction*(viewport: Viewport, position: Vec2): Vec3 = ## Calculates a vector that points from the camera towards the given screen