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
|
||||
!.envrc
|
||||
|
|
59
odin/sdl-opengl-rendering/flake.lock
generated
59
odin/sdl-opengl-rendering/flake.lock
generated
|
@ -20,11 +20,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1738680400,
|
||||
"narHash": "sha256-ooLh+XW8jfa+91F1nhf9OF7qhuA/y1ChLx6lXDNeY5U=",
|
||||
"lastModified": 1748693115,
|
||||
"narHash": "sha256-StSrWhklmDuXT93yc3GrTlb0cKSS0agTAxMGjLKAsY8=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "799ba5bffed04ced7067a91798353d360788b30d",
|
||||
"rev": "910796cabe436259a29a72e8d3f5e180fc6dfacc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -34,10 +34,61 @@
|
|||
"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": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
"nixpkgs": "nixpkgs",
|
||||
"odin": "odin",
|
||||
"ols": "ols"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
|
|
|
@ -2,74 +2,42 @@
|
|||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
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 =
|
||||
inputs:
|
||||
{
|
||||
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 ]) (
|
||||
inputs.flake-utils.lib.eachSystem (with inputs.flake-utils.lib.system; [ x86_64-linux ]) (
|
||||
system:
|
||||
let
|
||||
pkgs = inputs.nixpkgs.legacyPackages.${system}.extend inputs.self.overlays.default;
|
||||
cross = import inputs.nixpkgs {
|
||||
localSystem = system;
|
||||
crossSystem.config = "x86_64-w64-mingw32";
|
||||
pkgs = import inputs.nixpkgs {
|
||||
inherit system;
|
||||
overlays = [
|
||||
inputs.odin.overlays.default
|
||||
inputs.ols.overlays.default
|
||||
];
|
||||
};
|
||||
|
||||
inherit (pkgs) lib;
|
||||
in
|
||||
{
|
||||
packages = {
|
||||
inherit (pkgs) odin;
|
||||
gcc = cross.callPackage (import ./gcc.nix) { };
|
||||
libgl = cross.libGL;
|
||||
};
|
||||
|
||||
# {{{ Shell
|
||||
devShell = pkgs.mkShell rec {
|
||||
nativeBuildInputs = [
|
||||
pkgs.pkg-config
|
||||
pkgs.entr # File change detection
|
||||
pkgs.odin # Compiler
|
||||
pkgs.mold # Linker
|
||||
pkgs.ols # Language server
|
||||
pkgs.just # Script runner
|
||||
pkgs.samply # Profiler
|
||||
pkgs.ols # Language server
|
||||
pkgs.gdb # Debugger
|
||||
pkgs.seer # Debugger GUI
|
||||
pkgs.valgrind # Detect memory leaks
|
||||
|
|
|
@ -11,10 +11,14 @@ import "vendor:sdl3"
|
|||
State :: struct {
|
||||
tick: u32,
|
||||
window: ^sdl3.Window,
|
||||
program: u32,
|
||||
rect_program: u32,
|
||||
circle_program: u32,
|
||||
line_program: u32,
|
||||
rect_vao: VAO,
|
||||
circle_vao: VAO,
|
||||
wireframe: bool,
|
||||
buf_matrices: [INSTANCES]Mat3,
|
||||
buf_colors: [INSTANCES]Color,
|
||||
}
|
||||
|
||||
// {{{ Initialization
|
||||
|
@ -98,26 +102,23 @@ init :: proc() -> (state: State, ok: bool) {
|
|||
OpenGL.Enable(OpenGL.BLEND)
|
||||
OpenGL.BlendFunc(OpenGL.SRC_ALPHA, OpenGL.ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
state.program = OpenGL.load_shaders_source(
|
||||
#load("./vert.glsl"),
|
||||
#load("./frag.glsl"),
|
||||
state.rect_program = OpenGL.load_shaders_source(
|
||||
#load("./shaders/vert.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
|
||||
|
||||
state.rect_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
|
||||
// state.circle_vao = create_vao({{-1, -1}, {1, -1}, {1, 1}, {-1, 1}}, {0, 1, 2, 3}) or_return
|
||||
|
||||
init_command_queue()
|
||||
|
||||
|
@ -126,7 +127,9 @@ init :: proc() -> (state: State, ok: bool) {
|
|||
// }}}
|
||||
// {{{ Close
|
||||
close :: proc(state: State) {
|
||||
OpenGL.DeleteProgram(state.program)
|
||||
OpenGL.DeleteProgram(state.rect_program)
|
||||
OpenGL.DeleteProgram(state.circle_program)
|
||||
|
||||
_ = sdl3.StopTextInput(state.window)
|
||||
sdl3.DestroyWindow(state.window)
|
||||
sdl3.Quit()
|
||||
|
@ -136,16 +139,6 @@ close :: proc(state: State) {
|
|||
// {{{ Render
|
||||
render :: proc(state: ^State) {
|
||||
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.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_line({-0.25, 0}, {0.66, 0.4}, 0.01, Color{1, 1, 1, 1}, z = -0.5)
|
||||
|
||||
clear_screen()
|
||||
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;
|
||||
|
||||
out vec4 vertexColor;
|
||||
out vec2 vertexPos;
|
||||
|
||||
void main() {
|
||||
vec3 pos = instanceMatrix * vec3(aPos.xy, 1);
|
||||
gl_Position = vec4(pos.xyz, 1);
|
||||
vertexColor = instanceFill;
|
||||
vertexPos = aPos.xy;
|
||||
}
|
|
@ -1,21 +1,15 @@
|
|||
package visuals
|
||||
|
||||
import "core:log"
|
||||
import "core:math/linalg"
|
||||
import "vendor:OpenGL"
|
||||
|
||||
// {{{ Math constants
|
||||
ℝ :: f32
|
||||
ℝ² :: [2]ℝ
|
||||
ℝ³ :: [3]ℝ
|
||||
ℕ :: uint
|
||||
Mat3 :: matrix[3, 3]ℝ
|
||||
Color :: [4]ℝ
|
||||
// }}}
|
||||
// {{{ Command queues
|
||||
Shape :: struct {
|
||||
z: ℝ,
|
||||
fill: Color,
|
||||
}
|
||||
|
||||
Rect :: struct {
|
||||
using shape: Shape,
|
||||
top_left: ℝ²,
|
||||
|
@ -28,9 +22,17 @@ Circle :: struct {
|
|||
radius: ℝ,
|
||||
}
|
||||
|
||||
Line :: struct {
|
||||
using shape: Shape,
|
||||
from: ℝ²,
|
||||
to: ℝ²,
|
||||
thickness: ℝ,
|
||||
}
|
||||
|
||||
Command_Queue :: struct {
|
||||
rects: [dynamic]Rect,
|
||||
circles: [dynamic]Circle,
|
||||
lines: [dynamic]Line,
|
||||
}
|
||||
|
||||
queue: ^Command_Queue
|
||||
|
@ -39,6 +41,8 @@ init_command_queue :: proc() {
|
|||
queue = new(Command_Queue)
|
||||
queue^ = Command_Queue {
|
||||
rects = make([dynamic]Rect),
|
||||
circles = make([dynamic]Circle),
|
||||
lines = make([dynamic]Line),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,6 +75,21 @@ draw_circle :: proc {
|
|||
draw_circle_struct,
|
||||
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
|
||||
|
@ -151,12 +170,29 @@ create_vao :: proc(vertices: []ℝ², indices: []u32) -> (out: VAO, ok: bool) {
|
|||
return out, true
|
||||
}
|
||||
// }}}
|
||||
// {{{ Set rect transforms
|
||||
set_rect_transforms :: proc(vao: ^VAO, rects: []Rect) -> ℕ {
|
||||
log.assert(len(rects) <= INSTANCES, "Attempting to send too many rects to the GPU")
|
||||
matrices := new([INSTANCES]Mat3, context.temp_allocator)
|
||||
fills := new([INSTANCES]Color, context.temp_allocator)
|
||||
// {{{ Set transforms
|
||||
// Commit the contents of `state.buf_matrices` and `state.buf_colors` to the
|
||||
// GPU.
|
||||
commit_buffers :: proc(state: ^State, vao: ^VAO) {
|
||||
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 {
|
||||
// This matrix must transform the rect [-1, 1]² into the desired rect
|
||||
mat: Mat3
|
||||
|
@ -167,27 +203,15 @@ set_rect_transforms :: proc(vao: ^VAO, rects: []Rect) -> ℕ {
|
|||
mat[2].xy = center.xy
|
||||
mat[2].z = rect.z
|
||||
|
||||
matrices[i] = mat
|
||||
fills[i] = rect.fill
|
||||
state.buf_matrices[i] = mat
|
||||
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)
|
||||
}
|
||||
|
||||
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")
|
||||
matrices := new([INSTANCES]Mat3, context.temp_allocator)
|
||||
fills := new([INSTANCES]Color, context.temp_allocator)
|
||||
|
||||
for circle, i in circles {
|
||||
mat: Mat3
|
||||
|
@ -197,22 +221,31 @@ set_circle_transforms :: proc(vao: ^VAO, circles: []Circle) -> ℕ {
|
|||
mat[2].xy = circle.center.xy
|
||||
mat[2].z = circle.z
|
||||
|
||||
matrices[i] = mat
|
||||
fills[i] = circle.fill
|
||||
state.buf_matrices[i] = mat
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
draw_instances :: proc(vao: VAO, instances: ℕ) {
|
||||
|
@ -226,26 +259,47 @@ draw_instances :: proc(vao: VAO, instances: ℕ) {
|
|||
)
|
||||
}
|
||||
|
||||
render_queue :: proc(state: ^State) {
|
||||
rect_steps := len(queue.rects) / INSTANCES
|
||||
clear_screen :: proc() {
|
||||
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 {
|
||||
slice := queue.rects[i:]
|
||||
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)
|
||||
}
|
||||
|
||||
clear(&queue.rects)
|
||||
circle_steps := len(queue.circles) / INSTANCES
|
||||
|
||||
OpenGL.UseProgram(state.circle_program)
|
||||
for i := 0; i < len(queue.circles); i += INSTANCES {
|
||||
slice := queue.circles[i:]
|
||||
if len(slice) > INSTANCES {slice = slice[:INSTANCES]}
|
||||
instances := set_circle_transforms(&state.circle_vao, slice)
|
||||
draw_instances(state.circle_vao, instances)
|
||||
instances := set_circle_transforms(state, &state.rect_vao, slice)
|
||||
commit_buffers(state, &state.rect_vao)
|
||||
draw_instances(state.rect_vao, instances)
|
||||
}
|
||||
|
||||
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