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