nanovg/fbo

Code

fbo.odin ¶
154 linesSource

1package main
2
3/*
4Original Source: https://github.com/memononen/nanovg/blob/master/example/example_fbo.c
5Can be run using: odin.exe run main.odin -file
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	// Draw some stuff to an FBO as a test
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}

Assets 2

Declarations Used 56