From 62785bd02a94e9997f2ee893db5ac591d882840c Mon Sep 17 00:00:00 2001 From: Sander Hautvast Date: Fri, 23 Oct 2020 22:14:38 +0200 Subject: [PATCH] version2, it zooms, and it has colors --- README.md | 2 +- mandelbrot.nimble | 3 +- src/mandelbrot/mandelbrot.nim | 50 +++++- src/mandelbrot/shader.frag | 300 ++++++++++++++++++++++++++++++++-- 4 files changed, 333 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 54f8b14..d1eb944 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ * my first nim project https://nim-lang.org/ -* also: my first opengl project, manually translated from c++ from https://physicspython.wordpress.com/2020/02/16/visualizing-the-mandelbrot-set-using-opengl-part-1/ +* also: my first opengl project, manually translated from c++ found in https://physicspython.wordpress.com/2020/02/16/visualizing-the-mandelbrot-set-using-opengl-part-1/ * works at least on my mac diff --git a/mandelbrot.nimble b/mandelbrot.nimble index da63733..bee6c18 100644 --- a/mandelbrot.nimble +++ b/mandelbrot.nimble @@ -1,5 +1,4 @@ # Package - version = "0.1.0" author = "Sander Hautvast" description = "A mandelbrot fractal using opengl" @@ -8,4 +7,4 @@ srcDir = "src" bin = @["mandelbrot/mandelbrot"] # Dependencies -requires "nim >= 1.4.0", "nimgl >= 1.1.5" \ No newline at end of file +requires "nim >= 1.4.0", "nimgl >= 1.1.5", "glm >= 1.1.1" \ No newline at end of file diff --git a/src/mandelbrot/mandelbrot.nim b/src/mandelbrot/mandelbrot.nim index 25c8879..2c137b8 100644 --- a/src/mandelbrot/mandelbrot.nim +++ b/src/mandelbrot/mandelbrot.nim @@ -1,14 +1,36 @@ import nimgl/[glfw, opengl] + var GLData: tuple[program, vertexShader, fragmentShader: uint32] const WIN_WIDTH = 1000 WIN_HEIGHT = 800 +var + center_x = 0.0f + center_y = 0.0f + zoom:float64 = 1.0 + dx=0.0 + dy=0.0 + zf=0.99 proc keyProc(window: GLFWWindow, key: int32, scancode: int32, action: int32, mods: int32): void {.cdecl.} = - if key == GLFWKey.ESCAPE and action == GLFWPress: - window.setWindowShouldClose(true) +# if key == GLFWKey.ESCAPE and action == GLFWPress: +# window.setWindowShouldClose(true) + + +# proc process_input(window: GLFWwindow) + if action == GLFWPress: + if key == GLFWKey.ESCAPE: + window.setWindowShouldClose(true) + if key == GLFWKey.UP: + dy += 0.001f + if key == GLFWKey.DOWN: + dy -= 0.001f + if key == GLFWKey.LEFT: + dx -= 0.001f + if key == GLFWKey.RIGHT: + dx += 0.001f; proc logShaderCompilationFailure(shader: uint32, shader_path:string) = @@ -61,6 +83,13 @@ proc initShaders(vertex_shader_path: string, fragment_shader_path: string) = if success == 0: logProgramLinkingError() +proc set_float(name: string, value:float) = + glUniform1f(glGetUniformLocation(GLData.program, name.cstring()), value.cfloat()); + +# proc set_vec4(name: string, vec: Vec4[float]) = +# glUniform4f(glGetUniformLocation(GLData.program, name.cstring()), vec[0].cfloat(), vec[1].cfloat(), vec[2].cfloat(), vec[3].cfloat()) + + proc main() = assert glfwInit() @@ -70,7 +99,7 @@ proc main() = glfwWindowHint(GLFWOpenglProfile, GLFW_OPENGL_CORE_PROFILE) glfwWindowHint(GLFWResizable, GLFW_FALSE) - let window = glfwCreateWindow(WIN_WIDTH, WIN_HEIGHT, "Simple Mandelbrot fractal") + let window = glfwCreateWindow(WIN_WIDTH, WIN_HEIGHT, "Mandelbrot fractal") assert window != nil discard window.setKeyCallback(keyProc) @@ -116,10 +145,25 @@ proc main() = glClearColor(0.2, 0.2, 0.2, 0.5) glUseProgram(GLData.program) glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT) + + zoom *= zf + if zf < 0.0: zf = 0.0 + center_y += dy * zoom + if center_y > 1.0f: center_y = 1.0f + if center_y < -1.0f: center_y = -1.0f + center_x += dx * zoom + if center_x > 1.0f: center_x = 1.0f + if center_x < -1.0f: center_x = -1.0f + + set_float("zoom", zoom) + set_float("center_x", center_x) + set_float("center_y", center_y) + glBindVertexArray(mesh.vao) glDrawElements(GL_TRIANGLES, indices.len.cint, GL_UNSIGNED_INT, nil) window.swapBuffers() glfwPollEvents() + window.destroyWindow() glDeleteShader(GLData.vertexShader) diff --git a/src/mandelbrot/shader.frag b/src/mandelbrot/shader.frag index 2d1d03e..f74017a 100644 --- a/src/mandelbrot/shader.frag +++ b/src/mandelbrot/shader.frag @@ -1,35 +1,301 @@ #version 410 core in vec4 gl_FragCoord; -out vec4 frag_color; +out vec4 fragColor; +//out float gl_FragDepth; -#define MAX_ITERATIONS 500 +uniform float center_x; +uniform float center_y; +uniform float zoom; +#define MAX_ITERATIONS 600 + +const vec3 colors[256] = vec3[256]( +vec3(0.0,0.0,0.0), +vec3(128.0,0.0,0.0), +vec3(0.0,128.0,0.0), +vec3(128.0,128.0,0.0), +vec3(0.0,0.0,128.0), +vec3(128.0,0.0,128.0), +vec3(0.0,128.0,128.0), +vec3(192.0,192.0,192.0), +vec3(128.0,128.0,128.0), +vec3(255.0,0.0,0.0), +vec3(0.0,255.0,0.0), +vec3(255.0,255.0,0.0), +vec3(0.0,0.0,255.0), +vec3(255.0,0.0,255.0), +vec3(0.0,255.0,255.0), +vec3(255.0,255.0,255.0), +vec3(0.0,0.0,0.0), +vec3(0.0,0.0,95.0), +vec3(0.0,0.0,135.0), +vec3(0.0,0.0,175.0), +vec3(0.0,0.0,215.0), +vec3(0.0,0.0,255.0), +vec3(0.0,95.0,0.0), +vec3(0.0,95.0,95.0), +vec3(0.0,95.0,135.0), +vec3(0.0,95.0,175.0), +vec3(0.0,95.0,215.0), +vec3(0.0,95.0,255.0), +vec3(0.0,135.0,0.0), +vec3(0.0,135.0,95.0), +vec3(0.0,135.0,135.0), +vec3(0.0,135.0,175.0), +vec3(0.0,135.0,215.0), +vec3(0.0,135.0,255.0), +vec3(0.0,175.0,0.0), +vec3(0.0,175.0,95.0), +vec3(0.0,175.0,135.0), +vec3(0.0,175.0,175.0), +vec3(0.0,175.0,215.0), +vec3(0.0,175.0,255.0), +vec3(0.0,215.0,0.0), +vec3(0.0,215.0,95.0), +vec3(0.0,215.0,135.0), +vec3(0.0,215.0,175.0), +vec3(0.0,215.0,215.0), +vec3(0.0,215.0,255.0), +vec3(0.0,255.0,0.0), +vec3(0.0,255.0,95.0), +vec3(0.0,255.0,135.0), +vec3(0.0,255.0,175.0), +vec3(0.0,255.0,215.0), +vec3(0.0,255.0,255.0), +vec3(95.0,0.0,0.0), +vec3(95.0,0.0,95.0), +vec3(95.0,0.0,135.0), +vec3(95.0,0.0,175.0), +vec3(95.0,0.0,215.0), +vec3(95.0,0.0,255.0), +vec3(95.0,95.0,0.0), +vec3(95.0,95.0,95.0), +vec3(95.0,95.0,135.0), +vec3(95.0,95.0,175.0), +vec3(95.0,95.0,215.0), +vec3(95.0,95.0,255.0), +vec3(95.0,135.0,0.0), +vec3(95.0,135.0,95.0), +vec3(95.0,135.0,135.0), +vec3(95.0,135.0,175.0), +vec3(95.0,135.0,215.0), +vec3(95.0,135.0,255.0), +vec3(95.0,175.0,0.0), +vec3(95.0,175.0,95.0), +vec3(95.0,175.0,135.0), +vec3(95.0,175.0,175.0), +vec3(95.0,175.0,215.0), +vec3(95.0,175.0,255.0), +vec3(95.0,215.0,0.0), +vec3(95.0,215.0,95.0), +vec3(95.0,215.0,135.0), +vec3(95.0,215.0,175.0), +vec3(95.0,215.0,215.0), +vec3(95.0,215.0,255.0), +vec3(95.0,255.0,0.0), +vec3(95.0,255.0,95.0), +vec3(95.0,255.0,135.0), +vec3(95.0,255.0,175.0), +vec3(95.0,255.0,215.0), +vec3(95.0,255.0,255.0), +vec3(135.0,0.0,0.0), +vec3(135.0,0.0,95.0), +vec3(135.0,0.0,135.0), +vec3(135.0,0.0,175.0), +vec3(135.0,0.0,215.0), +vec3(135.0,0.0,255.0), +vec3(135.0,95.0,0.0), +vec3(135.0,95.0,95.0), +vec3(135.0,95.0,135.0), +vec3(135.0,95.0,175.0), +vec3(135.0,95.0,215.0), +vec3(135.0,95.0,255.0), +vec3(135.0,135.0,0.0), +vec3(135.0,135.0,95.0), +vec3(135.0,135.0,135.0), +vec3(135.0,135.0,175.0), +vec3(135.0,135.0,215.0), +vec3(135.0,135.0,255.0), +vec3(135.0,175.0,0.0), +vec3(135.0,175.0,95.0), +vec3(135.0,175.0,135.0), +vec3(135.0,175.0,175.0), +vec3(135.0,175.0,215.0), +vec3(135.0,175.0,255.0), +vec3(135.0,215.0,0.0), +vec3(135.0,215.0,95.0), +vec3(135.0,215.0,135.0), +vec3(135.0,215.0,175.0), +vec3(135.0,215.0,215.0), +vec3(135.0,215.0,255.0), +vec3(135.0,255.0,0.0), +vec3(135.0,255.0,95.0), +vec3(135.0,255.0,135.0), +vec3(135.0,255.0,175.0), +vec3(135.0,255.0,215.0), +vec3(135.0,255.0,255.0), +vec3(175.0,0.0,0.0), +vec3(175.0,0.0,95.0), +vec3(175.0,0.0,135.0), +vec3(175.0,0.0,175.0), +vec3(175.0,0.0,215.0), +vec3(175.0,0.0,255.0), +vec3(175.0,95.0,0.0), +vec3(175.0,95.0,95.0), +vec3(175.0,95.0,135.0), +vec3(175.0,95.0,175.0), +vec3(175.0,95.0,215.0), +vec3(175.0,95.0,255.0), +vec3(175.0,135.0,0.0), +vec3(175.0,135.0,95.0), +vec3(175.0,135.0,135.0), +vec3(175.0,135.0,175.0), +vec3(175.0,135.0,215.0), +vec3(175.0,135.0,255.0), +vec3(175.0,175.0,0.0), +vec3(175.0,175.0,95.0), +vec3(175.0,175.0,135.0), +vec3(175.0,175.0,175.0), +vec3(175.0,175.0,215.0), +vec3(175.0,175.0,255.0), +vec3(175.0,215.0,0.0), +vec3(175.0,215.0,95.0), +vec3(175.0,215.0,135.0), +vec3(175.0,215.0,175.0), +vec3(175.0,215.0,215.0), +vec3(175.0,215.0,255.0), +vec3(175.0,255.0,0.0), +vec3(175.0,255.0,95.0), +vec3(175.0,255.0,135.0), +vec3(175.0,255.0,175.0), +vec3(175.0,255.0,215.0), +vec3(175.0,255.0,255.0), +vec3(215.0,0.0,0.0), +vec3(215.0,0.0,95.0), +vec3(215.0,0.0,135.0), +vec3(215.0,0.0,175.0), +vec3(215.0,0.0,215.0), +vec3(215.0,0.0,255.0), +vec3(215.0,95.0,0.0), +vec3(215.0,95.0,95.0), +vec3(215.0,95.0,135.0), +vec3(215.0,95.0,175.0), +vec3(215.0,95.0,215.0), +vec3(215.0,95.0,255.0), +vec3(215.0,135.0,0.0), +vec3(215.0,135.0,95.0), +vec3(215.0,135.0,135.0), +vec3(215.0,135.0,175.0), +vec3(215.0,135.0,215.0), +vec3(215.0,135.0,255.0), +vec3(215.0,175.0,0.0), +vec3(215.0,175.0,95.0), +vec3(215.0,175.0,135.0), +vec3(215.0,175.0,175.0), +vec3(215.0,175.0,215.0), +vec3(215.0,175.0,255.0), +vec3(215.0,215.0,0.0), +vec3(215.0,215.0,95.0), +vec3(215.0,215.0,135.0), +vec3(215.0,215.0,175.0), +vec3(215.0,215.0,215.0), +vec3(215.0,215.0,255.0), +vec3(215.0,255.0,0.0), +vec3(215.0,255.0,95.0), +vec3(215.0,255.0,135.0), +vec3(215.0,255.0,175.0), +vec3(215.0,255.0,215.0), +vec3(215.0,255.0,255.0), +vec3(255.0,0.0,0.0), +vec3(255.0,0.0,95.0), +vec3(255.0,0.0,135.0), +vec3(255.0,0.0,175.0), +vec3(255.0,0.0,215.0), +vec3(255.0,0.0,255.0), +vec3(255.0,95.0,0.0), +vec3(255.0,95.0,95.0), +vec3(255.0,95.0,135.0), +vec3(255.0,95.0,175.0), +vec3(255.0,95.0,215.0), +vec3(255.0,95.0,255.0), +vec3(255.0,135.0,0.0), +vec3(255.0,135.0,95.0), +vec3(255.0,135.0,135.0), +vec3(255.0,135.0,175.0), +vec3(255.0,135.0,215.0), +vec3(255.0,135.0,255.0), +vec3(255.0,175.0,0.0), +vec3(255.0,175.0,95.0), +vec3(255.0,175.0,135.0), +vec3(255.0,175.0,175.0), +vec3(255.0,175.0,215.0), +vec3(255.0,175.0,255.0), +vec3(255.0,215.0,0.0), +vec3(255.0,215.0,95.0), +vec3(255.0,215.0,135.0), +vec3(255.0,215.0,175.0), +vec3(255.0,215.0,215.0), +vec3(255.0,215.0,255.0), +vec3(255.0,255.0,0.0), +vec3(255.0,255.0,95.0), +vec3(255.0,255.0,135.0), +vec3(255.0,255.0,175.0), +vec3(255.0,255.0,215.0), +vec3(255.0,255.0,255.0), +vec3(8.0,8.0,8.0), +vec3(18.0,18.0,18.0), +vec3(28.0,28.0,28.0), +vec3(38.0,38.0,38.0), +vec3(48.0,48.0,48.0), +vec3(58.0,58.0,58.0), +vec3(68.0,68.0,68.0), +vec3(78.0,78.0,78.0), +vec3(88.0,88.0,88.0), +vec3(98.0,98.0,98.0), +vec3(108.0,108.0,108.0), +vec3(118.0,118.0,118.0), +vec3(128.0,128.0,128.0), +vec3(138.0,138.0,138.0), +vec3(148.0,148.0,148.0), +vec3(158.0,158.0,158.0), +vec3(168.0,168.0,168.0), +vec3(178.0,178.0,178.0), +vec3(188.0,188.0,188.0), +vec3(198.0,198.0,198.0), +vec3(208.0,208.0,208.0), +vec3(218.0,218.0,218.0), +vec3(228.0,228.0,228.0), +vec3(238.0,238.0,238.0) +); + int get_iterations() { - float real = (gl_FragCoord.x / 1080.0 - 1.2) * 1.5; - float imag = (gl_FragCoord.y / 1080.0 - 0.7) * 1.5 ; + double real = ((gl_FragCoord.x / 1000.0f - 1.2f) * zoom + center_x) * 1.5f; + double imag = ((gl_FragCoord.y / 800.0f - 0.7f) * zoom + center_y) * 1.5f; + int iterations = 0; - float const_real = real; - float const_imag = imag; + double const_real = real; + double const_imag = imag; while (iterations < MAX_ITERATIONS) { - float tmp_real = real; + double tmp_real = real; real = (real * real - imag * imag) + const_real; imag = (2.0 * tmp_real * imag) + const_imag; - float dist = real * real + imag * imag; - + double dist = real * real + imag * imag; + if (dist > 4.0) - break; + break; ++iterations; } return iterations; } - + + vec4 return_color() { int iter = get_iterations(); @@ -38,12 +304,14 @@ vec4 return_color() gl_FragDepth = 0.0f; return vec4(0.0f, 0.0f, 0.0f, 1.0f); } - - float iterations = float(iter) / MAX_ITERATIONS; - return vec4(0.0f, iterations, 0.0f, 1.0f); + int colorIndex = int((float(iter)/float(MAX_ITERATIONS))*256); + vec3 color = colors[colorIndex]; + return vec4(color.x/256, color.y/256, color.z/256, 1.0); + } void main() { - frag_color = return_color(); -} \ No newline at end of file + fragColor = return_color(); +} +