odin(sdl-opengl-rendering): basic line rendering
This commit is contained in:
parent
5c5cd55904
commit
30772e4255
11 changed files with 253 additions and 136 deletions
odin/sdl-opengl-rendering
1
odin/sdl-opengl-rendering/.envrc
Normal file
1
odin/sdl-opengl-rendering/.envrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
use flake
|
1
odin/sdl-opengl-rendering/.gitignore
vendored
1
odin/sdl-opengl-rendering/.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
*.bin
|
*.bin
|
||||||
|
!.envrc
|
||||||
|
|
59
odin/sdl-opengl-rendering/flake.lock
generated
59
odin/sdl-opengl-rendering/flake.lock
generated
|
@ -20,11 +20,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1738680400,
|
"lastModified": 1748693115,
|
||||||
"narHash": "sha256-ooLh+XW8jfa+91F1nhf9OF7qhuA/y1ChLx6lXDNeY5U=",
|
"narHash": "sha256-StSrWhklmDuXT93yc3GrTlb0cKSS0agTAxMGjLKAsY8=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "799ba5bffed04ced7067a91798353d360788b30d",
|
"rev": "910796cabe436259a29a72e8d3f5e180fc6dfacc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -34,10 +34,61 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"odin": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": [
|
||||||
|
"flake-utils"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1747681085,
|
||||||
|
"narHash": "sha256-tG177/u/vDUnxXeIFjJWYTRSuvYRfSCDYv3tjgdf+Ec=",
|
||||||
|
"owner": "starlitcanopy",
|
||||||
|
"repo": "odin",
|
||||||
|
"rev": "612433442cc03297474a31d3d40fce74ce3f5331",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "starlitcanopy",
|
||||||
|
"repo": "odin",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ols": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": [
|
||||||
|
"flake-utils"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"odin": [
|
||||||
|
"odin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1747682765,
|
||||||
|
"narHash": "sha256-uq7kh10bBIx/gnnYOUCO2YD5+4UaNeD1W6YSlrYtJyQ=",
|
||||||
|
"owner": "starlitcanopy",
|
||||||
|
"repo": "ols",
|
||||||
|
"rev": "81d3e8ecb1ade5c02c4769961027b3d86b7a6f94",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "starlitcanopy",
|
||||||
|
"repo": "ols",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs",
|
||||||
|
"odin": "odin",
|
||||||
|
"ols": "ols"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems": {
|
"systems": {
|
||||||
|
|
|
@ -2,74 +2,42 @@
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
|
||||||
|
odin.url = "github:starlitcanopy/odin";
|
||||||
|
odin.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
odin.inputs.flake-utils.follows = "flake-utils";
|
||||||
|
|
||||||
|
ols.url = "github:starlitcanopy/ols";
|
||||||
|
ols.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
ols.inputs.flake-utils.follows = "flake-utils";
|
||||||
|
ols.inputs.odin.follows = "odin";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs =
|
outputs =
|
||||||
inputs:
|
inputs:
|
||||||
{
|
inputs.flake-utils.lib.eachSystem (with inputs.flake-utils.lib.system; [ x86_64-linux ]) (
|
||||||
overlays.default = final: prev: {
|
|
||||||
# {{{ Odin
|
|
||||||
odin = prev.odin.overrideAttrs (_: {
|
|
||||||
version = "unstable-2025-03-28";
|
|
||||||
src = final.fetchFromGitHub {
|
|
||||||
owner = "starlitcanopy";
|
|
||||||
repo = "Odin";
|
|
||||||
rev = "a1fc243f8df8b510e6de4f5e115fbfc09371cb9d";
|
|
||||||
sha256 = "0fb8lk47nb7ln0skjn3lyfi499q3wlnzp6w3qc4wf4s5zj43d6zh";
|
|
||||||
};
|
|
||||||
});
|
|
||||||
# }}}
|
|
||||||
# {{{ OLS
|
|
||||||
ols = prev.ols.overrideAttrs (_: {
|
|
||||||
version = "unstable-2025-03-12";
|
|
||||||
src = final.fetchFromGitHub {
|
|
||||||
owner = "DanielGavin";
|
|
||||||
repo = "ols";
|
|
||||||
rev = "1e44e3d78ad8a74ef09c7f54a6f6d3f7df517f8e";
|
|
||||||
sha256 = "16f7b8ijcaj5m2bdgbbl1q1mzgpgzzazrap2g17hkgy63aqq8qmf";
|
|
||||||
};
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
runHook preInstall
|
|
||||||
|
|
||||||
install -Dm755 ols odinfmt -t $out/bin/
|
|
||||||
cp -r builtin $out/bin/
|
|
||||||
wrapProgram $out/bin/ols --set-default ODIN_ROOT ${final.odin}/share
|
|
||||||
|
|
||||||
runHook postInstall
|
|
||||||
'';
|
|
||||||
});
|
|
||||||
# }}}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// inputs.flake-utils.lib.eachSystem (with inputs.flake-utils.lib.system; [ x86_64-linux ]) (
|
|
||||||
system:
|
system:
|
||||||
let
|
let
|
||||||
pkgs = inputs.nixpkgs.legacyPackages.${system}.extend inputs.self.overlays.default;
|
pkgs = import inputs.nixpkgs {
|
||||||
cross = import inputs.nixpkgs {
|
inherit system;
|
||||||
localSystem = system;
|
overlays = [
|
||||||
crossSystem.config = "x86_64-w64-mingw32";
|
inputs.odin.overlays.default
|
||||||
|
inputs.ols.overlays.default
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
inherit (pkgs) lib;
|
inherit (pkgs) lib;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
packages = {
|
|
||||||
inherit (pkgs) odin;
|
|
||||||
gcc = cross.callPackage (import ./gcc.nix) { };
|
|
||||||
libgl = cross.libGL;
|
|
||||||
};
|
|
||||||
|
|
||||||
# {{{ Shell
|
# {{{ Shell
|
||||||
devShell = pkgs.mkShell rec {
|
devShell = pkgs.mkShell rec {
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
pkgs.pkg-config
|
pkgs.pkg-config
|
||||||
pkgs.entr # File change detection
|
|
||||||
pkgs.odin # Compiler
|
pkgs.odin # Compiler
|
||||||
pkgs.mold # Linker
|
pkgs.mold # Linker
|
||||||
|
pkgs.ols # Language server
|
||||||
pkgs.just # Script runner
|
pkgs.just # Script runner
|
||||||
pkgs.samply # Profiler
|
pkgs.samply # Profiler
|
||||||
pkgs.ols # Language server
|
|
||||||
pkgs.gdb # Debugger
|
pkgs.gdb # Debugger
|
||||||
pkgs.seer # Debugger GUI
|
pkgs.seer # Debugger GUI
|
||||||
pkgs.valgrind # Detect memory leaks
|
pkgs.valgrind # Detect memory leaks
|
||||||
|
|
|
@ -9,12 +9,16 @@ import "vendor:OpenGL"
|
||||||
import "vendor:sdl3"
|
import "vendor:sdl3"
|
||||||
|
|
||||||
State :: struct {
|
State :: struct {
|
||||||
tick: u32,
|
tick: u32,
|
||||||
window: ^sdl3.Window,
|
window: ^sdl3.Window,
|
||||||
program: u32,
|
rect_program: u32,
|
||||||
rect_vao: VAO,
|
circle_program: u32,
|
||||||
circle_vao: VAO,
|
line_program: u32,
|
||||||
wireframe: bool,
|
rect_vao: VAO,
|
||||||
|
circle_vao: VAO,
|
||||||
|
wireframe: bool,
|
||||||
|
buf_matrices: [INSTANCES]Mat3,
|
||||||
|
buf_colors: [INSTANCES]Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
// {{{ Initialization
|
// {{{ Initialization
|
||||||
|
@ -98,26 +102,23 @@ init :: proc() -> (state: State, ok: bool) {
|
||||||
OpenGL.Enable(OpenGL.BLEND)
|
OpenGL.Enable(OpenGL.BLEND)
|
||||||
OpenGL.BlendFunc(OpenGL.SRC_ALPHA, OpenGL.ONE_MINUS_SRC_ALPHA)
|
OpenGL.BlendFunc(OpenGL.SRC_ALPHA, OpenGL.ONE_MINUS_SRC_ALPHA)
|
||||||
|
|
||||||
state.program = OpenGL.load_shaders_source(
|
state.rect_program = OpenGL.load_shaders_source(
|
||||||
#load("./vert.glsl"),
|
#load("./shaders/vert.glsl"),
|
||||||
#load("./frag.glsl"),
|
#load("./shaders/rect.frag.glsl"),
|
||||||
|
) or_return
|
||||||
|
|
||||||
|
state.circle_program = OpenGL.load_shaders_source(
|
||||||
|
#load("./shaders/vert.glsl"),
|
||||||
|
#load("./shaders/circle.frag.glsl"),
|
||||||
|
) or_return
|
||||||
|
|
||||||
|
state.line_program = OpenGL.load_shaders_source(
|
||||||
|
#load("./shaders/vert.glsl"),
|
||||||
|
#load("./shaders/line.frag.glsl"),
|
||||||
) or_return
|
) or_return
|
||||||
|
|
||||||
state.rect_vao = create_vao({{-1, -1}, {1, -1}, {1, 1}, {-1, 1}}, {0, 1, 2, 3}) or_return
|
state.rect_vao = create_vao({{-1, -1}, {1, -1}, {1, 1}, {-1, 1}}, {0, 1, 2, 3}) or_return
|
||||||
|
// state.circle_vao = create_vao({{-1, -1}, {1, -1}, {1, 1}, {-1, 1}}, {0, 1, 2, 3}) or_return
|
||||||
CIRCLE_POINTS :: 127
|
|
||||||
circle_vertices: [CIRCLE_POINTS + 1]ℝ²
|
|
||||||
circle_indices: [CIRCLE_POINTS + 2]u32
|
|
||||||
|
|
||||||
for i in 0 ..< CIRCLE_POINTS {
|
|
||||||
θ := ℝ(i) * 2 * math.π / CIRCLE_POINTS
|
|
||||||
circle_vertices[i + 1] = {math.cos(θ), math.sin(θ)}
|
|
||||||
circle_indices[i + 1] = u32(i + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
circle_indices[CIRCLE_POINTS + 1] = circle_indices[1]
|
|
||||||
|
|
||||||
state.circle_vao = create_vao(circle_vertices[:], circle_indices[:]) or_return
|
|
||||||
|
|
||||||
init_command_queue()
|
init_command_queue()
|
||||||
|
|
||||||
|
@ -126,7 +127,9 @@ init :: proc() -> (state: State, ok: bool) {
|
||||||
// }}}
|
// }}}
|
||||||
// {{{ Close
|
// {{{ Close
|
||||||
close :: proc(state: State) {
|
close :: proc(state: State) {
|
||||||
OpenGL.DeleteProgram(state.program)
|
OpenGL.DeleteProgram(state.rect_program)
|
||||||
|
OpenGL.DeleteProgram(state.circle_program)
|
||||||
|
|
||||||
_ = sdl3.StopTextInput(state.window)
|
_ = sdl3.StopTextInput(state.window)
|
||||||
sdl3.DestroyWindow(state.window)
|
sdl3.DestroyWindow(state.window)
|
||||||
sdl3.Quit()
|
sdl3.Quit()
|
||||||
|
@ -136,16 +139,6 @@ close :: proc(state: State) {
|
||||||
// {{{ Render
|
// {{{ Render
|
||||||
render :: proc(state: ^State) {
|
render :: proc(state: ^State) {
|
||||||
state.tick += 1
|
state.tick += 1
|
||||||
OpenGL.Clear(OpenGL.COLOR_BUFFER_BIT | OpenGL.DEPTH_BUFFER_BIT)
|
|
||||||
|
|
||||||
OpenGL.UseProgram(state.program)
|
|
||||||
defer OpenGL.UseProgram(0)
|
|
||||||
|
|
||||||
if state.wireframe {
|
|
||||||
OpenGL.PolygonMode(OpenGL.FRONT_AND_BACK, OpenGL.LINE)
|
|
||||||
} else {
|
|
||||||
OpenGL.PolygonMode(OpenGL.FRONT_AND_BACK, OpenGL.FILL)
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_rect({-0.5, 0}, {0.75, 0.5}, {1, 0, 0, 1}, z = 0.5)
|
draw_rect({-0.5, 0}, {0.75, 0.5}, {1, 0, 0, 1}, z = 0.5)
|
||||||
draw_rect({0.5, 0.25}, {0.3, 0.5}, {0, 1, 0, 1}, z = -0.5)
|
draw_rect({0.5, 0.25}, {0.3, 0.5}, {0, 1, 0, 1}, z = -0.5)
|
||||||
|
@ -171,6 +164,9 @@ render :: proc(state: ^State) {
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_circle({-0.25, -0.3}, 0.6, Color{0, 0, 0.5, 0.75}, z = -0.1)
|
draw_circle({-0.25, -0.3}, 0.6, Color{0, 0, 0.5, 0.75}, z = -0.1)
|
||||||
|
draw_line({-0.25, 0}, {0.66, 0.4}, 0.01, Color{1, 1, 1, 1}, z = -0.5)
|
||||||
|
|
||||||
|
clear_screen()
|
||||||
render_queue(state)
|
render_queue(state)
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
13
odin/sdl-opengl-rendering/src/math.odin
Normal file
13
odin/sdl-opengl-rendering/src/math.odin
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package visuals
|
||||||
|
|
||||||
|
ℝ :: f32
|
||||||
|
ℝ² :: [2]ℝ
|
||||||
|
ℝ³ :: [3]ℝ
|
||||||
|
ℕ :: uint
|
||||||
|
Mat3 :: matrix[3, 3]ℝ
|
||||||
|
Color :: [4]ℝ
|
||||||
|
|
||||||
|
// Get a vector perpendicular to the given input
|
||||||
|
vec2_perp :: proc(v: ℝ²) -> ℝ² {
|
||||||
|
return {-v.y, v.x}
|
||||||
|
}
|
13
odin/sdl-opengl-rendering/src/shaders/circle.frag.glsl
Normal file
13
odin/sdl-opengl-rendering/src/shaders/circle.frag.glsl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
in vec4 vertexColor;
|
||||||
|
in vec2 vertexPos;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 p = vertexPos;
|
||||||
|
float mask = p.x * p.x + p.y * p.y > 1 ? 0 : 1;
|
||||||
|
|
||||||
|
FragColor = mask * vertexColor;
|
||||||
|
}
|
18
odin/sdl-opengl-rendering/src/shaders/line.frag.glsl
Normal file
18
odin/sdl-opengl-rendering/src/shaders/line.frag.glsl
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
in vec4 vertexColor;
|
||||||
|
in vec2 vertexPos;
|
||||||
|
|
||||||
|
float sdfLine(vec2 p) {
|
||||||
|
return abs(p.y) - 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
float aWidth = 0.001;
|
||||||
|
float dist = sdfLine(vertexPos);
|
||||||
|
float alpha = smoothstep(aWidth, -aWidth, dist);
|
||||||
|
|
||||||
|
FragColor = vec4(vertexColor.xyz, alpha * vertexColor.a);
|
||||||
|
}
|
|
@ -5,9 +5,11 @@ layout (location = 1) in vec4 instanceFill;
|
||||||
layout (location = 2) in mat3 instanceMatrix;
|
layout (location = 2) in mat3 instanceMatrix;
|
||||||
|
|
||||||
out vec4 vertexColor;
|
out vec4 vertexColor;
|
||||||
|
out vec2 vertexPos;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec3 pos = instanceMatrix * vec3(aPos.xy, 1);
|
vec3 pos = instanceMatrix * vec3(aPos.xy, 1);
|
||||||
gl_Position = vec4(pos.xyz, 1);
|
gl_Position = vec4(pos.xyz, 1);
|
||||||
vertexColor = instanceFill;
|
vertexColor = instanceFill;
|
||||||
|
vertexPos = aPos.xy;
|
||||||
}
|
}
|
|
@ -1,21 +1,15 @@
|
||||||
package visuals
|
package visuals
|
||||||
|
|
||||||
import "core:log"
|
import "core:log"
|
||||||
|
import "core:math/linalg"
|
||||||
import "vendor:OpenGL"
|
import "vendor:OpenGL"
|
||||||
|
|
||||||
// {{{ Math constants
|
|
||||||
ℝ :: f32
|
|
||||||
ℝ² :: [2]ℝ
|
|
||||||
ℝ³ :: [3]ℝ
|
|
||||||
ℕ :: uint
|
|
||||||
Mat3 :: matrix[3, 3]ℝ
|
|
||||||
Color :: [4]ℝ
|
|
||||||
// }}}
|
|
||||||
// {{{ Command queues
|
// {{{ Command queues
|
||||||
Shape :: struct {
|
Shape :: struct {
|
||||||
z: ℝ,
|
z: ℝ,
|
||||||
fill: Color,
|
fill: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect :: struct {
|
Rect :: struct {
|
||||||
using shape: Shape,
|
using shape: Shape,
|
||||||
top_left: ℝ²,
|
top_left: ℝ²,
|
||||||
|
@ -28,9 +22,17 @@ Circle :: struct {
|
||||||
radius: ℝ,
|
radius: ℝ,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Line :: struct {
|
||||||
|
using shape: Shape,
|
||||||
|
from: ℝ²,
|
||||||
|
to: ℝ²,
|
||||||
|
thickness: ℝ,
|
||||||
|
}
|
||||||
|
|
||||||
Command_Queue :: struct {
|
Command_Queue :: struct {
|
||||||
rects: [dynamic]Rect,
|
rects: [dynamic]Rect,
|
||||||
circles: [dynamic]Circle,
|
circles: [dynamic]Circle,
|
||||||
|
lines: [dynamic]Line,
|
||||||
}
|
}
|
||||||
|
|
||||||
queue: ^Command_Queue
|
queue: ^Command_Queue
|
||||||
|
@ -38,7 +40,9 @@ queue: ^Command_Queue
|
||||||
init_command_queue :: proc() {
|
init_command_queue :: proc() {
|
||||||
queue = new(Command_Queue)
|
queue = new(Command_Queue)
|
||||||
queue^ = Command_Queue {
|
queue^ = Command_Queue {
|
||||||
rects = make([dynamic]Rect),
|
rects = make([dynamic]Rect),
|
||||||
|
circles = make([dynamic]Circle),
|
||||||
|
lines = make([dynamic]Line),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +75,21 @@ draw_circle :: proc {
|
||||||
draw_circle_struct,
|
draw_circle_struct,
|
||||||
draw_circle_args,
|
draw_circle_args,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
draw_line_args :: proc(from, to: ℝ², thickness: ℝ, color: Color, z: ℝ = 0) {
|
||||||
|
draw_line_struct(
|
||||||
|
Line{from = from, to = to, thickness = thickness, shape = Shape{z = z, fill = color}},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_line_struct :: proc(line: Line) {
|
||||||
|
append(&queue.lines, line)
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_line :: proc {
|
||||||
|
draw_line_struct,
|
||||||
|
draw_line_args,
|
||||||
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
// {{{ VAO & consts
|
// {{{ VAO & consts
|
||||||
|
@ -151,12 +170,29 @@ create_vao :: proc(vertices: []ℝ², indices: []u32) -> (out: VAO, ok: bool) {
|
||||||
return out, true
|
return out, true
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
// {{{ Set rect transforms
|
// {{{ Set transforms
|
||||||
set_rect_transforms :: proc(vao: ^VAO, rects: []Rect) -> ℕ {
|
// Commit the contents of `state.buf_matrices` and `state.buf_colors` to the
|
||||||
log.assert(len(rects) <= INSTANCES, "Attempting to send too many rects to the GPU")
|
// GPU.
|
||||||
matrices := new([INSTANCES]Mat3, context.temp_allocator)
|
commit_buffers :: proc(state: ^State, vao: ^VAO) {
|
||||||
fills := new([INSTANCES]Color, context.temp_allocator)
|
OpenGL.BindBuffer(OpenGL.ARRAY_BUFFER, vao.instance_mat_buffer)
|
||||||
|
OpenGL.BufferData(
|
||||||
|
OpenGL.ARRAY_BUFFER,
|
||||||
|
INSTANCES * size_of(Mat3),
|
||||||
|
&state.buf_matrices,
|
||||||
|
OpenGL.DYNAMIC_DRAW,
|
||||||
|
)
|
||||||
|
|
||||||
|
OpenGL.BindBuffer(OpenGL.ARRAY_BUFFER, vao.instance_fill_buffer)
|
||||||
|
OpenGL.BufferData(
|
||||||
|
OpenGL.ARRAY_BUFFER,
|
||||||
|
INSTANCES * size_of(Color),
|
||||||
|
&state.buf_colors,
|
||||||
|
OpenGL.DYNAMIC_DRAW,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
set_rect_transforms :: proc(state: ^State, vao: ^VAO, rects: []Rect) -> ℕ {
|
||||||
|
log.assert(len(rects) <= INSTANCES, "Attempting to send too many rects to the GPU")
|
||||||
for rect, i in rects {
|
for rect, i in rects {
|
||||||
// This matrix must transform the rect [-1, 1]² into the desired rect
|
// This matrix must transform the rect [-1, 1]² into the desired rect
|
||||||
mat: Mat3
|
mat: Mat3
|
||||||
|
@ -167,27 +203,15 @@ set_rect_transforms :: proc(vao: ^VAO, rects: []Rect) -> ℕ {
|
||||||
mat[2].xy = center.xy
|
mat[2].xy = center.xy
|
||||||
mat[2].z = rect.z
|
mat[2].z = rect.z
|
||||||
|
|
||||||
matrices[i] = mat
|
state.buf_matrices[i] = mat
|
||||||
fills[i] = rect.fill
|
state.buf_colors[i] = rect.fill
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGL.BindBuffer(OpenGL.ARRAY_BUFFER, vao.instance_mat_buffer)
|
|
||||||
OpenGL.BufferData(
|
|
||||||
OpenGL.ARRAY_BUFFER,
|
|
||||||
INSTANCES * size_of(Mat3),
|
|
||||||
matrices,
|
|
||||||
OpenGL.DYNAMIC_DRAW,
|
|
||||||
)
|
|
||||||
OpenGL.BindBuffer(OpenGL.ARRAY_BUFFER, vao.instance_fill_buffer)
|
|
||||||
OpenGL.BufferData(OpenGL.ARRAY_BUFFER, INSTANCES * size_of(Color), fills, OpenGL.DYNAMIC_DRAW)
|
|
||||||
|
|
||||||
return len(rects)
|
return len(rects)
|
||||||
}
|
}
|
||||||
|
|
||||||
set_circle_transforms :: proc(vao: ^VAO, circles: []Circle) -> ℕ {
|
set_circle_transforms :: proc(state: ^State, vao: ^VAO, circles: []Circle) -> ℕ {
|
||||||
log.assert(len(circles) <= INSTANCES, "Attempting to send too many circles to the GPU")
|
log.assert(len(circles) <= INSTANCES, "Attempting to send too many circles to the GPU")
|
||||||
matrices := new([INSTANCES]Mat3, context.temp_allocator)
|
|
||||||
fills := new([INSTANCES]Color, context.temp_allocator)
|
|
||||||
|
|
||||||
for circle, i in circles {
|
for circle, i in circles {
|
||||||
mat: Mat3
|
mat: Mat3
|
||||||
|
@ -197,22 +221,31 @@ set_circle_transforms :: proc(vao: ^VAO, circles: []Circle) -> ℕ {
|
||||||
mat[2].xy = circle.center.xy
|
mat[2].xy = circle.center.xy
|
||||||
mat[2].z = circle.z
|
mat[2].z = circle.z
|
||||||
|
|
||||||
matrices[i] = mat
|
state.buf_matrices[i] = mat
|
||||||
fills[i] = circle.fill
|
state.buf_colors[i] = circle.fill
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGL.BindBuffer(OpenGL.ARRAY_BUFFER, vao.instance_mat_buffer)
|
|
||||||
OpenGL.BufferData(
|
|
||||||
OpenGL.ARRAY_BUFFER,
|
|
||||||
INSTANCES * size_of(Mat3),
|
|
||||||
matrices,
|
|
||||||
OpenGL.DYNAMIC_DRAW,
|
|
||||||
)
|
|
||||||
OpenGL.BindBuffer(OpenGL.ARRAY_BUFFER, vao.instance_fill_buffer)
|
|
||||||
OpenGL.BufferData(OpenGL.ARRAY_BUFFER, INSTANCES * size_of(Color), fills, OpenGL.DYNAMIC_DRAW)
|
|
||||||
|
|
||||||
return len(circles)
|
return len(circles)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_line_transforms :: proc(state: ^State, vao: ^VAO, lines: []Line) -> ℕ {
|
||||||
|
log.assert(len(lines) <= INSTANCES, "Attempting to send too many lines to the GPU")
|
||||||
|
|
||||||
|
for line, i in lines {
|
||||||
|
mat: Mat3
|
||||||
|
|
||||||
|
dir := line.to - line.from
|
||||||
|
mat[0].xy = dir / 2
|
||||||
|
mat[1].xy = vec2_perp(linalg.normalize0(dir)) * line.thickness
|
||||||
|
mat[2].xy = (line.from + line.to) / 2
|
||||||
|
mat[2].z = line.z
|
||||||
|
|
||||||
|
state.buf_matrices[i] = mat
|
||||||
|
state.buf_colors[i] = line.fill
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(lines)
|
||||||
|
}
|
||||||
// }}}
|
// }}}
|
||||||
// {{{ Render the entire queue
|
// {{{ Render the entire queue
|
||||||
draw_instances :: proc(vao: VAO, instances: ℕ) {
|
draw_instances :: proc(vao: VAO, instances: ℕ) {
|
||||||
|
@ -226,26 +259,47 @@ draw_instances :: proc(vao: VAO, instances: ℕ) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
render_queue :: proc(state: ^State) {
|
clear_screen :: proc() {
|
||||||
rect_steps := len(queue.rects) / INSTANCES
|
OpenGL.Clear(OpenGL.COLOR_BUFFER_BIT | OpenGL.DEPTH_BUFFER_BIT)
|
||||||
|
}
|
||||||
|
|
||||||
|
render_queue :: proc(state: ^State) {
|
||||||
|
if state.wireframe {
|
||||||
|
OpenGL.PolygonMode(OpenGL.FRONT_AND_BACK, OpenGL.LINE)
|
||||||
|
} else {
|
||||||
|
OpenGL.PolygonMode(OpenGL.FRONT_AND_BACK, OpenGL.FILL)
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGL.UseProgram(state.rect_program)
|
||||||
for i := 0; i < len(queue.rects); i += INSTANCES {
|
for i := 0; i < len(queue.rects); i += INSTANCES {
|
||||||
slice := queue.rects[i:]
|
slice := queue.rects[i:]
|
||||||
if len(slice) > INSTANCES {slice = slice[:INSTANCES]}
|
if len(slice) > INSTANCES {slice = slice[:INSTANCES]}
|
||||||
instances := set_rect_transforms(&state.rect_vao, slice)
|
instances := set_rect_transforms(state, &state.rect_vao, slice)
|
||||||
|
commit_buffers(state, &state.rect_vao)
|
||||||
draw_instances(state.rect_vao, instances)
|
draw_instances(state.rect_vao, instances)
|
||||||
}
|
}
|
||||||
|
|
||||||
clear(&queue.rects)
|
clear(&queue.rects)
|
||||||
circle_steps := len(queue.circles) / INSTANCES
|
|
||||||
|
|
||||||
|
OpenGL.UseProgram(state.circle_program)
|
||||||
for i := 0; i < len(queue.circles); i += INSTANCES {
|
for i := 0; i < len(queue.circles); i += INSTANCES {
|
||||||
slice := queue.circles[i:]
|
slice := queue.circles[i:]
|
||||||
if len(slice) > INSTANCES {slice = slice[:INSTANCES]}
|
if len(slice) > INSTANCES {slice = slice[:INSTANCES]}
|
||||||
instances := set_circle_transforms(&state.circle_vao, slice)
|
instances := set_circle_transforms(state, &state.rect_vao, slice)
|
||||||
draw_instances(state.circle_vao, instances)
|
commit_buffers(state, &state.rect_vao)
|
||||||
|
draw_instances(state.rect_vao, instances)
|
||||||
}
|
}
|
||||||
|
|
||||||
clear(&queue.circles)
|
clear(&queue.circles)
|
||||||
|
|
||||||
|
OpenGL.UseProgram(state.line_program)
|
||||||
|
for i := 0; i < len(queue.lines); i += INSTANCES {
|
||||||
|
slice := queue.lines[i:]
|
||||||
|
if len(slice) > INSTANCES {slice = slice[:INSTANCES]}
|
||||||
|
instances := set_line_transforms(state, &state.rect_vao, slice)
|
||||||
|
commit_buffers(state, &state.rect_vao)
|
||||||
|
draw_instances(state.rect_vao, instances)
|
||||||
|
}
|
||||||
|
clear(&queue.lines)
|
||||||
|
|
||||||
|
OpenGL.UseProgram(0)
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue