opengl/minimal_sdl2

Code

sdl2_opengl_demo.odin ¶
184 linesSource

1package main
2
3import "core:fmt"
4import glm "core:math/linalg/glsl"
5import "core:time"
6
7import SDL "vendor:sdl2"
8import gl "vendor:OpenGL"
9
10GL_VERSION_MAJOR :: 3
11GL_VERSION_MINOR :: 3
12
13main :: proc() {
14	WINDOW_WIDTH  :: 854
15	WINDOW_HEIGHT :: 480
16
17	SDL.Init({.VIDEO})
18	defer SDL.Quit()
19
20	window := SDL.CreateWindow("Odin SDL2 Demo", SDL.WINDOWPOS_UNDEFINED, SDL.WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT, {.OPENGL})
21	if window == nil {
22		fmt.eprintln("Failed to create window")
23		return
24	}
25	defer SDL.DestroyWindow(window)
26
27	SDL.GL_SetAttribute(.CONTEXT_PROFILE_MASK,  i32(SDL.GLprofile.CORE))
28	SDL.GL_SetAttribute(.CONTEXT_MAJOR_VERSION, GL_VERSION_MAJOR)
29	SDL.GL_SetAttribute(.CONTEXT_MINOR_VERSION, GL_VERSION_MINOR)
30
31	gl_context := SDL.GL_CreateContext(window)
32	defer SDL.GL_DeleteContext(gl_context)
33
34	// load the OpenGL procedures once an OpenGL context has been established
35	gl.load_up_to(GL_VERSION_MAJOR, GL_VERSION_MINOR, SDL.gl_set_proc_address)
36
37	// useful utility procedures that are part of vendor:OpenGl
38	program, program_ok := gl.load_shaders_source(vertex_source, fragment_source)
39	if !program_ok {
40		fmt.eprintln("Failed to create GLSL program")
41		return
42	}
43	defer gl.DeleteProgram(program)
44
45	gl.UseProgram(program)
46
47	uniforms := gl.get_uniforms_from_program(program)
48	defer delete(uniforms)
49
50	vao: u32
51	gl.GenVertexArrays(1, &vao); defer gl.DeleteVertexArrays(1, &vao)
52	gl.BindVertexArray(vao)
53
54	// initialization of OpenGL buffers
55	vbo, ebo: u32
56	gl.GenBuffers(1, &vbo); defer gl.DeleteBuffers(1, &vbo)
57	gl.GenBuffers(1, &ebo); defer gl.DeleteBuffers(1, &ebo)
58
59	// struct declaration
60	Vertex :: struct {
61		pos: glm.vec3,
62		col: glm.vec4,
63	}
64
65	vertices := []Vertex{
66		{{-0.5, +0.5, 0}, {1.0, 0.0, 0.0, 0.75}},
67		{{-0.5, -0.5, 0}, {1.0, 1.0, 0.0, 0.75}},
68		{{+0.5, -0.5, 0}, {0.0, 1.0, 0.0, 0.75}},
69		{{+0.5, +0.5, 0}, {0.0, 0.0, 1.0, 0.75}},
70	}
71
72	indices := []u16{
73		0, 1, 2,
74		2, 3, 0,
75	}
76
77	gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
78	gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*size_of(vertices[0]), raw_data(vertices), gl.STATIC_DRAW)
79	gl.EnableVertexAttribArray(0)
80	gl.EnableVertexAttribArray(1)
81	gl.VertexAttribPointer(0, 3, gl.FLOAT, false, size_of(Vertex), offset_of(Vertex, pos))
82	gl.VertexAttribPointer(1, 4, gl.FLOAT, false, size_of(Vertex), offset_of(Vertex, col))
83
84	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo)
85	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(indices)*size_of(indices[0]), raw_data(indices), gl.STATIC_DRAW)
86
87	// high precision timer
88	start_tick := time.tick_now()
89
90	loop: for {
91		duration := time.tick_since(start_tick)
92		t := f32(time.duration_seconds(duration))
93
94		// event polling
95		event: SDL.Event
96		for SDL.PollEvent(&event) {
97			// #partial switch tells the compiler not to error if every case is not present
98			#partial switch event.type {
99			case .KEYDOWN:
100				#partial switch event.key.keysym.sym {
101				case .ESCAPE:
102					// labelled control flow
103					break loop
104				}
105			case .QUIT:
106				// labelled control flow
107				break loop
108			}
109		}
110
111		// Native support for GLSL-like functionality
112		pos := glm.vec3{
113			glm.cos(t*2),
114			glm.sin(t*2),
115			0,
116		}
117
118		// array programming support
119		pos *= 0.3
120
121		// matrix support
122		// model matrix which a default scale of 0.5
123		model := glm.mat4{
124			0.5,   0,   0, 0,
125			  0, 0.5,   0, 0,
126			  0,   0, 0.5, 0,
127			  0,   0,   0, 1,
128		}
129
130		// matrix indexing and array short with `.x`
131		model[0, 3] = -pos.x
132		model[1, 3] = -pos.y
133		model[2, 3] = -pos.z
134
135		// native swizzling support for arrays
136		model[3].yzx = pos.yzx
137
138		model = model * glm.mat4Rotate({0, 1, 1}, t)
139
140		view := glm.mat4LookAt({0, -1, +1}, {0, 0, 0}, {0, 0, 1})
141		proj := glm.mat4Perspective(45, 1.3, 0.1, 100.0)
142
143		// matrix multiplication
144		u_transform := proj * view * model
145
146		// matrix types in Odin are stored in column-major format but written as you'd normal write them
147		gl.UniformMatrix4fv(uniforms["u_transform"].location, 1, false, &u_transform[0, 0])
148
149		gl.Viewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT)
150		gl.ClearColor(0.5, 0.7, 1.0, 1.0)
151		gl.Clear(gl.COLOR_BUFFER_BIT)
152
153		gl.DrawElements(gl.TRIANGLES, i32(len(indices)), gl.UNSIGNED_SHORT, nil)
154
155		SDL.GL_SwapWindow(window)
156	}
157}
158
159
160vertex_source := `#version 330 core
161
162layout(location=0) in vec3 a_position;
163layout(location=1) in vec4 a_color;
164
165out vec4 v_color;
166
167uniform mat4 u_transform;
168
169void main() {
170	gl_Position = u_transform * vec4(a_position, 1.0);
171	v_color = a_color;
172}
173`
174
175fragment_source := `#version 330 core
176
177in vec4 v_color;
178
179out vec4 o_color;
180
181void main() {
182	o_color = v_color;
183}
184`

Declarations Used 51