fbo.odin ¶
1package main
2
3
4
5
6
7
8import "core:fmt"
9import "core:math"
10import gl "vendor:OpenGL"
11import glfw "vendor:glfw"
12import nvg "vendor:nanovg"
13import nvg_gl "vendor:nanovg/gl"
14
15renderPattern :: proc(ctx: ^nvg.Context, fb: ^nvg_gl.framebuffer, t: f32, pxRatio: f32) {
16 s := f32(20)
17 sr := (math.cos(t) + 1) * 0.5
18 r := s * 0.6 * (0.2 + 0.8 * sr)
19
20 if fb == nil {
21 return
22 }
23
24 fboWidth, fboHeight := nvg.ImageSize(ctx, fb.image)
25 winWidth := int(f32(fboWidth) / pxRatio)
26 winHeight := int(f32(fboHeight) / pxRatio)
27
28
29 nvg_gl.BindFramebuffer(fb)
30 gl.Viewport(0, 0, i32(fboWidth), i32(fboHeight))
31 gl.ClearColor(0, 0, 0, 0)
32 gl.Clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)
33 nvg.BeginFrame(ctx, f32(winWidth), f32(winHeight), pxRatio)
34
35 pw := math.ceil(f32(winWidth) / s)
36 ph := math.ceil(f32(winHeight) / s)
37
38 nvg.BeginPath(ctx)
39 for y in 0 ..< ph {
40 for x in 0 ..< pw {
41 cx := (x + 0.5) * s
42 cy := (y + 0.5) * s
43 nvg.Circle(ctx, cx, cy, r)
44 }
45 }
46 nvg.FillColor(ctx, nvg.RGBA(220, 160, 0, 200))
47 nvg.Fill(ctx)
48
49 nvg.EndFrame(ctx)
50 nvg_gl.BindFramebuffer(nil)
51}
52
53loadFonts :: proc(ctx: ^nvg.Context) -> bool {
54 font: int
55 font = nvg.CreateFont(ctx, "sans", "fonts/Roboto-Regular.ttf")
56 if font == -1 {
57 fmt.printf("Could not add font regular.\n")
58 return false
59 }
60 font = nvg.CreateFont(ctx, "sans-bold", "fonts/Roboto-Bold.ttf")
61 if font == -1 {
62 fmt.printf("Could not add font bold.\n")
63 return false
64 }
65 return true
66}
67
68main :: proc() {
69 if !glfw.Init() {
70 panic("glfw failed")
71 }
72
73 glfw.WindowHint(glfw.CONTEXT_VERSION_MAJOR, 4)
74 glfw.WindowHint(glfw.CONTEXT_VERSION_MINOR, 5)
75 glfw.WindowHint(glfw.OPENGL_FORWARD_COMPAT, 1)
76 glfw.WindowHint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
77 glfw.WindowHint(glfw.OPENGL_DEBUG_CONTEXT, 1)
78
79 window := glfw.CreateWindow(1000, 600, "NanoVG", nil, nil)
80
81 if window == nil {
82 glfw.Terminate()
83 panic("glfw window failed")
84 }
85
86 glfw.MakeContextCurrent(window)
87 gl.load_up_to(4, 5, glfw.gl_set_proc_address)
88
89 ctx := nvg_gl.Create({.ANTI_ALIAS, .STENCIL_STROKES, .DEBUG})
90 defer nvg_gl.Destroy(ctx)
91
92 glfw.SetTime(0)
93 prevt := glfw.GetTime()
94
95 fw, fh := glfw.GetFramebufferSize(window)
96 w, h := glfw.GetWindowSize(window)
97 px_ratio := f32(fw) / f32(fw)
98 fb := nvg_gl.CreateFramebuffer(
99 ctx,
100 int(100 * px_ratio),
101 int(100 * px_ratio),
102 {.REPEAT_X, .REPEAT_Y},
103 )
104
105 if !loadFonts(ctx) {
106 panic("Could not load fonts")
107 }
108
109 for !glfw.WindowShouldClose(window) {
110 t := glfw.GetTime()
111 prevt = t
112
113 fw, fh = glfw.GetFramebufferSize(window)
114 w, h = glfw.GetWindowSize(window)
115 px_ratio = f32(fw) / f32(fw)
116
117 renderPattern(ctx, &fb, f32(t), px_ratio)
118
119 gl.Viewport(0, 0, fw, fh)
120 gl.ClearColor(0.3, 0.3, 0.32, 1.0)
121 gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)
122
123 {
124 nvg.FrameScoped(ctx, f32(w), f32(h), px_ratio)
125
126 img := nvg.ImagePattern(0, 0, 100, 100, 0, fb.image, 1.0)
127 nvg.SaveScoped(ctx)
128
129 for i in 0 ..< 20 {
130 nvg.FillScoped(ctx)
131 nvg.Rect(ctx, 10 + f32(i) * 30, 10, 10, f32(w) - 20)
132 nvg.FillColor(ctx, nvg.HSLA(f32(i) / 19.0, 0.5, 0.5, 255))
133 }
134
135 nvg.BeginPath(ctx)
136 nvg.RoundedRect(
137 ctx,
138 140 + math.sin(f32(t) * 1.3) * 100,
139 140 + math.cos(f32(t) * 1.71244) * 100,
140 250,
141 250,
142 20,
143 )
144 nvg.FillPaint(ctx, img)
145 nvg.Fill(ctx)
146 nvg.StrokeColor(ctx, nvg.RGBA(220, 160, 0, 255))
147 nvg.StrokeWidth(ctx, 3.0)
148 nvg.Stroke(ctx)
149 }
150
151 glfw.SwapBuffers(window)
152 glfw.PollEvents()
153 }
154}