Coder Social home page Coder Social logo

aglet's Introduction

aglet

A safe, high-level core OpenGL 3.3+ context manager and wrapper for Nim.

Documentation

Note: As of June 2021, I'm no longer actively working on aglet. Since the project is still quite unfinished, I'm willing to accept contributions via PRs. If anyone contributes code frequently enough, I'm willing to give them contributor status to make working on the project easier.

Features

No state machine

OpenGL is a mess—it's a giant state machine, and it's hard to keep track of its current state. Modern programming languages are more suited towards using objects for resource allocation and managenent, and that's what aglet strives to provide. aglet uses Nim's type system to ensure OpenGL type safety. When you get a Texture2D object, you can be sure it's a 2D texture. It's not a vague GLuint that does not really describe anything. Apart from that, you don't have to worry about keeping track of all this state—aglet does all the bookkeeping for you, and even avoids unnecessary API calls via some simple and cheap if statements.

The main goal is to provide a safe API around the core GL API, which is made primarily for C. aglet embraces Nim's features like concepts to make the wrapper generic and extendable. Forget having to deal with pointers and other unsafe features—aglet abstracts that away by using safe containers, like openArrays. Forget all the state management—aglet abstracts it away via safe, stateless objects that make your code much easier to maintain. What your code reads is really what it does—you don't have to scan your codebase to find out which texture is currently bound.

No global variables

Forget about GLAD's global variables—aglet is fully safe for dynamic loading via the std/dynlib module. All loaded OpenGL procs are stored in the abstract Window class.

Fast check times

Import the context backend once, and don't think about it ever since. The abstract codebase is lightweight and does not use any Nimterop wrappers, which are known to slow down nim check, which is used by many editor extensions (most notably the Visual Studio Code extension). At some point aglet will remove its GLFW dependency completely, but that's what it uses for now to help develop core features quicker.

Short, generic code

Code written using aglet is much shorter than the equivalent code written in libraries imported from C. It abstracts all the verbosity away to keep your codebase small and concise.

Idiomatic and error-free

aglet takes advantage of Nim features such as distinct types to make your code less error-prone. For instance, it's not possible to attach a Renderbuffer[Depth32f] to a color-only framebuffer, because a Renderbuffer[Depth32f] does not implement a converter to ColorSource. Combine this with other small utility features, and aglet code is much less error-prone than the equivalent C code.

It's free

aglet is and will always be free. It's licensed under the MIT license, so you're free to use it in commercial projects.

Examples

Opening a window

import aglet
import aglet/window/glfw  # we need a backend for windowing

# initialize the library state
var agl = initAglet()
agl.initWindow()

# create our window
var win = agl.newWindowGlfw(800, 600, "window example",
                            winHints(resizable = false))

# begin the render loop
while not win.closeRequested:

  # render
  var frame = win.render()
  frame.clearColor(rgba(0.0, 0.0, 1.0, 1.0))
  frame.finish()

  # handle events
  win.pollEvents do (event: InputEvent):
    echo event

You can find more examples in the tests/ directory.

Roadmap

  • Context management
    • via GLFW
    • pure Nim implementation
  • Generic render target
    • DrawParams object as a replacement for the state machine
  • Vertex buffers (Mesh)
    • Vertex buffer
    • Element (index) buffer
    • Buffer slicing
    • Instancing
  • Shaders and programs
  • Textures
    • Types
      • 1D, 2D, 3D
      • 1D array, 2D array
      • Cube map
    • Features
      • Texture units
      • Sampler objects
      • Texture swizzle mask
  • Framebuffers
    • Renderbuffers
    • SimpleFramebuffer (one color attachment)
    • MultiFramebuffer (≥1 color attachment)

Please report any extra features you'd like to see in the Issues tab!

Installation

By adding it your dependencies:

requires "aglet >= 0.1.0"

Via the nimble command:

$ nimble install aglet

Manually:

$ git clone https://github.com/liquid600pgm/aglet
$ cd aglet
$ nimble install

aglet's People

Contributors

johndoneth avatar liquidev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

johndoneth

aglet's Issues

Very long compile times

Nimterop is quite a bulky dependency, which adds a lot to the compile times. It should be possible to eliminate it by vendoring the GLFW code into this repository.

Depth texture cannot be created

let shadowMap = win.newTexture2D[: Depth32](vec2i(4096, 4096)).toFramebuffer()

Results in:

