first version
This commit is contained in:
commit
3cca69183e
4 changed files with 201 additions and 0 deletions
12
mandelbrot.nimble
Normal file
12
mandelbrot.nimble
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Package
|
||||||
|
|
||||||
|
version = "0.1.0"
|
||||||
|
author = "Sander Hautvast"
|
||||||
|
description = "A new awesome nimble package"
|
||||||
|
license = "MIT"
|
||||||
|
srcDir = "src"
|
||||||
|
bin = @["mandelbrot/mandelbrot"]
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
|
||||||
|
requires "nim >= 1.4.0", "nimgl >= 1.1.5"
|
||||||
133
src/mandelbrot/mandelbrot.nim
Normal file
133
src/mandelbrot/mandelbrot.nim
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
import nimgl/[glfw, opengl]
|
||||||
|
|
||||||
|
var GLData: tuple[program, vertexShader, fragmentShader: uint32]
|
||||||
|
const
|
||||||
|
WIN_WIDTH = 1000
|
||||||
|
WIN_HEIGHT = 800
|
||||||
|
|
||||||
|
|
||||||
|
proc keyProc(window: GLFWWindow, key: int32, scancode: int32, action: int32, mods: int32): void {.cdecl.} =
|
||||||
|
if key == GLFWKey.ESCAPE and action == GLFWPress:
|
||||||
|
window.setWindowShouldClose(true)
|
||||||
|
|
||||||
|
|
||||||
|
proc logShaderCompilationFailure(shader: uint32, shader_path:string) =
|
||||||
|
var logSize: int32
|
||||||
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, logSize.addr)
|
||||||
|
|
||||||
|
var logStr = cast[ptr GLchar](alloc(logSize))
|
||||||
|
|
||||||
|
glGetShaderInfoLog(shader, logSize, nil, logStr)
|
||||||
|
echo "Error compiling shader: ", logStr
|
||||||
|
echo "Shader location: ", shader_path
|
||||||
|
# Cleanup
|
||||||
|
dealloc(logStr)
|
||||||
|
quit(-1)
|
||||||
|
|
||||||
|
proc logProgramLinkingError() =
|
||||||
|
var logSize: int32
|
||||||
|
glGetProgramiv(GLData.program, GL_INFO_LOG_LENGTH, logSize.addr)
|
||||||
|
|
||||||
|
var logStr = cast[ptr GLchar](alloc(logSize))
|
||||||
|
glGetProgramInfoLog(GLData.program, logSize, nil, logStr)
|
||||||
|
echo "Error linking shader program: ", logStr
|
||||||
|
# Cleanup
|
||||||
|
dealloc(logStr)
|
||||||
|
quit(-1)
|
||||||
|
|
||||||
|
proc addShader(shader_path: string, shader_type: GLenum):uint32 =
|
||||||
|
let
|
||||||
|
shadercode = readFile(shader_path)
|
||||||
|
shader = glCreateShader(shader_type)
|
||||||
|
var shadercodeCString = cstring(shadercode)
|
||||||
|
glShaderSource(shader, 1, addr shadercodeCString, nil)
|
||||||
|
glCompileShader(shader)
|
||||||
|
|
||||||
|
var success: int32
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, success.addr)
|
||||||
|
if success == 0: logShaderCompilationFailure(shader, shader_path)
|
||||||
|
glAttachShader(GLData.program, shader)
|
||||||
|
return shader
|
||||||
|
|
||||||
|
|
||||||
|
proc initShaders(vertex_shader_path: string, fragment_shader_path: string) =
|
||||||
|
GLData.program = glCreateProgram()
|
||||||
|
GLData.vertexShader = addShader(vertex_shader_path, GL_VERTEX_SHADER)
|
||||||
|
GLData.fragmentShader = addShader(fragment_shader_path, GL_FRAGMENT_SHADER)
|
||||||
|
|
||||||
|
glLinkProgram(GLData.program)
|
||||||
|
var success: int32
|
||||||
|
glGetProgramiv(GLData.program, GL_LINK_STATUS, success.addr)
|
||||||
|
if success == 0: logProgramLinkingError()
|
||||||
|
|
||||||
|
|
||||||
|
proc main() =
|
||||||
|
assert glfwInit()
|
||||||
|
|
||||||
|
glfwWindowHint(GLFWContextVersionMajor, 4)
|
||||||
|
glfwWindowHint(GLFWContextVersionMinor, 1)
|
||||||
|
glfwWindowHint(GLFWOpenglForwardCompat, GLFW_TRUE) # Used for Mac
|
||||||
|
glfwWindowHint(GLFWOpenglProfile, GLFW_OPENGL_CORE_PROFILE)
|
||||||
|
glfwWindowHint(GLFWResizable, GLFW_FALSE)
|
||||||
|
|
||||||
|
let window = glfwCreateWindow(WIN_WIDTH, WIN_HEIGHT, "Simple Mandelbrot fractal")
|
||||||
|
assert window != nil
|
||||||
|
|
||||||
|
discard window.setKeyCallback(keyProc)
|
||||||
|
window.makeContextCurrent()
|
||||||
|
|
||||||
|
assert glInit()
|
||||||
|
|
||||||
|
var vertices = @[
|
||||||
|
-1.0f, -1.0f, -0.0f,
|
||||||
|
1.0f, 1.0f, -0.0f,
|
||||||
|
-1.0f, 1.0f, -0.0f,
|
||||||
|
1.0f, -1.0f, -0.0]
|
||||||
|
|
||||||
|
var indices = @[
|
||||||
|
0'u32, 1'u32, 2'u32,
|
||||||
|
0'u32, 3'u32, 1'u32]
|
||||||
|
# 2---,1
|
||||||
|
# | .' |
|
||||||
|
# 0'---3
|
||||||
|
|
||||||
|
var mesh: tuple[vao,vbo,ebo: uint32]
|
||||||
|
|
||||||
|
glGenVertexArrays(1, mesh.vao.addr)
|
||||||
|
glGenBuffers(1, mesh.vbo.addr)
|
||||||
|
glGenBuffers(1, mesh.ebo.addr)
|
||||||
|
glBindVertexArray(mesh.vao)
|
||||||
|
|
||||||
|
# bind vertices
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo)
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, cint(cfloat.sizeof*vertices.len), vertices[0].addr, GL_STATIC_DRAW)
|
||||||
|
|
||||||
|
# bind indices = elements
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ebo)
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, cint(cuint.sizeof*indices.len), indices[0].addr, GL_STATIC_DRAW)
|
||||||
|
|
||||||
|
glVertexAttribPointer(0'u32, 3, EGL_FLOAT, false, 3 * cfloat.sizeof, nil)
|
||||||
|
glEnableVertexAttribArray(0)
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
|
glBindVertexArray(mesh.vao)
|
||||||
|
initShaders("src/mandelbrot/shader.vert", "src/mandelbrot/shader.frag")
|
||||||
|
|
||||||
|
while not window.windowShouldClose:
|
||||||
|
glClearColor(0.2, 0.2, 0.2, 0.5)
|
||||||
|
glUseProgram(GLData.program)
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
|
||||||
|
glBindVertexArray(mesh.vao)
|
||||||
|
glDrawElements(GL_TRIANGLES, indices.len.cint, GL_UNSIGNED_INT, nil)
|
||||||
|
window.swapBuffers()
|
||||||
|
glfwPollEvents()
|
||||||
|
|
||||||
|
window.destroyWindow()
|
||||||
|
glDeleteShader(GLData.vertexShader)
|
||||||
|
glDeleteShader(GLData.fragmentShader)
|
||||||
|
glDeleteVertexArrays(1, mesh.vao.addr)
|
||||||
|
glDeleteBuffers(1, mesh.vbo.addr)
|
||||||
|
glDeleteBuffers(1, mesh.ebo.addr)
|
||||||
|
glfwTerminate()
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
||||||
49
src/mandelbrot/shader.frag
Normal file
49
src/mandelbrot/shader.frag
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
#version 410 core
|
||||||
|
in vec4 gl_FragCoord;
|
||||||
|
|
||||||
|
out vec4 frag_color;
|
||||||
|
|
||||||
|
#define MAX_ITERATIONS 500
|
||||||
|
|
||||||
|
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 ;
|
||||||
|
|
||||||
|
int iterations = 0;
|
||||||
|
float const_real = real;
|
||||||
|
float const_imag = imag;
|
||||||
|
|
||||||
|
while (iterations < MAX_ITERATIONS)
|
||||||
|
{
|
||||||
|
float tmp_real = real;
|
||||||
|
real = (real * real - imag * imag) + const_real;
|
||||||
|
imag = (2.0 * tmp_real * imag) + const_imag;
|
||||||
|
|
||||||
|
float dist = real * real + imag * imag;
|
||||||
|
|
||||||
|
if (dist > 4.0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
++iterations;
|
||||||
|
}
|
||||||
|
return iterations;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 return_color()
|
||||||
|
{
|
||||||
|
int iter = get_iterations();
|
||||||
|
if (iter == MAX_ITERATIONS)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
frag_color = return_color();
|
||||||
|
}
|
||||||
7
src/mandelbrot/shader.vert
Normal file
7
src/mandelbrot/shader.vert
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#version 410 core
|
||||||
|
layout (location = 0) in vec3 pos;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(pos.xyz, 1.0);
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue