Skip to content

Commit

Permalink
change: use opengl
Browse files Browse the repository at this point in the history
  • Loading branch information
levovix0 committed Apr 3, 2024
1 parent ada26cb commit ac8fdaf
Show file tree
Hide file tree
Showing 13 changed files with 731 additions and 125 deletions.
3 changes: 3 additions & 0 deletions folx.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ bin = @["folx"]
requires "nim >= 2.0.2"
requires "siwin ^= 0.8.4.6", "jsony", "pixie", "fusion", "winim"
requires "cligen"
requires "shady ^= 0.1.3" # writing shaders in nim instead of glsl
requires "fusion ^= 1.2" # pattern matching and ast dsl
requires "opengl ^= 1.2.9"


let dataDir =
Expand Down
12 changes: 7 additions & 5 deletions src/explorer.nim
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ component Disk {.noexport.}:
)

if selected:
Rect: color = colorTheme.bgSelection
Rect(w = 2): color = colorTheme.bgSelectionLabel
Rect: color = colorTheme.bgSelection.color
Rect(w = 2): color = colorTheme.bgSelectionLabel.color

Text disk(x = 10):
color = colorTheme.cActive
Expand All @@ -207,14 +207,16 @@ component File {.noexport.}:
let dy = round(glyphTableStack[^1].font.size * 1.27)

if selected:
Rect: color = colorTheme.bgSelection
Rect(w = 2): color = colorTheme.bgSelectionLabel
Rect: color = colorTheme.bgSelection.color
Rect(w = 2): color = colorTheme.bgSelectionLabel.color

let bg =
if selected: colorTheme.bgSelection
else: bg

contextStack[^1].image.draw(getIcon(file), translate(parentBox.xy + vec2(20, 4)) * scale(vec2(0.06 * dy, 0.06 * dy)))
let icon = getIcon(file)
Image icon(x = 20, y = 4, w = icon.width.float * 0.06 * dy, h = icon.height.float * 0.06 * dy):
discard

Text (file.name & file.ext)(x = 40, w = 200, clip = true):
color = colorTheme.cActive
Expand Down
22 changes: 16 additions & 6 deletions src/folx.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import sequtils, os, times, math, unicode, std/monotimes, options
import cligen
import pkg/[cligen, opengl]
import gui, configuration, git, text, text_editor, side_explorer, explorer, title, status_bar, welcome
import ./graphics/[globals, shaders, shaderutils]

