GithubHelp home page GithubHelp logo

glfb's Introduction

Warning:
This library is in Low Maintainance mode.
See the relevant section for an explanation of what that means.

gl*FB | Tiny Framebuffer with OpenGL

This library provides a simple way to draw a pixel buffer into the screen.
A framebuffer is a memory buffer containing data representing all the pixels in a complete video frame.
The user of the library is fully responsible for how the contents of the pixel buffer are generated.

HowTo

Add this repository to your nimble file with requires "https://github.com/heysokam/glFB#head"
Then, in your code file:

import glFB
# ... your code here ... 

API Examples

Simple API

var scr = Screen.new(960,540)           # Initialize the Screen object
while not scr.close():                  # Run while the Screen has not been marked for closing
  for pix in scr.pixels: pix = myPixel  # Generate the pixels on the CPU
  scr.update()                          # Update the screen contents in the GPU
scr.term()                              # Terminate everything after

Pixel access ergonomics:

# Individual pixels
let pix    = scr[10,10]          # Returns a copy of the pixel at coordinates [X,Y]
for pixel in scr.pixels:         # Access all pixels individually one by one
  pixel = rgbx(0,0,0,0)          # Each item is modifiable, like mitems
scr[10,10] = rgbx(0,0,0,0)       # Directly modify a single pixel at [X,Y]

# All pixels at once
let data   = scr.data            # Alias for accessing the entire Screen's pixel data
scr.data   = SomeSeqOfColorRGBX  # Alias for pixel buffer data asignation all at once (size must match)

# Note: Coordinate (0,0) is at topleft of the screen

Advanced Usage

Screen construction:

# Constructor function options:  
# 1. Creates pixel buffer with all values set to (0,0,0,0)
  var scr = Screen.new( Width, Height )
# 2. Creates a pixel buffer with the contents and size of the input pixie.Image
  var scr = Screen.new( SomePixieImageObject )
# 3. Creates the required pixie image internally, using the given separate pixel buffer inputs
  var scr = Screen.new( Width, Height, SomeSeqOfColorRGBX )

# Implicit Defaults during Screen Creation with `Screen.new( ... )`:  
  title        : string                  = "glFB | Window";  # Title of the window
  resizable    : bool                    = false;            # Whether the window is allowed to be resized or not
  resize       : glfw.FrameBufferSizeFun = w.resize;         # GLFW framebuffer resize callback.  aka: glFB/window  proc resize() ...
  key          : glfw.KeyFun             = i.key;            # GLFW Input Keyboard callback.      aka: glFB/input   proc key() ...
  mousePos     : glfw.CursorPosFun       = nil;              # GLFW Input Mouse Position callback.
  mouseBtn     : glfw.MouseButtonFun     = nil;              # GLFW Input Mouse Button callback.
  mouseScroll  : glfw.ScrollFun          = nil;              # GLFW Input Mouse ScrollWheel callback.
  mouseCapture : bool                    = false;            # Whether to capture the mouse on window launch or not
  error        : glfw.ErrorFun           = nil;              # GLFW Error callback
  vsync        : bool                    = false;            # Whether vsync is active or not

Post-Processing shader example (Simple API):

var scr = Screen.new(960,540)                         # Initialize the Screen
scr.addPost(DbgFrag)                                  # Add the Debug Post-Processing effect to the list
while not scr.close():                                # Run while the Screen has not been marked for closing
  for pix in scr.pixels: pix = rgbx(255,255,255,255)  # Generate the pixels on the CPU
  scr.update()                                        # Draw the contents (also applies all Post-Processing shaders)
scr.term()                                            # Terminate everything after

Post-Processing shader removal:

var shd = scr.addPost( SomeShaderCodeString )  # Returns the (implicitly discarded) handle of the shader
scr.rmvPost( shd )                             # Remove the shader from the list with its handle id

Fully verbose example:

import glFB

#_______________________________________
# Our dummy CPU renderer
from chroma import rgbx
proc renderPixels(scr :var Screen) :void=
  for pix in scr.pixels: pix = rgbx(255,255,255,255)
#_______________________________________


