math/noise/draw_texture

Code

noise.odin ¶
295 linesSource

1package draw_texture
2
3import "base:runtime"
4
5import "core:c"
6import "core:fmt"
7import "core:math/linalg/glsl"
8import "core:math/noise"
9import "core:mem"
10
11import    "vendor:glfw"
12import gl "vendor:OpenGL"
13
14WIDTH  :: 400
15HEIGHT :: 400
16TITLE  :: cstring("Open Simplex 2 Texture!")
17
18// @note You might need to lower this to 3.3 depending on how old your graphics card is.
19GL_MAJOR_VERSION :: 4
20GL_MINOR_VERSION :: 1
21
22Adjust_Noise :: struct {
23	seed:       i64,
24	octaves:    i32,
25	frequency: f64,
26}
27
28Vertices :: [16]f32
29
30create_vertices :: proc(x, y, width, height: f32) -> Vertices {
31
32	/**
33
34	0 - x,y
35	1 - x, y + height
36	2 - x + width, y
37	3 - x + width, y + height
38
39	0      2
40	|-----/|
41	|   /  |
42	|  /   |
43	|/-----|
44	1      3
45
46	**/
47
48	vertices: Vertices = {
49		x, y,                   0.0, 1.0,
50		x, y + height,          0.0, 0.0,
51		x + width, y,           1.0, 1.0,
52		x + width, y + height,  1.0, 0.0,
53	}
54
55	return vertices
56}
57
58
59WAVELENGTH :: 120
60Pixel :: [4]u8
61
62noise_at :: proc(seed: i64, x, y: int) -> f32 {
63	return (noise.noise_2d(seed, {f64(x) / 120, f64(y) / 120}) + 1.0) / 2.0
64}
65
66create_texture_noise :: proc(texture_id: u32, adjust_noise: Adjust_Noise) {
67
68	texture_data := make([]u8, WIDTH * HEIGHT * 4)
69	defer delete(texture_data)
70
71	gl.BindTexture(gl.TEXTURE_2D, texture_id)
72	gl.ActiveTexture(gl.TEXTURE0)
73
74	gradient_location: glsl.vec2 = {f32(WIDTH / 2), f32(HEIGHT / 2)}
75
76	pixels := mem.slice_data_cast([]Pixel, texture_data)
77
78	for x := 0; x < WIDTH; x += 1 {
79
80		for y := 0; y < HEIGHT; y += 1 {
81
82			using adjust_noise := adjust_noise
83
84			noise_val: f32
85
86			{
87
88				for i := 0; i < int(octaves); i += 1 {
89					noise_val += 0.4 * ((noise.noise_2d(seed, {f64(x) / frequency / 2, f64(y) / frequency / 2}) + 1.0) / 2.0)
90					noise_val += 0.6 * ((noise.noise_2d(seed, {f64(x) / frequency * 2 ,f64(y) / frequency * 2}) + 1.0) / 2.0)
91					frequency *= glsl.exp(frequency)
92				}
93				noise_val /= f32(octaves)
94			}
95
96			val := glsl.distance_vec2({f32(x), f32(y)}, gradient_location)
97			val /= f32(HEIGHT / 2)
98
99			noise_val = noise_val - val
100
101			if noise_val < 0.0 {
102				noise_val = 0
103			}
104
105			val = glsl.clamp(val, 0.0, 1.0)
106			color := u8((noise_val) * 255.0)
107
108			switch {
109			case color <  20:
110				// Water
111				noise_val =  0.75 + 0.25 * noise_at(seed, x, y)
112				pixels[0] = {u8( 51 * noise_val), u8( 81 * noise_val), u8(251 * noise_val), 255}
113
114			case color <  30:
115				// Sand
116				noise_val = 0.75 + 0.25 * noise_at(seed, x, y)
117				pixels[0] = {u8(251 * noise_val), u8(244 * noise_val), u8(189 * noise_val), 255}
118
119			case color <  60:
120				// Grass
121				noise_val = 0.75 + 0.25 * noise_at(seed, x, y)
122				pixels[0] = {u8(124 * noise_val), u8(200 * noise_val), u8( 65 * noise_val), 255}
123
124			case color <  90:
125				// The forest
126				noise_val = 0.75 + 0.25 * noise_at(seed, x, y)
127				pixels[0] = {u8(124 * noise_val), u8(150 * noise_val), u8( 65 * noise_val), 255}
128
129			case color < 120:
130				// The Mountain
131				noise_val = 0.7 + 0.2 * noise_at(seed, x, y)
132				noise_val = glsl.pow(noise_val, 2)
133
134				pixels[0] = {u8(143 * noise_val), u8(143 * noise_val), u8(143 * noise_val), 255}
135
136			case:
137				// The peak of the mountain
138				noise_val = 0.7 + 0.2 * noise_at(seed, x, y)
139				noise_val = glsl.pow(noise_val, 2)
140
141				pixels[0] = {u8(205 * noise_val), u8(221 * noise_val), u8(246 * noise_val), 255}
142			}
143			pixels = pixels[1:]
144		}
145	}
146
147	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, i32(WIDTH), i32(HEIGHT), 0, gl.RGBA, gl.UNSIGNED_BYTE, &texture_data[0])
148}
149
150main :: proc() {
151
152	if !bool(glfw.Init()) {
153		fmt.println("GLFW has failed to load.")
154		return
155	}
156
157	glfw.SetErrorCallback(proc "c" (error: c.int, description: cstring) {
158		context = runtime.default_context()
159		fmt.println(description)
160	})
161
162	glfw.WindowHint(glfw.CONTEXT_VERSION_MAJOR, GL_MAJOR_VERSION)
163	glfw.WindowHint(glfw.CONTEXT_VERSION_MINOR, GL_MINOR_VERSION)
164	glfw.WindowHint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
165	glfw.WindowHint(glfw.OPENGL_FORWARD_COMPAT, 1)
166
167	window_handle := glfw.CreateWindow(WIDTH, HEIGHT, TITLE, nil, nil)
168
169	defer glfw.Terminate()
170	defer glfw.DestroyWindow(window_handle)
171
172	if window_handle == nil {
173		fmt.println("GLFW has failed to load the window.")
174		return
175	}
176
177	// Load OpenGL context or the "state" of OpenGL.
178	glfw.MakeContextCurrent(window_handle)
179	// Load OpenGL function pointers with the specficed OpenGL major and minor version.
180	gl.load_up_to(GL_MAJOR_VERSION, GL_MINOR_VERSION, glfw.gl_set_proc_address)
181
182	// Disable Vsync
183	glfw.SwapInterval(0)
184
185	vao: u32
186	vbo: u32
187	ebo: u32
188
189	gl.GenVertexArrays(1, &vao)
190	defer gl.DeleteVertexArrays(1, &vao)
191
192	gl.GenBuffers(1, &vbo)
193	gl.GenBuffers(1, &ebo)
194	defer gl.DeleteBuffers(1, &vbo)
195	defer gl.DeleteBuffers(1, &ebo)
196
197	gl.BindVertexArray(vao)
198	gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
199	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo)
200
201	vertices := create_vertices(x = 0, y = 0, width = WIDTH, height = HEIGHT)
202
203	/**
204
205	0      2
206	|-----/|
207	|   /  |
208	|  /   |
209	|/-----|
210	1      3
211
212	**/
213
214	indices: [6]u32 = {
215		0, 1, 2,
216		2, 1, 3,
217	}
218
219	gl.EnableVertexAttribArray(0)
220	gl.VertexAttribPointer(0, 2, gl.FLOAT, false, 4 * size_of(f32), 0)
221
222	gl.EnableVertexAttribArray(1)
223	gl.VertexAttribPointer(1, 2, gl.FLOAT, false, 4 * size_of(f32), size_of(f32) * 2)
224
225	gl.BufferData(gl.ARRAY_BUFFER,         len(vertices) * size_of(f32), raw_data(vertices[:]), gl.STATIC_DRAW)
226	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(indices)  * size_of(u32), raw_data(indices[:]),  gl.STATIC_DRAW)
227
228	program_id: u32; ok: bool
229	if program_id, ok = gl.load_shaders("./shader.vert", "./shader.frag"); !ok {
230		fmt.println("Failed to load shaders.")
231		return
232	}
233	defer gl.DeleteProgram(program_id)
234
235	texture_id : u32
236	gl.GenTextures(1, &texture_id)
237	defer gl.DeleteTextures(1, &texture_id)
238
239	gl.BindTexture(gl.TEXTURE_2D, texture_id)
240	gl.ActiveTexture(gl.TEXTURE0)
241
242	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT)
243	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT)
244	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
245	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
246
247	ortho := glsl.mat4Ortho3d(0.0, f32(WIDTH), f32(HEIGHT), 0.0, 1.0, 100.0)
248
249	adjust_noise: Adjust_Noise
250	adjust_noise.frequency = WIDTH / 2
251	adjust_noise.octaves = 1
252	adjust_noise.seed = 360000
253
254	create_texture_noise(texture_id, adjust_noise)
255
256
257	for !glfw.WindowShouldClose(window_handle) {
258
259		// Process all incoming events like keyboard press, window resize, and etc.
260		glfw.PollEvents()
261
262		if glfw.GetKey(window_handle, glfw.KEY_COMMA) == glfw.PRESS && glfw.GetKey(window_handle, glfw.KEY_LEFT_SHIFT) == glfw.PRESS {
263			adjust_noise.frequency -= 5.0
264			adjust_noise.frequency = glsl.clamp(adjust_noise.frequency, 1, 9000)
265			create_texture_noise(texture_id, adjust_noise)
266		} else if glfw.GetKey(window_handle, glfw.KEY_COMMA) == glfw.PRESS {
267			adjust_noise.frequency += 5.0
268			create_texture_noise(texture_id, adjust_noise)
269		}
270
271		if glfw.GetKey(window_handle, glfw.KEY_PERIOD) == glfw.PRESS && glfw.GetKey(window_handle, glfw.KEY_LEFT_SHIFT) == glfw.PRESS {
272			adjust_noise.octaves -= 1.0
273			adjust_noise.octaves = glsl.clamp(adjust_noise.octaves, 1, 100)
274			create_texture_noise(texture_id, adjust_noise)
275		} else if glfw.GetKey(window_handle, glfw.KEY_PERIOD) == glfw.PRESS {
276			adjust_noise.octaves += 1.0
277			create_texture_noise(texture_id, adjust_noise)
278		}
279
280		gl.ClearColor(0.5, 0.0, 1.0, 1.0)
281		gl.Clear(gl.COLOR_BUFFER_BIT)
282
283		gl.UseProgram(program_id)
284		gl.BindVertexArray(vao)
285		gl.BindTexture(gl.TEXTURE_2D, texture_id)
286		gl.ActiveTexture(gl.TEXTURE0)
287		gl.Uniform1i(gl.GetUniformLocation(program_id, "u_texture"), 0)
288		gl.UniformMatrix4fv(gl.GetUniformLocation(program_id, "u_projection"), 1, gl.FALSE, &ortho[0][0])
289
290		gl.DrawElements(gl.TRIANGLES, i32(len(indices)), gl.UNSIGNED_INT, nil)
291
292		glfw.SwapBuffers(window_handle)
293
294	}
295}

Shaders

shader.frag ¶
10 linesSource

#version 330 core

layout(location = 0) out vec4 color;
		
in vec2 texture_coords;
uniform sampler2D u_texture;

void main() {
		color = texture(u_texture, texture_coords);
}

shader.vert ¶
15 linesSource

#version 330 core

layout(location = 0) in vec2 xy;
layout(location = 1) in vec2 passed_texture_coords;
		
uniform mat4 u_projection;
out vec2 texture_coords;

void main() {
        // Get rid of the z dimension.
        vec4 xy_copy = u_projection * vec4(xy, 1.0, 1.0);
	xy_copy.z = 1.0;
	gl_Position = xy_copy;
	texture_coords = passed_texture_coords;
}

Declarations Used 76