fractorb
changeset 3:f440ecffc45a tip
trying to draw the orbit in the shader
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 26 Nov 2017 14:49:34 +0200 |
parents | 03e8b9a5031d |
children | |
files | mbrot.glsl src/main.c |
diffstat | 2 files changed, 115 insertions(+), 11 deletions(-) [+] |
line diff
1.1 --- a/mbrot.glsl Mon Nov 20 03:53:02 2017 +0200 1.2 +++ b/mbrot.glsl Sun Nov 26 14:49:34 2017 +0200 1.3 @@ -1,5 +1,5 @@ 1.4 // vi:ft=glsl: 1.5 -#define ITER 96 1.6 +#define ITER 128 1.7 1.8 uniform float view_scale; 1.9 uniform vec2 view_center; 1.10 @@ -7,6 +7,7 @@ 1.11 1.12 float mbrot_dist_point(in vec2 c, in vec2 p) 1.13 { 1.14 + vec2 pixpos = c; 1.15 vec2 z = c; 1.16 float mindist_sq = 8192.0; 1.17 1.18 @@ -15,18 +16,59 @@ 1.19 float y = (z.x * z.y + z.x * z.y) + c.y; 1.20 1.21 z = vec2(x, y); 1.22 - vec2 dir = z - seed; 1.23 + vec2 dir = z - p; 1.24 mindist_sq = min(mindist_sq, dot(dir, dir)); 1.25 } 1.26 1.27 - return sqrt(mindist_sq); 1.28 + return mindist_sq; 1.29 +} 1.30 + 1.31 +float line_dist_sq(in vec2 a, in vec2 b, in vec2 p) 1.32 +{ 1.33 + vec2 dir = b - a; 1.34 + vec2 pvec = p - a; 1.35 + float t = dot(dir, pvec); 1.36 + 1.37 + if(t < 0.0) return dot(pvec, pvec); 1.38 + if(t > 1.0) return dot(p - b, p - b); 1.39 + 1.40 + vec2 ppt = a + dir * t; 1.41 + vec2 lpvec = p - ppt; 1.42 + return dot(lpvec, lpvec); 1.43 +} 1.44 + 1.45 +float mbrot_orbit_dist(in vec2 c, in vec2 p) 1.46 +{ 1.47 + vec2 pixpos = c; 1.48 + vec2 z = c; 1.49 + float mindist_sq = 8192.0; 1.50 + 1.51 + for(int i=0; i<ITER; i++) { 1.52 + float x = (z.x * z.x - z.y * z.y) + c.x; 1.53 + float y = (z.x * z.y + z.x * z.y) + c.y; 1.54 + vec2 next = vec2(x, y); 1.55 + 1.56 + float dist_sq = line_dist_sq(z, next, p); 1.57 + mindist_sq = min(mindist_sq, dist_sq); 1.58 + 1.59 + z = next; 1.60 + } 1.61 + 1.62 + return mindist_sq; 1.63 } 1.64 1.65 void main() 1.66 { 1.67 vec2 c = gl_TexCoord[0].xy; 1.68 - float m = 1.0 - mbrot_dist_point(c, vec2(0.0, 0.0)); 1.69 + float pdist_sq; 1.70 + float m = 1.0 - min(sqrt(mbrot_dist_point(c, seed)), 1.0); 1.71 1.72 +#ifdef PLOT_ORBIT 1.73 + float orb_dist = sqrt(mbrot_orbit_dist(seed, c)); 1.74 + vec3 orbcol = vec3(0.001 / orb_dist, 0.0, 0.0); 1.75 + gl_FragColor.rgb = vec3(m, m, m) / 2.0 + orbcol; 1.76 +#else 1.77 gl_FragColor.rgb = vec3(m, m, m); 1.78 +#endif 1.79 gl_FragColor.a = 1.0; 1.80 }
2.1 --- a/src/main.c Mon Nov 20 03:53:02 2017 +0200 2.2 +++ b/src/main.c Sun Nov 26 14:49:34 2017 +0200 2.3 @@ -8,6 +8,17 @@ 2.4 #include <GL/glut.h> 2.5 #include "sdr.h" 2.6 2.7 +enum { 2.8 + SDR_LINE_DIST_BIT = 1, 2.9 + SDR_PLOT_ORBIT_BIT = 2 2.10 +}; 2.11 +const char *sdrdef[] = { 2.12 + "#define LINE_DIST\n", 2.13 + "#define PLOT_ORBIT\n" 2.14 +}; 2.15 +#define NUM_SDR_BITS (sizeof sdrdef / sizeof *sdrdef) 2.16 +#define NUM_SHADERS (1 << NUM_SDR_BITS) 2.17 + 2.18 int init(void); 2.19 void cleanup(void); 2.20 void disp(void); 2.21 @@ -21,11 +32,12 @@ 2.22 static int win_width = 1280, win_height = 800; 2.23 static float win_aspect; 2.24 static int mouse_x = 640, mouse_y = 400; 2.25 -static unsigned int prog_mbrot; 2.26 +static unsigned int prog_mbrot[NUM_SHADERS]; 2.27 2.28 static float view_center[2] = {0.7, 0.0}; 2.29 static float view_scale = 1.2; 2.30 2.31 +static unsigned int sdrflags; 2.32 2.33 int main(int argc, char **argv) 2.34 { 2.35 @@ -53,17 +65,57 @@ 2.36 2.37 int init(void) 2.38 { 2.39 + int i, j; 2.40 + unsigned int vs = 0, ps[NUM_SHADERS] = {0}; 2.41 + 2.42 glewInit(); 2.43 2.44 - if(!(prog_mbrot = create_program_load("vertex.glsl", "mbrot.glsl"))) { 2.45 + if(!(vs = load_vertex_shader("vertex.glsl"))) { 2.46 return -1; 2.47 } 2.48 + 2.49 + for(i=0; i<NUM_SHADERS; i++) { 2.50 + clear_shader_header(GL_FRAGMENT_SHADER); 2.51 + for(j=0; j<NUM_SDR_BITS; j++) { 2.52 + if(i & (1 << j)) { 2.53 + add_shader_header(GL_FRAGMENT_SHADER, sdrdef[j]); 2.54 + } 2.55 + } 2.56 + 2.57 + if(!(ps[i] = load_pixel_shader("mbrot.glsl"))) { 2.58 + goto err; 2.59 + } 2.60 + 2.61 + if(!(prog_mbrot[i] = create_program_link(vs, ps[i], 0))) { 2.62 + goto err; 2.63 + } 2.64 + } 2.65 return 0; 2.66 + 2.67 +err: 2.68 + for(i=0; i<NUM_SHADERS; i++) { 2.69 + if(prog_mbrot[i]) { 2.70 + free_program(prog_mbrot[i]); 2.71 + prog_mbrot[i] = 0; 2.72 + } 2.73 + if(ps[i]) { 2.74 + free_shader(ps[i]); 2.75 + } 2.76 + } 2.77 + if(vs) { 2.78 + free_shader(vs); 2.79 + } 2.80 + return -1; 2.81 } 2.82 2.83 void cleanup(void) 2.84 { 2.85 - free_program(prog_mbrot); 2.86 + int i; 2.87 + 2.88 + for(i=0; i<NUM_SHADERS; i++) { 2.89 + free_program(prog_mbrot[i]); 2.90 + prog_mbrot[i] = 0; 2.91 + } 2.92 } 2.93 2.94 void pixel_to_complex(float *res, float px, float py) 2.95 @@ -83,10 +135,10 @@ 2.96 2.97 pixel_to_complex(seed, mouse_x, mouse_y); 2.98 2.99 - set_uniform_float2(prog_mbrot, "seed", seed[0], seed[1]); 2.100 - set_uniform_float(prog_mbrot, "view_scale", view_scale); 2.101 - set_uniform_float2(prog_mbrot, "view_center", view_center[0], view_center[1]); 2.102 - glUseProgram(prog_mbrot); 2.103 + set_uniform_float2(prog_mbrot[sdrflags], "seed", seed[0], seed[1]); 2.104 + set_uniform_float(prog_mbrot[sdrflags], "view_scale", view_scale); 2.105 + set_uniform_float2(prog_mbrot[sdrflags], "view_center", view_center[0], view_center[1]); 2.106 + glUseProgram(prog_mbrot[sdrflags]); 2.107 2.108 glBegin(GL_QUADS); 2.109 for(i=0; i<4; i++) { 2.110 @@ -131,6 +183,16 @@ 2.111 } 2.112 break; 2.113 2.114 + case ' ': 2.115 + sdrflags ^= SDR_LINE_DIST_BIT; 2.116 + glutPostRedisplay(); 2.117 + break; 2.118 + 2.119 + case 'o': 2.120 + sdrflags ^= SDR_PLOT_ORBIT_BIT; 2.121 + glutPostRedisplay(); 2.122 + break; 2.123 + 2.124 case '`': 2.125 screenshot(); 2.126 break;