#include #include #include #include #include #include #include #if __EMSCRIPTEN__ #include #include #include #include #else #include #include #include #endif #include "koh.h" #define SCREEN_WIDTH 320 #define SCREEN_WIDTH2 (SCREEN_WIDTH/2) #define SCREEN_HEIGHT 320 #define SCREEN_HEIGHT2 (SCREEN_HEIGHT/2) static int quit=0; static SDL_Window *window = NULL; static SDL_Renderer *renderer = NULL; typedef struct rgba32_t { double r,g,b,a; } rgba32_t; #define MAX_LEVEL 7 #define QUEUE_SIZE (1+MAX_LEVEL*MAX_LEVEL*MAX_LEVEL*MAX_LEVEL*3) int queue_index=0; koh_node koh_queue[QUEUE_SIZE]; koh_config koh_set_config; int first_run=1; void queue_init() { int i; queue_index = 0; for (i=0;i= QUEUE_SIZE) { printf("Cannot add to queue\n"); return ; } koh_queue[queue_index] = kn; queue_index += 1; return; } koh_node queue_get(int idx) { koh_node kn = {-1,-1,-1,-1}; if ((idx<0) || (idx>=QUEUE_SIZE)) { return kn; } kn = koh_queue[idx]; return kn; } rgba32_t color_gen_shade(rgba32_t original, int gen, int max_gen) { rgba32_t c = {0,0,0,0}; c.r = (1.0*original.r/max_gen)*gen; c.g = (1.0*original.g/max_gen)*gen; c.b = (1.0*original.b/max_gen)*gen; c.a = original.a; return c; } rgba32_t color_gen_shade_inv(rgba32_t original, int gen, int max_gen) { rgba32_t c = {0,0,0,0}; c.r = original.r-(1.0*original.r/max_gen)*gen; c.g = original.g-(1.0*original.g/max_gen)*gen; c.b = original.b-(1.0*original.b/max_gen)*gen; c.a = original.a; return c; } rgba32_t color_gen_mainlv(rgba32_t original, int gen, int max_gen) { double color_r = 10.0/255; double color_g = 20.0/255; double color_b = 14.0/255; rgba32_t c = {color_r, color_g, color_b,0}; c.r = 1.0*180/255 - (max_gen-gen)*color_r; c.g = 1.0*100/255 - (max_gen-gen)*color_g; c.b = 1.0*50/255 - (max_gen-gen)*color_b; c.a = original.a; return c; } rgba32_t color_gen_redish(rgba32_t original, int gen, int max_gen) { double color_r = 20.0/255; double color_g = 10.0/255; double color_b = 14.0/255; rgba32_t c = {color_r, color_g, color_b,0}; c.r = 1.0*180/255 - (max_gen-gen)*color_r; c.g = 1.0*30/255 - (max_gen-gen)*color_g; c.b = 1.0*10/255 - (max_gen-gen)*color_b; c.a = original.a; return c; } rgba32_t color_gen_yellowish(rgba32_t original, int gen, int max_gen) { double color_r = 10.0/255; double color_g = 20.0/255; double color_b = 14.0/255; rgba32_t c = {color_r, color_g, color_b,0}; c.r = 1.0*180/255 - (max_gen-gen)*color_r; c.g = 1.0*160/255 - (max_gen-gen)*color_g; c.b = 1.0*40/255 - (max_gen-gen)*color_b; c.a = original.a; return c; } rgba32_t color_switch(int pattern_id, rgba32_t original, int gen, int max_gen) { switch(pattern_id) { case 0: return color_gen_shade(original, gen, max_gen); case 1: return color_gen_shade_inv(original, gen, max_gen); case 2: return color_gen_mainlv(original, gen, max_gen); case 3: return color_gen_yellowish(original, gen, max_gen); case 4: return color_gen_redish(original, gen, max_gen); default: return color_gen_mainlv(original, gen, max_gen); } return color_gen_mainlv(original, gen, max_gen); } void generate_koh(int gener, double size, int posx, int posy, double k) { int i; koh_node kn = {-1,-1,-1,-1}; double t_size = size*k; if (gener<0) { return; } kn.generaton = gener; kn.size = size; kn.x = posx; kn.y = posy; //printf("Gener %d posx %d posy %d size %f=>%f\n",gener,posx,posy,size,t_size); queue_add(kn); generate_koh(gener-1, t_size, posx-t_size/2, posy-t_size/2, k); generate_koh(gener-1, t_size, posx-t_size/2, posy+size-t_size/2, k); generate_koh(gener-1, t_size, posx+size-t_size/2, posy+size-t_size/2, k); generate_koh(gener-1, t_size, posx+size-t_size/2, posy-t_size/2, k); } void Triangle( int x, int y, int w, int h) { // An array of 3 vectors which represents 3 vertices static const GLfloat g_vertex_buffer_data[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; // This will identify our vertex buffer GLuint vertexbuffer; // Generate 1 buffer, put the resulting identifier in vertexbuffer glGenBuffers(1, &vertexbuffer); // The following commands will talk about our 'vertexbuffer' buffer glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); // Give our vertices to OpenGL. glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); // 1st attribute buffer : vertices glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); glVertexAttribPointer( 0, // attribute 0. No particular reason for 0, but must match the layout in the shader. 3, // size GL_FLOAT, // type GL_FALSE, // normalized? 0, // stride (void*)0 // array buffer offset ); // Draw the triangle ! glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle glDisableVertexAttribArray(0); } // Shader sources #if 1 const GLchar* vertexSource = "#version 100 \n" "attribute vec4 position; \n" "attribute vec4 colour; \n" "varying vec4 interpolated_colour;\n" "void main() \n" "{ \n" " interpolated_colour = colour;\n" " gl_Position = position; \n" " \n" "} \n"; #else const GLchar* vertexSource = "layout(location = 0) in vec3 vertexPosition;\n" "layout(location = 1) in vec3 vertexColor;\n" "out vec3 fragmentColor;\n" "uniform mat4 MVP;\n" "void main(){ \n" " gl_Position = vec4(vertexPosition,1);\n" " fragmentColor = vertexColor;\n" "}\n"; #endif #if 1 const GLchar* fragmentSource = "#version 100 \n" "precision mediump float;\n" "varying vec4 interpolated_colour;\n" "void main() \n" "{ \n" " gl_FragColor = interpolated_colour;\n" "} \n"; #else const GLchar* fragmentSource = "in vec3 fragmentColor;\n" "out vec3 color;\n" "void main(){\n" " color = vec3(0.0,0.0,0.0);\n" "}\n"; #endif GLuint vertexShader; GLuint fragmentShader; GLuint shaderProgram; GLint posAttrib; void RectPX( int x, int y,int w, int h ) { GLfloat x1 = (1.0f*x-SCREEN_WIDTH2)/SCREEN_WIDTH2; GLfloat y1 = (1.0f*y-SCREEN_HEIGHT2)/SCREEN_HEIGHT2; GLfloat x2 = (1.0f*(x+w)-SCREEN_WIDTH2)/SCREEN_WIDTH2; GLfloat y2 = (1.0f*(y+h)-SCREEN_HEIGHT2)/SCREEN_HEIGHT2; GLfloat vVertices[] = { x1, y2, 0.0f, x2, y2, 0.0f, x2, y1, 0.0f, x1, y1, 0.0f }; GLuint vertexPosObject; //printf("x1 %f y1 %f x2 %f y2 %f\n",x1,y1,x2,y2); glGenBuffers(1, &vertexPosObject); glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject); glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices), vVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject); glVertexAttribPointer(0 /* ? */, 3, GL_FLOAT, GL_FALSE, 0, 0); glDrawArrays ( GL_TRIANGLE_FAN, 0, 4 ); } void RectPXcolor( int x, int y,int w, int h, rgba32_t c ) { GLfloat x1 = (1.0f*x-SCREEN_WIDTH2)/SCREEN_WIDTH2; GLfloat y1 = (1.0f*y-SCREEN_HEIGHT2)/SCREEN_HEIGHT2; GLfloat x2 = (1.0f*(x+w)-SCREEN_WIDTH2)/SCREEN_WIDTH2; GLfloat y2 = (1.0f*(y+h)-SCREEN_HEIGHT2)/SCREEN_HEIGHT2; GLfloat vVertices[] = { x1, y2, 0.0f, x2, y2, 0.0f, x2, y1, 0.0f, x1, y1, 0.0f }; GLfloat cVertices[] = { c.r, c.g, c.b, c.r, c.g, c.b, c.r, c.g, c.b, c.r, c.g, c.b}; GLuint vertexPosObject; GLuint colorBuffer; glGenBuffers(1, &vertexPosObject); glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject); glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices), vVertices, GL_STATIC_DRAW); //printf("!!!x1 %f y1 %f x2 %f y2 %f\n",x1,y1,x2,y2); glGenBuffers(1, &colorBuffer); glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(cVertices), cVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject); glVertexAttribPointer(0 /* ? */, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); glVertexAttribPointer(1 /* ? */, 3, GL_FLOAT, GL_FALSE, 0, 0); glDrawArrays ( GL_TRIANGLE_FAN, 0, 4 ); glDeleteBuffers( 1, &vertexPosObject ); glDeleteBuffers( 1, &colorBuffer ); } void koh_generation_inc() { koh_set_config.max_generations += 1; if (koh_set_config.max_generations > MAX_LEVEL-1) { koh_set_config.max_generations = MAX_LEVEL-1; } } void koh_generation_dec() { koh_set_config.max_generations -= 1; if (koh_set_config.max_generations < 0) { koh_set_config.max_generations = 0; } } void koh_pos_x_add(int x) { koh_set_config.x += 10; } void koh_pos_x_sub(int x) { koh_set_config.x -= 10; } void koh_pos_y_add(int y) { koh_set_config.y += 10; } void koh_pos_y_sub(int y) { koh_set_config.y -= 10; } void koh_pattern_next() { koh_set_config.color_pattern += 1; if (koh_set_config.color_pattern>4) { koh_set_config.color_pattern=4; } } void koh_pattern_prev() { koh_set_config.color_pattern -= 1; if (koh_set_config.color_pattern<0) koh_set_config.color_pattern=0; } void koh_size_dec() { koh_set_config.size -= 25; if (koh_set_config.size<50) koh_set_config.size = 50; } void koh_size_inc() { koh_set_config.size += 25; if (koh_set_config.size>400) koh_set_config.size = 400; } rgba32_t start_col = {0.0,1.0,0.0,0.0}; #if __EMSCRIPTEN__ void main_tick() { #else int main_tick() { #endif int i,j; int update_fractal=0; SDL_Event event; SDL_StartTextInput(); while (SDL_PollEvent(&event) != 0) { switch (event.type) { case SDL_QUIT: { quit = 1; break; } case SDL_KEYDOWN: { switch (event.key.keysym.sym) { case 81: case SDLK_DOWN: update_fractal = 1; koh_pos_y_sub(10); break; case 82: case SDLK_UP: update_fractal = 1; koh_pos_y_add(10); break; case 80: case SDLK_LEFT: koh_pos_x_sub(10); update_fractal = 1; printf("sub 10\n"); break; case 79: case SDLK_RIGHT: update_fractal = 1; printf("add 10\n"); koh_pos_x_add(10); break; case 61: case 46: case SDLK_KP_PLUS: case SDLK_PLUS: update_fractal=1; koh_generation_inc(); printf("plus\n"); break; case SDLK_MINUS: update_fractal = 1; koh_generation_dec(); break; case 21: case SDLK_r: update_fractal = 1; koh_set_config.size = 100.0; koh_set_config.x = SCREEN_WIDTH2-100/2; koh_set_config.y = SCREEN_WIDTH2-100/2; koh_set_config.k = 0.5f; koh_set_config.max_generations = MAX_LEVEL-1; koh_set_config.color_pattern = 0; break; case 20: case SDLK_q: koh_pattern_prev(); break; case 26: case SDLK_w: koh_pattern_next(); break; case 4: case SDLK_a: update_fractal = 1; koh_size_dec(); break; case 22: case SDLK_s: update_fractal = 1; koh_size_inc(); break; default: printf("Unknown key %d\n",event.key.keysym.sym); update_fractal = 1; } break; } } //printf("Poll event\n"); } //check for first ever run if (first_run == 1) { first_run = 0; update_fractal = 1; } if (update_fractal == 1) { queue_init(); printf("k=%f",koh_set_config.k); generate_koh( koh_set_config.max_generations, koh_set_config.size, koh_set_config.x, koh_set_config.y, koh_set_config.k ); printf("Regenerated fractal\n"); } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(shaderProgram); for (i=0;i<=koh_set_config.max_generations;i++) { rgba32_t c = color_switch(koh_set_config.color_pattern, start_col, i, MAX_LEVEL); for (j=0;j