From 9e94bbbd56f8531432917362b8dc5f0d5f5c52e6 Mon Sep 17 00:00:00 2001 From: Nirav Patel Date: Sat, 10 Sep 2011 23:07:51 -0700 Subject: [PATCH] with rotation --- sosg/sosg.c | 53 ++++++++++++++++++++++++++++++++++++++++---------- sosg/sosg.frag | 18 ++++++++++++++--- 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/sosg/sosg.c b/sosg/sosg.c index e8652a9..3787ea6 100644 --- a/sosg/sosg.c +++ b/sosg/sosg.c @@ -18,19 +18,25 @@ #include #define TICK_INTERVAL 16 +#define PI 3.141592653589793 +#define ROTATION_INTERVAL PI/(120.0*(1000.0/TICK_INTERVAL)) typedef struct sosg_struct { int w; int h; + int texres[2]; float radius; float height; float center[2]; + float rotation; + float drotation; Uint32 time; SDL_Surface *screen; GLuint texture; GLuint program; GLuint vertex; GLuint fragment; + GLuint lrotation; } sosg_t; static SDL_Surface *load_image(const char *filename) @@ -132,6 +138,9 @@ static int load_shaders(sosg_t *data) glUniform2f(loc, data->center[0]/(float)data->w, data->center[1]/(float)data->h); loc = glGetUniformLocation(data->program, "ratio"); glUniform1f(loc, (float)data->w/(float)data->h); + loc = glGetUniformLocation(data->program, "texres"); + glUniform2f(loc, 1.0/(float)data->texres[0], 1.0/(float)data->texres[1]); + data->lrotation = glGetUniformLocation(data->program, "rotation"); return 0; } @@ -145,6 +154,7 @@ static int setup(sosg_t *data) } data->time = SDL_GetTicks(); + SDL_EnableKeyRepeat(250, TICK_INTERVAL); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); @@ -176,28 +186,47 @@ static void timer_update(sosg_t *data) SDL_Delay(data->time - now); } - data->time = now + TICK_INTERVAL; + while (data->time <= now) { + data->time += TICK_INTERVAL; + } } static int handle_events(sosg_t *data) { SDL_Event event; - SDL_WaitEvent(&event); - - switch (event.type) { - case SDL_KEYDOWN: - if (event.key.keysym.sym == SDLK_ESCAPE) { + + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_ESCAPE: + return -1; + case SDLK_LEFT: + data->drotation += ROTATION_INTERVAL; + break; + case SDLK_RIGHT: + data->drotation -= ROTATION_INTERVAL; + break; + case SDLK_p: + data->drotation = 0.0; + default: + break; + } + break; + case SDL_QUIT: return -1; - } - break; - case SDL_QUIT: - return -1; + default: + break; + } } + return 0; } static void update(sosg_t *data) { + glUniform1f(data->lrotation, data->rotation); + // Clear the screen before drawing glClear(GL_COLOR_BUFFER_BIT); @@ -239,6 +268,7 @@ int main(int argc, char *argv[]) data->height = 370.0; data->center[0] = 431.0; data->center[1] = 210.0; + data->rotation = PI; if (setup(data)) { return 1; @@ -253,6 +283,8 @@ int main(int argc, char *argv[]) } data->texture = load_texture(surface); + data->texres[0] = surface->w; + data->texres[1] = surface->h; SDL_FreeSurface(surface); } else { printf("SDL could not load %s: %s\n", filename, SDL_GetError()); @@ -268,6 +300,7 @@ int main(int argc, char *argv[]) while (handle_events(data) != -1) { update(data); timer_update(data); + data->rotation += data->drotation; } // Now we can delete the OpenGL texture and close down SDL diff --git a/sosg/sosg.frag b/sosg/sosg.frag index e1dbbbe..52a29c4 100644 --- a/sosg/sosg.frag +++ b/sosg/sosg.frag @@ -2,7 +2,9 @@ uniform sampler2D tex; uniform float radius; uniform float height; uniform float ratio; +uniform float rotation; uniform vec2 center; +uniform vec2 texres; #define SIN_PI_4 0.7071067811865475 #define PI2 6.283185307179586 @@ -11,15 +13,25 @@ uniform vec2 center; void main(void) { + vec4 color = vec4(0.0); vec2 offset = (gl_TexCoord[0].st - center)*vec2(ratio, 1.0); float d = length(offset); if (d > radius) { - gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); + gl_FragColor = color; } else { + // Map equirectangular to the Snow Globe fisheye float h = d*SIN_PI_4/radius; float theta = asin(height*h)+asin(h); float phi = atan(offset[0],offset[1]); - vec2 fisheye = vec2((PI-phi)/PI2, theta/PI_2); - gl_FragColor = texture2D(tex, fisheye); + vec2 fisheye = vec2((rotation-phi)/PI2, theta/PI_2); + + // A really naive filter to reduce sparkling + color += texture2D(tex, fisheye + vec2(-texres[0], 0.0)); + color += texture2D(tex, fisheye + vec2(texres[0], 0.0)); + color += texture2D(tex, fisheye); + color += texture2D(tex, fisheye + vec2(0.0, texres[1])); + color += texture2D(tex, fisheye + vec2(0.0, -texres[1])); + color /= 5.0; + gl_FragColor = color; } }