/home/jason/truss3d/src/truss3d.nim(112, 61) template/generic instantiation of `toFramebuffer` from here
/home/jason/.nimble/pkgs/aglet-0.4.4/aglet/texture.nim(866, 49) template/generic instantiation of `source` from here
/home/jason/.nimble/pkgs/aglet-0.4.4/aglet/texture.nim(860, 19) Error: type mismatch: got <Texture2D[pixeltypes.Depth32]>
but expected one of: 
proc implSource(texture: Texture2D[ColorPixelType]): FramebufferSource
  first type mismatch at position: 1
  required type for texture: Texture2D[ColorPixelType.ColorPixelType]
  but expression 'texture' is of type: Texture2D[pixeltypes.Depth32]

Getting the current buffer's data

Accessing the current buffers data(pixel RGB values) in an efficient, simple way.
I have not found another library with the functionality that can do this, digging into OpenGL it seems to be possible through the PBO, accessing it this way may be quite a cost(dragging it from the gpu to ram)

cheers Zed

Instanced arrays

Right now it is possible to send per-instance data via uniforms, but this has the drawback of having some upper limit on the array size. This feature was not included in 0.1.0 because I'm not yet sure about the API.

Android

Do you know if or how this would work for Android development? I know they also require a manifest but that's about the extent of my experience with full fledged Android apps. As for different frameworks, I have built and ran some of the Kivy examples and Corona but am very interested in doing something in Nim.

Extra documentation

Including:

  • introductions for people who are not familiar with OpenGL
  • more examples in tests/
    • distilled examples for framebuffers and pixel downloads

Missing texture types

The following texture types exist in the API but cannot be created and/or used:

  • 1D array
  • 2D array
  • cube map

Own windowing

GLFW is pretty bulky and written in C, it also uses some global state, and I don't like that.

This is an idea for the far future, right now I have no plans on actually implementing this.

Uniform buffer objects/shader storage buffer objects

Pretty self-explanatory. The problem is that the in-memory layout is driver-specific, and the std140 layout does not match the alignment rules of Nim objects, which makes sending data to the graphics card quite inconvenient.
This could probably be solved using macros and generics, but I'm not sure about the API. The current uniforms macro could play well with this, for example:

type
  MyData = object
    a, b, c: Vec3f

let
  ubo = win.newUniformBuffer(MyData())
  u = uniforms {
    MyUniformBlock: ubo,
  }

The problem I'm facing is that alignment problem; I would have to read the spec (which is not a problem) but generating all the code to align everything properly would be quite a challenge.
Another thing is that uniform blocks support dynamic arrays. That's fine and dandy, but how would we solve this syntactically? Use a seq or some special storage type?

These are all things for extra consideration, and I will take care of that when I need it or somebody asks for it.

OpenGL versioning

If any features of OpenGL versions >3.3 are to be added to aglet, they should be barriered behind flags that disable them if the user requests an older OpenGL version.

The target GL version will be specifiable using a define: -d:aglOpenGL=<major>.<minor>, eg. -d:aglOpenGL=3.3 will limit the feature set to OpenGL 3.3 at compile time. This will disable all features from versions newer than 3.3 and throw a compile-time error.

This should be relatively easy to implement:

import strutils

const
  aglOpenGL {.strdefine.} = "4.6"  # all features enabled by default
  targetGlVersion = block:
    let parts = aglOpenGL.split('.')
    assert parts.len == 2, "usage: -d:aglOpenGL=<major>.<minor>"
    (parts[0].parseInt, parts[1].parseInt)

proc openGl*(major, minor: int): bool {.compileTime.} =
  targetGlVersion >= (major, minor)

when openGl(4, 0):
  discard  # features for GL >= 4.0

Integer `Vec[T]` VAO Attributes are always passed as `GL_NONE`

I'm storing color per vertex as Vec[4, system.uint8] to work with ImGui and noticed that the type for the vertex attribute was always being set to GL_NONE which lead me to discover this bug.

gl.glVertexAttribIPointer(GlUint(index), N, T.toGlEnum,

The expression T.toGlEnum will always evaluate to 0 or GL_NONE. It should be TT.toGlEnum instead, to work with the type inside of the Vec.

I will open a PR shortly. Should toGlEnum have a catch all which throws an exception?

Texture swizzle mask

Pretty self-explanatory, what holds me back on this is the API is how it could be implemented. I would need to implement an extra property on the texture, I think, which I'm not yet sure on; probably a property like this could be created:

# for text rendering:
someTexture.swizzleMask = [ccOne, ccOne, ccOne, ccRed]

A nicer solution would allow adjusting this per-sampler, but I do not think this is possible with OpenGL.

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.