Skip to content

Instantly share code, notes, and snippets.

@tai2
Last active December 17, 2015 04:48
Show Gist options
  • Select an option

  • Save tai2/5552886 to your computer and use it in GitHub Desktop.

Select an option

Save tai2/5552886 to your computer and use it in GitHub Desktop.
Old school tunnel effect. c.f. http://benryves.com/tutorials/tunnel/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GLUT/glut.h>
#include <FreeImage.h>
#define MIN(x,y) ((x) > (y) ? (y) : (x))
#define KEY_ESC 27
#define WINDOW_POS_X 100
#define WINDOW_POS_Y 100
#define DEF_SCREEN_WIDTH 512
#define DEF_SCREEN_HEIGHT 512
#define TEXTURE_FILE "texture.jpg"
#define TEXTURE_SIZE 512
#define V_DEPTH 300.0
#define V_RAD 200.0
#define UPDATE_PERIOD 16
static int curr_width = 0;
static int curr_height = 0;
static GLubyte *screen_buf = NULL;
static int fullscreen = 0;
static FIBITMAP *texture = NULL;
static clock_t c_orig = 0;
static void
keyboard(unsigned char c, int x, int y)
{
switch (c) {
case KEY_ESC:
exit(0);
break;
case 'f':
if (fullscreen) {
glutReshapeWindow(DEF_SCREEN_WIDTH, DEF_SCREEN_HEIGHT);
glutPositionWindow(WINDOW_POS_X, WINDOW_POS_Y);
fullscreen = 0;
} else {
glutFullScreen();
fullscreen = 1;
}
break;
}
}
void
idle()
{
glutPostRedisplay();
}
static void
reshape(int w, int h)
{
curr_width = w;
curr_height = h;
if (screen_buf) {
free(screen_buf);
}
screen_buf = (GLubyte *)malloc(curr_width * curr_height * 4);
if (!screen_buf) {
abort();
}
}
static void
draw_pixel(int x, int y, GLubyte r, GLubyte g, GLubyte b)
{
int base = 4 * ((curr_height - 1 - y) * curr_width + x);
screen_buf[base + 0] = r;
screen_buf[base + 1] = g;
screen_buf[base + 2] = b;
screen_buf[base + 3] = 255;
}
static void
display()
{
int x, y;
double t = (double)(clock() - c_orig) / CLOCKS_PER_SEC;
double distance_max = (curr_width - 1) * (curr_width - 1) + (curr_height - 1) * (curr_height - 1);
glClear(GL_COLOR_BUFFER_BIT);
for (y = 0; y < curr_height; y++) {
for (x = 0; x < curr_width; x++) {
int tx = x - curr_width * 0.5 + ((curr_width * 0.1) * sin(0.6 * t));
int ty = y - curr_width * 0.5 + ((curr_height * 0.25) * cos(0.5 * t));
int distance = tx * tx + ty * ty;
int depth = distance == 0 ? 8388608 : 8388608 / distance;
int u, v;
double rad;
double brightness;
RGBQUAD texval;
if (tx == 0) {
if (0 < ty) {
rad = M_PI / 2;
} else {
rad = 3 * M_PI / 4;
}
} else {
rad = atan((double)ty / tx);
if (0 > tx) {
rad += M_PI;
}
}
rad += M_PI / 2;
rad *= 6;
u = ((int)(TEXTURE_SIZE * rad / (2 * M_PI) + V_RAD * t)) % TEXTURE_SIZE;
v = ((int)(depth + V_DEPTH * t + V_DEPTH * cos(0.5 * t))) % TEXTURE_SIZE;
while (0 > u) u += TEXTURE_SIZE;
while (0 > v) v += TEXTURE_SIZE;
brightness = MIN(1.0, 0.05 + distance / distance_max);
FreeImage_GetPixelColor(texture, u, v, &texval);
draw_pixel(x, y,
brightness * texval.rgbRed,
brightness * texval.rgbGreen,
brightness * texval.rgbBlue);
}
}
glWindowPos2i(0, 0);
glDrawPixels(curr_width, curr_height, GL_RGBA, GL_UNSIGNED_BYTE, screen_buf);
glutSwapBuffers();
}
static FIBITMAP*
load_texture(const char *filename)
{
FIBITMAP *fib;
fib = FreeImage_Load(FIF_JPEG, filename, JPEG_DEFAULT);
if (!fib) {
abort();
}
if (FreeImage_GetWidth(fib) != TEXTURE_SIZE || FreeImage_GetHeight(fib) != TEXTURE_SIZE) {
abort();
}
return fib;
}
static void
unload_texture(FIBITMAP *fib) {
FreeImage_Unload(fib);
}
int
main(int argc, char** argv)
{
srand(0);
texture = load_texture(TEXTURE_FILE);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
glutInitWindowSize(DEF_SCREEN_WIDTH, DEF_SCREEN_HEIGHT);
glutInitWindowPosition(WINDOW_POS_X, WINDOW_POS_Y);
glutCreateWindow(argv[0]);
glutKeyboardFunc(keyboard);
glutIdleFunc(idle);
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
c_orig = clock();
glutMainLoop();
unload_texture(texture);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment