fractorb

annotate src/main.c @ 3:f440ecffc45a

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
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <stdlib.h>
nuclear@2 3 #include <string.h>
nuclear@1 4 #include <math.h>
nuclear@2 5 #include <errno.h>
nuclear@2 6 #include <dirent.h>
nuclear@0 7 #include <GL/glew.h>
nuclear@0 8 #include <GL/glut.h>
nuclear@0 9 #include "sdr.h"
nuclear@0 10
nuclear@3 11 enum {
nuclear@3 12 SDR_LINE_DIST_BIT = 1,
nuclear@3 13 SDR_PLOT_ORBIT_BIT = 2
nuclear@3 14 };
nuclear@3 15 const char *sdrdef[] = {
nuclear@3 16 "#define LINE_DIST\n",
nuclear@3 17 "#define PLOT_ORBIT\n"
nuclear@3 18 };
nuclear@3 19 #define NUM_SDR_BITS (sizeof sdrdef / sizeof *sdrdef)
nuclear@3 20 #define NUM_SHADERS (1 << NUM_SDR_BITS)
nuclear@3 21
nuclear@0 22 int init(void);
nuclear@0 23 void cleanup(void);
nuclear@0 24 void disp(void);
nuclear@0 25 void reshape(int x, int y);
nuclear@1 26 void keydown(unsigned char key, int x, int y);
nuclear@1 27 void keyup(unsigned char key, int x, int y);
nuclear@0 28 void mouse(int bn, int st, int x, int y);
nuclear@0 29 void motion(int x, int y);
nuclear@2 30 void screenshot(void);
nuclear@0 31
nuclear@1 32 static int win_width = 1280, win_height = 800;
nuclear@1 33 static float win_aspect;
nuclear@1 34 static int mouse_x = 640, mouse_y = 400;
nuclear@3 35 static unsigned int prog_mbrot[NUM_SHADERS];
nuclear@0 36
nuclear@1 37 static float view_center[2] = {0.7, 0.0};
nuclear@1 38 static float view_scale = 1.2;
nuclear@1 39
nuclear@3 40 static unsigned int sdrflags;
nuclear@1 41
nuclear@0 42 int main(int argc, char **argv)
nuclear@0 43 {
nuclear@0 44 glutInit(&argc, argv);
nuclear@0 45 glutInitWindowSize(1280, 800);
nuclear@0 46 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
nuclear@0 47 glutCreateWindow("fractorb");
nuclear@0 48
nuclear@0 49 glutDisplayFunc(disp);
nuclear@0 50 glutReshapeFunc(reshape);
nuclear@1 51 glutKeyboardFunc(keydown);
nuclear@1 52 glutKeyboardUpFunc(keyup);
nuclear@0 53 glutMouseFunc(mouse);
nuclear@0 54 glutMotionFunc(motion);
nuclear@0 55
nuclear@0 56 if(init() == -1) {
nuclear@0 57 return 1;
nuclear@0 58 }
nuclear@0 59 atexit(cleanup);
nuclear@0 60
nuclear@0 61 glutMainLoop();
nuclear@0 62 return 0;
nuclear@0 63 }
nuclear@0 64
nuclear@0 65
nuclear@0 66 int init(void)
nuclear@0 67 {
nuclear@3 68 int i, j;
nuclear@3 69 unsigned int vs = 0, ps[NUM_SHADERS] = {0};
nuclear@3 70
nuclear@0 71 glewInit();
nuclear@0 72
nuclear@3 73 if(!(vs = load_vertex_shader("vertex.glsl"))) {
nuclear@0 74 return -1;
nuclear@0 75 }
nuclear@3 76
nuclear@3 77 for(i=0; i<NUM_SHADERS; i++) {
nuclear@3 78 clear_shader_header(GL_FRAGMENT_SHADER);
nuclear@3 79 for(j=0; j<NUM_SDR_BITS; j++) {
nuclear@3 80 if(i & (1 << j)) {
nuclear@3 81 add_shader_header(GL_FRAGMENT_SHADER, sdrdef[j]);
nuclear@3 82 }
nuclear@3 83 }
nuclear@3 84
nuclear@3 85 if(!(ps[i] = load_pixel_shader("mbrot.glsl"))) {
nuclear@3 86 goto err;
nuclear@3 87 }
nuclear@3 88
nuclear@3 89 if(!(prog_mbrot[i] = create_program_link(vs, ps[i], 0))) {
nuclear@3 90 goto err;
nuclear@3 91 }
nuclear@3 92 }
nuclear@0 93 return 0;
nuclear@3 94
nuclear@3 95 err:
nuclear@3 96 for(i=0; i<NUM_SHADERS; i++) {
nuclear@3 97 if(prog_mbrot[i]) {
nuclear@3 98 free_program(prog_mbrot[i]);
nuclear@3 99 prog_mbrot[i] = 0;
nuclear@3 100 }
nuclear@3 101 if(ps[i]) {
nuclear@3 102 free_shader(ps[i]);
nuclear@3 103 }
nuclear@3 104 }
nuclear@3 105 if(vs) {
nuclear@3 106 free_shader(vs);
nuclear@3 107 }
nuclear@3 108 return -1;
nuclear@0 109 }
nuclear@0 110
nuclear@0 111 void cleanup(void)
nuclear@0 112 {
nuclear@3 113 int i;
nuclear@3 114
nuclear@3 115 for(i=0; i<NUM_SHADERS; i++) {
nuclear@3 116 free_program(prog_mbrot[i]);
nuclear@3 117 prog_mbrot[i] = 0;
nuclear@3 118 }
nuclear@0 119 }
nuclear@0 120
nuclear@1 121 void pixel_to_complex(float *res, float px, float py)
nuclear@1 122 {
nuclear@1 123 float u = (2.0 * px / win_width - 1.0) * win_aspect;
nuclear@1 124 float v = 2.0 * py / win_height - 1.0;
nuclear@1 125 res[0] = u * view_scale - view_center[0];
nuclear@1 126 res[1] = v * view_scale - view_center[1];
nuclear@1 127 }
nuclear@1 128
nuclear@0 129 void disp(void)
nuclear@0 130 {
nuclear@1 131 int i;
nuclear@1 132 float seed[2];
nuclear@1 133 static const float verts[][2] = {{-1, -1}, {1, -1}, {1, 1}, {-1, 1}};
nuclear@1 134 static const float corners[][2] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}};
nuclear@1 135
nuclear@1 136 pixel_to_complex(seed, mouse_x, mouse_y);
nuclear@1 137
nuclear@3 138 set_uniform_float2(prog_mbrot[sdrflags], "seed", seed[0], seed[1]);
nuclear@3 139 set_uniform_float(prog_mbrot[sdrflags], "view_scale", view_scale);
nuclear@3 140 set_uniform_float2(prog_mbrot[sdrflags], "view_center", view_center[0], view_center[1]);
nuclear@3 141 glUseProgram(prog_mbrot[sdrflags]);
nuclear@0 142
nuclear@0 143 glBegin(GL_QUADS);
nuclear@1 144 for(i=0; i<4; i++) {
nuclear@1 145 float bv[2];
nuclear@1 146 pixel_to_complex(bv, (win_width - 1) * corners[i][0], (win_height - 1) * corners[i][1]);
nuclear@1 147 glTexCoord2f(bv[0], bv[1]);
nuclear@1 148 glVertex2f(verts[i][0], verts[i][1]);
nuclear@1 149 }
nuclear@0 150 glEnd();
nuclear@0 151
nuclear@0 152 glutSwapBuffers();
nuclear@0 153 }
nuclear@0 154
nuclear@0 155 void reshape(int x, int y)
nuclear@0 156 {
nuclear@0 157 glViewport(0, 0, x, y);
nuclear@0 158
nuclear@1 159 win_aspect = (float)x / (float)y;
nuclear@1 160 win_width = x;
nuclear@1 161 win_height = y;
nuclear@0 162 }
nuclear@0 163
nuclear@1 164 static int keystate[256];
nuclear@1 165
nuclear@1 166 void keydown(unsigned char key, int x, int y)
nuclear@0 167 {
nuclear@1 168 static int fullscreen;
nuclear@1 169 static int prev_width, prev_height;
nuclear@1 170
nuclear@1 171 switch(key) {
nuclear@1 172 case 27:
nuclear@0 173 exit(0);
nuclear@1 174
nuclear@1 175 case 'f':
nuclear@1 176 fullscreen = !fullscreen;
nuclear@1 177 if(fullscreen) {
nuclear@1 178 prev_width = win_width;
nuclear@1 179 prev_height = win_height;
nuclear@1 180 glutFullScreen();
nuclear@1 181 } else {
nuclear@1 182 glutReshapeWindow(prev_width, prev_height);
nuclear@1 183 }
nuclear@1 184 break;
nuclear@1 185
nuclear@3 186 case ' ':
nuclear@3 187 sdrflags ^= SDR_LINE_DIST_BIT;
nuclear@3 188 glutPostRedisplay();
nuclear@3 189 break;
nuclear@3 190
nuclear@3 191 case 'o':
nuclear@3 192 sdrflags ^= SDR_PLOT_ORBIT_BIT;
nuclear@3 193 glutPostRedisplay();
nuclear@3 194 break;
nuclear@3 195
nuclear@2 196 case '`':
nuclear@2 197 screenshot();
nuclear@2 198 break;
nuclear@2 199
nuclear@1 200 default:
nuclear@1 201 break;
nuclear@0 202 }
nuclear@1 203 keystate[key] = 1;
nuclear@0 204 }
nuclear@0 205
nuclear@1 206 void keyup(unsigned char key, int x, int y)
nuclear@1 207 {
nuclear@1 208 keystate[key] = 0;
nuclear@1 209 }
nuclear@1 210
nuclear@1 211 static int prev_x, prev_y;
nuclear@1 212 static int bnstate[8];
nuclear@1 213
nuclear@0 214 void mouse(int bn, int st, int x, int y)
nuclear@0 215 {
nuclear@1 216 prev_x = x;
nuclear@1 217 prev_y = y;
nuclear@1 218 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN ? 1 : 0;
nuclear@0 219 }
nuclear@0 220
nuclear@0 221 void motion(int x, int y)
nuclear@0 222 {
nuclear@1 223 int dx = x - prev_x;
nuclear@1 224 int dy = y - prev_y;
nuclear@1 225 prev_x = x;
nuclear@1 226 prev_y = y;
nuclear@1 227
nuclear@1 228 if(!(dx | dy)) return;
nuclear@1 229
nuclear@1 230 if(bnstate[0]) {
nuclear@1 231 if(keystate['s']) {
nuclear@1 232 mouse_x = x;
nuclear@1 233 mouse_y = y;
nuclear@1 234 } else if(keystate['z']) {
nuclear@1 235 float s = sqrt(view_scale);
nuclear@1 236 view_scale += dy * 0.01 * s;
nuclear@1 237 if(view_scale < 1e-8) view_scale = 1e-8;
nuclear@1 238 } else {
nuclear@1 239 float s = sqrt(view_scale);
nuclear@1 240 view_center[0] += 0.01 * dx * s;
nuclear@1 241 view_center[1] += 0.01 * dy * s;
nuclear@1 242 }
nuclear@1 243 glutPostRedisplay();
nuclear@1 244 }
nuclear@0 245 }
nuclear@2 246
nuclear@2 247 void screenshot(void)
nuclear@2 248 {
nuclear@2 249 FILE *fp;
nuclear@2 250 DIR *dir;
nuclear@2 251 struct dirent *dent;
nuclear@2 252 unsigned char *img;
nuclear@2 253 static int shotnum = -1;
nuclear@2 254 char fname[128];
nuclear@2 255
nuclear@2 256 if(shotnum == -1) {
nuclear@2 257 shotnum = 1;
nuclear@2 258 if((dir = opendir("."))) {
nuclear@2 259 while((dent = readdir(dir))) {
nuclear@2 260 int num;
nuclear@2 261 if(sscanf(dent->d_name, "img%d.ppm", &num) == 1) {
nuclear@2 262 if(num >= shotnum) shotnum = num + 1;
nuclear@2 263 }
nuclear@2 264 }
nuclear@2 265 closedir(dir);
nuclear@2 266 }
nuclear@2 267 } else {
nuclear@2 268 ++shotnum;
nuclear@2 269 }
nuclear@2 270
nuclear@2 271 sprintf(fname, "img%04d.ppm", shotnum > 0 ? shotnum : 0);
nuclear@2 272 if(!(fp = fopen(fname, "wb"))) {
nuclear@2 273 fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno));
nuclear@2 274 return;
nuclear@2 275 }
nuclear@2 276
nuclear@2 277 if(!(img = malloc(win_width * win_height * 3))) {
nuclear@2 278 fprintf(stderr, "failed to allocate screenshot buffer\n");
nuclear@2 279 fclose(fp);
nuclear@2 280 return;
nuclear@2 281 }
nuclear@2 282
nuclear@2 283 glReadPixels(0, 0, win_width, win_height, GL_RGB, GL_UNSIGNED_BYTE, img);
nuclear@2 284
nuclear@2 285 fprintf(fp, "P6\n%d %d\n255\n", win_width, win_height);
nuclear@2 286 fwrite(img, 1, win_width * win_height * 3, fp);
nuclear@2 287 fclose(fp);
nuclear@2 288 free(img);
nuclear@2 289 return;
nuclear@2 290 }