Parameterise some bits for cool animations and make fullscreen
This commit is contained in:
parent
8b90943479
commit
e5a730a32d
2
build.sh
2
build.sh
@ -2,4 +2,4 @@
|
|||||||
set -e
|
set -e
|
||||||
glslc -fshader-stage=vert vert_shader.glsl -o vert_shader.spv
|
glslc -fshader-stage=vert vert_shader.glsl -o vert_shader.spv
|
||||||
glslc -fshader-stage=frag frag_shader.glsl -o frag_shader.spv
|
glslc -fshader-stage=frag frag_shader.glsl -o frag_shader.spv
|
||||||
clang -std=c11 -pedantic -Wall -Wextra -lglfw -lvulkan main.c -o gpu-fractal
|
clang -std=c11 -pedantic -Wall -Wextra -lglfw -lm -lvulkan main.c -o gpu-fractal
|
||||||
|
24
config.h
Normal file
24
config.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Camden Dixie O'Brien
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAXITER 1000
|
||||||
|
#define SS 9
|
||||||
|
|
||||||
|
//#define JULIA
|
||||||
|
//#define JULIA_C_RE 0.285
|
||||||
|
//#define JULIA_C_IM 0.010
|
||||||
|
|
||||||
|
#define JULIA
|
||||||
|
#define JULIA_C_RE 0.300
|
||||||
|
#define JULIA_DTHETA 0.00001
|
||||||
|
#define ZOOMRATE 0.0004
|
||||||
|
|
||||||
|
//#define CENTRE_RE -0.743643887
|
||||||
|
//#define CENTRE_IM 0.131825904
|
||||||
|
//#define ZOOMRATE 0.001
|
||||||
|
|
||||||
|
//#define CENTRE_RE -0.900000000
|
||||||
|
//#define POWRATE 0.0001
|
||||||
|
//#define ZOOMRATE 0.0001
|
@ -5,49 +5,110 @@
|
|||||||
|
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
#define MAXITER 1000
|
#include "config.h"
|
||||||
|
|
||||||
|
#define NCOLS 8
|
||||||
|
|
||||||
layout(location = 0) out vec4 out_colour;
|
layout(location = 0) out vec4 out_colour;
|
||||||
|
|
||||||
layout(push_constant) uniform Constants {
|
layout(push_constant) uniform Constants {
|
||||||
vec2 img_size;
|
vec2 img_size;
|
||||||
vec2 shift;
|
#ifdef JULIA
|
||||||
float zoom;
|
vec2 julia;
|
||||||
|
#endif
|
||||||
|
vec2 centre;
|
||||||
|
float scale;
|
||||||
|
#ifdef POWRATE
|
||||||
|
float zpow;
|
||||||
|
#endif
|
||||||
} params;
|
} params;
|
||||||
|
|
||||||
vec2 ss_offsets[4] = vec2[](
|
vec3 incol = vec3(0.000000, 0.014444, 0.027321);
|
||||||
|
|
||||||
|
vec3 palette[NCOLS] = vec3[](
|
||||||
|
vec3(0.000000, 0.049707, 0.107023),
|
||||||
|
vec3(0.025187, 0.064803, 0.177888),
|
||||||
|
vec3(0.254152, 0.080220, 0.274677),
|
||||||
|
vec3(0.502886, 0.080220, 0.278894),
|
||||||
|
vec3(1.000000, 0.124772, 0.119538),
|
||||||
|
vec3(1.000000, 0.234551, 0.030713),
|
||||||
|
vec3(1.000000, 0.381326, 0.000000),
|
||||||
|
vec3(1.000000, 0.651406, 0.215861)
|
||||||
|
);
|
||||||
|
|
||||||
|
#if SS == 4
|
||||||
|
vec2 ss_offsets[SS] = vec2[](
|
||||||
vec2(-0.25, -0.25),
|
vec2(-0.25, -0.25),
|
||||||
vec2( 0.25, -0.25),
|
vec2( 0.25, -0.25),
|
||||||
vec2(-0.25, 0.25),
|
vec2(-0.25, 0.25),
|
||||||
vec2( 0.25, 0.25)
|
vec2( 0.25, 0.25)
|
||||||
);
|
);
|
||||||
|
#elif SS == 9
|
||||||
|
vec2 ss_offsets[SS] = vec2[](
|
||||||
|
vec2(-0.33, -0.33), vec2(0.0, -0.33), vec2(0.33, -0.33),
|
||||||
|
vec2(-0.33, 0.0), vec2(0.0, 0.0), vec2(0.33, 0.0),
|
||||||
|
vec2(-0.33, 0.33), vec2(0.0, 0.33), vec2(0.33, 0.33)
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
#error "Unsupported supersampling count"
|
||||||
|
#endif
|
||||||
|
|
||||||
vec2 maptoz(vec2 xy)
|
vec2 maptoz(vec2 xy)
|
||||||
{
|
{
|
||||||
return params.zoom * ((xy / params.img_size.xy) * 4.0 - 2.0) + params.shift;
|
float aspect = params.img_size.x / params.img_size.y;
|
||||||
|
vec2 z = 4.0 * (xy / params.img_size.xy - 0.5);
|
||||||
|
z.x *= aspect;
|
||||||
|
return params.scale * z + params.centre;
|
||||||
}
|
}
|
||||||
|
|
||||||
float mandelbrot(vec2 c) {
|
vec2 zpow(vec2 z, float p) {
|
||||||
|
float r = length(z);
|
||||||
|
float theta = atan(z.y, z.x);
|
||||||
|
float mag = pow(r, p);
|
||||||
|
float phi = p * theta;
|
||||||
|
return mag * vec2(cos(phi), sin(phi));
|
||||||
|
}
|
||||||
|
|
||||||
|
int fractal(vec2 c) {
|
||||||
|
#ifdef JULIA
|
||||||
|
vec2 z = c;
|
||||||
|
c = params.julia;
|
||||||
|
#else
|
||||||
vec2 z = vec2(0.0, 0.0);
|
vec2 z = vec2(0.0, 0.0);
|
||||||
|
#endif
|
||||||
for (int i = 0; i < MAXITER; ++i) {
|
for (int i = 0; i < MAXITER; ++i) {
|
||||||
|
#ifdef POWRATE
|
||||||
|
z = zpow(z, params.zpow) + c;
|
||||||
|
#else
|
||||||
z = vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y) + c;
|
z = vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y) + c;
|
||||||
|
#endif
|
||||||
if (length(z) > 2.0)
|
if (length(z) > 2.0)
|
||||||
return float(i) / float(MAXITER);
|
return i;
|
||||||
}
|
}
|
||||||
return 0.0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 colour(float i) {
|
vec3 colour(int i) {
|
||||||
return vec3(i, i * i, i * i * i);
|
if (i == -1) {
|
||||||
|
return incol;
|
||||||
|
} else {
|
||||||
|
float c = float(NCOLS) * sqrt(float(i) / float(MAXITER));
|
||||||
|
int fc = int(floor(c));
|
||||||
|
int cc = int(ceil(c));
|
||||||
|
float p = c - float(fc);
|
||||||
|
p = smoothstep(0.0, 1.0, p);
|
||||||
|
return mix(palette[fc], palette[cc], p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec2 c;
|
vec2 c;
|
||||||
vec3 col = vec3(0.0, 0.0, 0.0);
|
vec3 col = vec3(0.0, 0.0, 0.0);
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < SS; ++i) {
|
||||||
c = maptoz(gl_FragCoord.xy + ss_offsets[i]);
|
c = maptoz(gl_FragCoord.xy + ss_offsets[i]);
|
||||||
col += colour(mandelbrot(c));
|
col += colour(fractal(c));
|
||||||
}
|
}
|
||||||
|
col /= SS;
|
||||||
out_colour = vec4(col, 1.0);
|
out_colour = vec4(col, 1.0);
|
||||||
}
|
}
|
||||||
|
78
main.c
78
main.c
@ -5,8 +5,11 @@
|
|||||||
|
|
||||||
#define GLFW_INCLUDE_VULKAN
|
#define GLFW_INCLUDE_VULKAN
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <complex.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -21,14 +24,22 @@
|
|||||||
#define PRESENT_MODE_BUFFER_SIZE 8
|
#define PRESENT_MODE_BUFFER_SIZE 8
|
||||||
#define SWAPCHAIN_IMG_BUFFER_SIZE 4
|
#define SWAPCHAIN_IMG_BUFFER_SIZE 4
|
||||||
|
|
||||||
#define MAX_SHADER_SIZE (4 * 1024)
|
#define MAX_SHADER_SIZE (8 * 1024)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float width, height;
|
float width, height;
|
||||||
|
#ifdef JULIA
|
||||||
struct {
|
struct {
|
||||||
float x, y;
|
float re, im;
|
||||||
} shift;
|
} julia;
|
||||||
float zoom;
|
#endif
|
||||||
|
struct {
|
||||||
|
float re, im;
|
||||||
|
} centre;
|
||||||
|
float scale;
|
||||||
|
#ifdef POWRATE
|
||||||
|
float zpow;
|
||||||
|
#endif
|
||||||
} params_t;
|
} params_t;
|
||||||
|
|
||||||
static const char *layers[] = { "VK_LAYER_KHRONOS_validation" };
|
static const char *layers[] = { "VK_LAYER_KHRONOS_validation" };
|
||||||
@ -62,14 +73,18 @@ int main(void)
|
|||||||
glfwInit();
|
glfwInit();
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||||
GLFWwindow *window
|
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
||||||
= glfwCreateWindow(900, 900, "GPU Fractal", NULL, NULL);
|
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
||||||
|
GLFWwindow *window = glfwCreateWindow(
|
||||||
|
mode->width, mode->height, "GPU Fractal", monitor, NULL);
|
||||||
|
/* GLFWwindow *window */
|
||||||
|
/* = glfwCreateWindow(900, 900, "GPU Fractal", NULL, NULL); */
|
||||||
assert(window);
|
assert(window);
|
||||||
|
|
||||||
// Initialise Vulkan instance.
|
// Initialise Vulkan instance.
|
||||||
const VkApplicationInfo app_info = {
|
const VkApplicationInfo app_info = {
|
||||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||||
.pApplicationName = "Vulkan Test",
|
.pApplicationName = "GPU Fractal",
|
||||||
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||||
.pEngineName = "No Engine",
|
.pEngineName = "No Engine",
|
||||||
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||||
@ -461,16 +476,41 @@ int main(void)
|
|||||||
result = vkCreateFence(dev, &fence_config, NULL, &in_flight);
|
result = vkCreateFence(dev, &fence_config, NULL, &in_flight);
|
||||||
assert(result == VK_SUCCESS);
|
assert(result == VK_SUCCESS);
|
||||||
|
|
||||||
|
// Prepare parameters
|
||||||
params_t params = {
|
params_t params = {
|
||||||
.width = (float)swapchain_extent.width,
|
.width = (float)swapchain_extent.width,
|
||||||
.height = (float)swapchain_extent.height,
|
.height = (float)swapchain_extent.height,
|
||||||
.shift = {
|
#ifdef JULIA
|
||||||
.x = -0.743643887037158704752191506114774,
|
.julia = {
|
||||||
.y = 0.131825904205311970493132056385139,
|
#ifdef JULIA_C_RE
|
||||||
|
.re = JULIA_C_RE,
|
||||||
|
#endif
|
||||||
|
#ifdef JULIA_C_IM
|
||||||
|
.im = JULIA_C_IM,
|
||||||
|
#endif
|
||||||
},
|
},
|
||||||
.zoom = 1.0,
|
#endif
|
||||||
|
#if defined(CENTRE_RE) || defined(CENTRE_IM)
|
||||||
|
.centre = {
|
||||||
|
#ifdef CENTRE_RE
|
||||||
|
.re = CENTRE_RE,
|
||||||
|
#endif
|
||||||
|
#ifdef CENTRE_IM
|
||||||
|
.im = CENTRE_IM,
|
||||||
|
#endif
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
.scale = 1.0,
|
||||||
|
#ifdef POWRATE
|
||||||
|
.zpow = 2.0,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef JULIA_DTHETA
|
||||||
|
const double dtheta = JULIA_DTHETA;
|
||||||
|
const double complex rotz = cexp(I * dtheta);
|
||||||
|
#endif
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window)) {
|
while (!glfwWindowShouldClose(window)) {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
@ -548,8 +588,20 @@ int main(void)
|
|||||||
result = vkQueuePresentKHR(queue, &present_info);
|
result = vkQueuePresentKHR(queue, &present_info);
|
||||||
assert(result == VK_SUCCESS);
|
assert(result == VK_SUCCESS);
|
||||||
|
|
||||||
// Increment zoom
|
#ifdef JULIA_DTHETA
|
||||||
params.zoom *= 0.99;
|
double complex julia = params.julia.re + I * params.julia.im;
|
||||||
|
julia *= rotz;
|
||||||
|
params.julia.re = (float)creal(julia);
|
||||||
|
params.julia.im = (float)cimag(julia);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ZOOMRATE
|
||||||
|
params.scale *= (1 - ZOOMRATE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef POWRATE
|
||||||
|
params.zpow += POWRATE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
vkDeviceWaitIdle(dev);
|
vkDeviceWaitIdle(dev);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user