proc contains*(b: Rect, a: GVec2): bool =
let a = a.vec2
Expand Down Expand Up @@ -30,13 +31,17 @@ proc folx(files: seq[string] = @[], workspace: string = "", preferWorkFolderReso
else: files[0].splitPath.head

if preferWorkFolderResources: configuration.workFolderResources()
let window = newSoftwareRenderingWindow(

let window = newOpenglWindow(
title="folx", size=config.window.size,
frameless = if config.window.customTitleBar: true else: false,
transparent = if config.window.customTitleBar: true else: false,
)

loadExtensions()

global_drawContext = newDrawContext()

var
editor_gt = readFont(rc config.font).newGlyphTable(config.fontSize)
interface_gt = readFont(rc config.interfaceFont).newGlyphTable(config.interfaceFontSize)
Expand Down Expand Up @@ -215,12 +220,17 @@ proc folx(files: seq[string] = @[], workspace: string = "", preferWorkFolderReso
window.eventsHandler.onRender = proc(e: RenderEvent) =
image.clear colorTheme.bgTextArea.color.rgbx
setCursor Cursor(kind: builtin, builtin: BuiltinCursor.arrow)

glClearColor colorTheme.bgTextArea.color.r, colorTheme.bgTextArea.color.g, colorTheme.bgTextArea.color.b, colorTheme.bgTextArea.color.a
glClear(GL_COLOR_BUFFER_BIT)

let size = e.window.size
glViewport 0, 0, size.x.GLsizei, size.y.GLsizei
global_drawContext.updateSizeRender(size)

frame(w = window.size.x, h = window.size.y, clip=true):
withContext r:
handleFolx()
handleFolx()

window.drawImage image.data.toBgrx, ivec2(image.width.int32, image.height.int32)
window.cursor = globalCursor
isLeftClick = false
isLeftDown = false
Expand Down
223 changes: 223 additions & 0 deletions src/graphics/gl.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
import vmath, opengl, pixie

when (compiles do: import imageman):
import imageman
const hasImageman* = true
else:
const hasImageman* = false

export vmath, opengl


type
Buffers* = ref BuffersObj
BuffersObj = object
n: int32
obj: UncheckedArray[GlUint]

VertexArrays* = ref VertexArraysObj
VertexArraysObj = object
n: int32
obj: UncheckedArray[GlUint]

Textures* = ref TexturesObj
## note: texures can't be actualy deleted for now. glDeleteTextures is not enough. If you want to resize texture, use loadTexture multiple times instead.
TexturesObj = object
n: int32
obj: UncheckedArray[GlUint]

Shader* = ref ShaderObj
ShaderObj = object
obj: GlUint

FrameBuffers* = ref FrameBuffersObj
FrameBuffersObj = object
n: int32
obj: UncheckedArray[GlUint]

ShaderCompileDefect* = object of Defect

Shape* = ref object
kind: GlEnum
len: int
vao: VertexArrays
bo: Buffers

OpenglUniform*[T] = distinct GlInt


# -------- Buffers, VertexArrays, Textures --------
template makeOpenglObjectSeq(t, tobj, T, gen, del, newp, delextra) =
proc `=destroy`(xobj {.inject.}: tobj) =
delextra
del(xobj.n, cast[ptr T](xobj.obj.addr))

proc newp*(n: int): t =
if n == 0: return
assert n in 1..int32.high
unsafeNew result, int32.sizeof + n * T.sizeof
result.n = n.int32
gen(n.int32, cast[ptr T](result.obj.addr))

proc len*(x: t): int =
if x == nil: 0
else: x.n

proc `[]`*(x: t, i: int): T =
if i notin 0..<x.len:
raise IndexDefect.newException("index " & $i & " out of range 0..<" & $x.len)
x.obj[i]


proc unloadTextures(x: TexturesObj) =
for i in 0..<x.n:
## sems like it don't work
# glBindTexture(GlTexture2d, x.obj[i])
# glTexImage2D(GlTexture2d, 0, GlRgba.Glint, 0, 0, 0, GlRgba, GlUnsignedByte, nil)


{.push, warning[Effect]: off.}
makeOpenglObjectSeq Buffers, BuffersObj, GlUint, glGenBuffers, glDeleteBuffers, newBuffers: discard
makeOpenglObjectSeq VertexArrays, VertexArraysObj, GlUint, glGenVertexArrays, glDeleteVertexArrays, newVertexArrays: discard
makeOpenglObjectSeq Textures, TexturesObj, GlUint, glGenTextures, glDeleteTextures, newTextures:
unloadTextures(xobj)
makeOpenglObjectSeq FrameBuffers, FrameBuffersObj, GlUint, glGenFrameBuffers, glDeleteFrameBuffers, newFrameBuffers: discard
{.pop.}

proc `[]`*(x: Textures, i: enum): GlUint =
if i.int notin 0..<x.len:
raise IndexDefect.newException("index " & $i & " out of range 0..<" & $x.len)
x.obj[i.int]

when defined(gcc):
{.passc: "-fcompare-debug-second".} # seems like it hides warning about "passing flexieble array ABI changed in GCC 4.4"
# i don't care, gcc


# -------- helpers --------
proc arrayBufferData*[T](data: openarray[T], usage: GlEnum = GlStaticDraw) =
glBufferData(GlArrayBuffer, data.len * T.sizeof, data.unsafeaddr, usage)

proc elementArrayBufferData*[T](data: openarray[T], usage: GlEnum = GlStaticDraw) =
glBufferData(GlElementArrayBuffer, data.len * T.sizeof, data.unsafeaddr, usage)

template withVertexArray*(vao: GlUint, body) =
glBindVertexArray(vao)
block: body
glBindVertexArray(0)

when hasImageman:
proc loadTexture*(obj: GlUint, img: imageman.Image[ColorRGBAU]) =
glBindTexture(GlTexture2d, obj)
glTexImage2D(GlTexture2d, 0, GlRgba.GLint, img.width.GLsizei, img.height.GLsizei, 0, GlRgba, GlUnsignedByte, img.data[0].unsafeaddr)
glGenerateMipmap(GlTexture2d)
glBindTexture(GlTexture2d, 0)

proc loadTexture*(obj: GlUint, img: pixie.Image) =
glBindTexture(GlTexture2d, obj)
glTexImage2D(GlTexture2d, 0, GlRgba.GLint, img.width.GLsizei, img.height.GLsizei, 0, GlRgba, GlUnsignedByte, img.data[0].unsafeaddr)
glGenerateMipmap(GlTexture2d)
glBindTexture(GlTexture2d, 0)



# -------- Shader --------
{.push, warning[Effect]: off.}
proc `=destroy`(x: ShaderObj) =
if x.obj != 0:
glDeleteProgram(x.obj)
{.pop.}

proc newShader*(shaders: openarray[(GlEnum, string)]): Shader =
new result

var shad = newSeq[GlUint](shaders.len)

proc free =
for x in shad:
if x != 0: glDeleteShader(x)

for i, (k, s) in shaders:
var cs = s.cstring
shad[i] = glCreateShader(k)
glShaderSource(shad[i], 1, cast[cstringArray](cs.addr), nil)
glCompileShader(shad[i])
if (var success: GlInt; glGetShaderiv(shad[i], GlCompileStatus, success.addr); success != GlTrue.GlInt):
var buffer: array[512, char]
glGetShaderInfoLog(shad[i], 512, nil, cast[cstring](buffer.addr))
free()
raise ShaderCompileDefect.newException("failed to compile shader " & $(i+1) & ": " & $cast[cstring](buffer.addr))

defer: free()

result.obj = glCreateProgram()
for i, x in shad:
glAttachShader(result.obj, x)
glLinkProgram(result.obj)
if (var success: GlInt; glGetProgramiv(result.obj, GlLinkStatus, success.addr); success != GlTrue.GlInt):
var buffer: array[512, char]
glGetProgramInfoLog(result.obj, 512, nil, cast[cstring](buffer.addr))
# todo: delete gl shader programm?
raise ShaderCompileDefect.newException("failed to link shader program: " & $cast[cstring](buffer.addr))

proc use*(x: Shader) =
glUseProgram(x.obj)

proc `[]`*(x: Shader, name: string): GlInt =
result = glGetUniformLocation(x.obj, name)
if result == -1:
raise KeyError.newException("shader has no uniform " & name & " (is it unused?)")

proc `uniform=`*(i: GlInt, value: GlFloat) =
glUniform1f(i, value)

proc `uniform=`*(i: GlInt, value: Vec2) =
glUniform2f(i, value.x, value.y)

proc `uniform=`*(i: GlInt, value: Vec3) =
glUniform3f(i, value.x, value.y, value.z)

proc `uniform=`*(i: GlInt, value: Vec4) =
glUniform4f(i, value.x, value.y, value.z, value.w)

proc `uniform=`*(i: GlInt, value: Mat4) =
glUniformMatrix4fv(i, 1, GlFalse, cast[ptr GlFloat](value.unsafeaddr))


proc `uniform=`*[T](x: OpenglUniform[T], value: T) = x.GlInt.uniform = value


# -------- Shape --------
proc makeAttributes(t: type) =
when t is tuple:
var i = 0
var offset = 0
var x: t
for x in x.fields:
type t2 = x.typeof
glVertexAttribPointer i.uint32, t2.sizeof div GlFloat.sizeof, cGlFloat, GlFalse, t.sizeof.GlSizei, cast[pointer](offset)
glEnableVertexAttribArray i.uint32
inc i
inc offset, t2.sizeof
else:
glVertexAttribPointer 0, t.sizeof div GlFloat.sizeof, cGlFloat, GlFalse, t.sizeof.GlSizei, nil
glEnableVertexAttribArray 0


proc newShape*[T](vert: openarray[T], idx: openarray[GlUint], kind = GlTriangles): Shape =
new result
result.vao = newVertexArrays(1)
result.bo = newBuffers(2)
result.len = idx.len
result.kind = kind

withVertexArray result.vao[0]:
glBindBuffer GlArrayBuffer, result.bo[0]
arrayBufferData vert
glBindBuffer GlElementArrayBuffer, result.bo[1]
elementArrayBufferData idx
makeAttributes T

proc draw*(x: Shape) =
withVertexArray x.vao[0]:
glDrawElements(x.kind, x.len.GlSizei, GlUnsignedInt, nil)
3 changes: 3 additions & 0 deletions src/graphics/globals.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import shaders

var global_drawContext*: DrawContext
Loading

0 comments on commit ac8fdaf

Please sign in to comment.