#_______________________________________
# Our verbose glFB Framebuffer application
#_____________________________
# Input functions for GLFW
from nglfw as glfw import nil
proc myResizeFunction        (window :glfw.Window; width, height :cint) {.cdecl.} = discard
proc myKeyboardFunction      (window :glfw.Window; key, scancode, action, modifiers :cint) {.cdecl.} = discard
proc myMousePositionFunction (window :glfw.Window; x, y :cdouble) {.cdecl.} = discard
proc myMouseButtonFunction   (window :glfw.Window; button, action, modifiers :cint) {.cdecl.} = discard
proc myMouseScrollFunction   (window :glfw.Window; xoffset, yoffset :cdouble) {.cdecl.} = discard

# Create the Screen object
var scr = Screen.new(              # Initialize the Screen object, using the (W,H) variant
  W            = 960,              # (must be explicit) Window and pixelbuffer initial width
  H            = 540,              # (must be explicit) Window and pixelbuffer initial height
  title        = "glFB | Window",
  resizable    = true,             # Change window to resizable (default false)
  resize       = myResizeFunction,
  key          = myKeyboardFunction,
  mousePos     = myMousePositionFunction,
  mouseBtn     = myMouseButtonFunction,
  mouseScroll  = myMouseScrollFunction,
  mouseCapture = true,             # Change default to capture the mouse (default false)
  error        = myErrorCallback,
  ) # << Screen.new( ... )

# Generate a custom Post-Processing shader
var shd = scr.addPost( SomeShaderCodeString )  # Store the handle. Will be removed later in the example, using a condition

# Do something explicit with glfw on the window
# Could be anything supported by glfw, you have full access to the window context
glfw.setWindowShouldClose(scr.win.ct, true)

# Update loop
while not scr.close():                # Run while the Screen has not been marked for closing
  scr.renderPixels()                  # Generate the pixels on the CPU, with the verbose example custom function
  if myCondition: scr.rmvPost( shd )  # Remove the post-process effect. Drawing will no longer trigger it
  scr.update()                        # Update the screen contents in the GPU

# Terminate after we are done
scr.term()                            # Terminate everything after

Notes:

No acceleration

The GPU is exclusively used for accessing the data, and transfering it into the screen.
The only GPU-based processing this library does is applying the list of (optional) Post-Processing effects.
This library applies no GPU acceleration anywhere else, which makes it suitable for purely CPU-driven renderers.

Coordinates

Coordinate (0,0) is topleft of the screen.
OpenGL wants 0,0 to be bottomleft, but glFB changes this in the FST vertex shader, so that the buffer is drawn correctly.

TODO

  • Window size Uniform access
  • Texture size Uniform access
  • Time Uniform access

Low Maintainance mode

This library is in low maintainance mode.

New updates are unlikely to be implemented, unless:

  • They are randomnly needed for some casual side project (eg: a gamejam or similar)
  • They are submitted through a PR

Proposals and PRs are very welcomed, and are very likely to be accepted right away.

See the relevant section for an explaination of why this is the case.


Why I changed Pure Nim to be my auxiliary programming language, instead of being my primary focus

Important:
This reason is very personal, and it is exclusively about using Nim in a manual-memory-management context.
Nim is great as it is, and the GC performance is so optimized that it's barely noticeable that it is there.
That's why I still think Nim is the best language for projects where a GC'ed workflow makes more sense.

Nim with --mm:none was always my ideal language.
But its clear that the GC:none feature (albeit niche) is only provided as a sidekick, and not really maintained as a core feature.

I tried to get Nim to behave correctly with --mm:none for months and months.
It takes an absurd amount of unnecessary effort to get it to a basic default state.

And I'm not talking about the lack of GC removing half of the nim/std library because of nim's extensive use of seq/string in its stdlib.
I'm talking about features that shouldn't even be allowed to exist at all in a gc:none context, because they leak memory and create untrackable bugs.
(eg: exceptions, object variants, dynamically allocated types, etc etc)

After all of that effort, and seeing how futile it was, I gave up on --mm:none completely.
It would take a big amount of effort patching nim itself so that these issues are no longer there.
And, sadly, based on experience, I'm not confident in my ability to communicate with Nim's leadership to do such work myself.

This setback led me to consider other alternatives, including Zig or Pure C.
But, in the end, I decided that from now on I will be programming with my MinC source-to-source language/compiler instead.

As such, I will be deprecating most of my n*dk libraries.
I will be creating my engine's devkit with MinC instead.

That means, as it is detailed in the Low Maintainance section, that this library will receive a very low/minimal amount of support.

glfb's People

Contributors

heysokam avatar

Stargazers

 avatar dh avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.