distray
diff src/main.cc @ 0:cf494adee646
distance field raytracer
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 25 Dec 2015 05:41:10 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/main.cc Fri Dec 25 05:41:10 2015 +0200 1.3 @@ -0,0 +1,197 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <assert.h> 1.7 +#include <GL/glew.h> 1.8 +#include <GL/glut.h> 1.9 +#include <vmath/vmath.h> 1.10 +#include "rend.h" 1.11 + 1.12 +static bool init(); 1.13 +static void cleanup(); 1.14 +static void display(); 1.15 +static void reshape(int x, int y); 1.16 +static void keyb(unsigned char key, int x, int y); 1.17 +static void mouse(int bn, int st, int x, int y); 1.18 +static void motion(int x, int y); 1.19 +static void resize_fbtex(int xsz, int ysz); 1.20 +static void update_fbtex(); 1.21 +static int next_pow2(int x); 1.22 +static float dfunc(float x, float y, float z); 1.23 + 1.24 +static int pix_scale = 2; 1.25 +static int width = 640; 1.26 +static int height = 384; 1.27 +static int win_width = width * pix_scale; 1.28 +static int win_height = height * pix_scale; 1.29 + 1.30 +static float *pixels; 1.31 +static unsigned int tex; 1.32 +static int tex_width, tex_height; 1.33 + 1.34 +static float cam_theta, cam_phi = 25, cam_dist = 10; 1.35 + 1.36 + 1.37 +int main(int argc, char **argv) 1.38 +{ 1.39 + glutInit(&argc, argv); 1.40 + glutInitWindowSize(win_width, win_height); 1.41 + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 1.42 + glutCreateWindow("distance field raytracer"); 1.43 + 1.44 + glutDisplayFunc(display); 1.45 + glutReshapeFunc(reshape); 1.46 + glutKeyboardFunc(keyb); 1.47 + glutMouseFunc(mouse); 1.48 + glutMotionFunc(motion); 1.49 + 1.50 + if(!init()) { 1.51 + return 1; 1.52 + } 1.53 + atexit(cleanup); 1.54 + 1.55 + glutMainLoop(); 1.56 + return 0; 1.57 +} 1.58 + 1.59 +static bool init() 1.60 +{ 1.61 + glewInit(); 1.62 + 1.63 + glEnable(GL_CULL_FACE); 1.64 + 1.65 + glGenTextures(1, &tex); 1.66 + glBindTexture(GL_TEXTURE_2D, tex); 1.67 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1.68 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1.69 + 1.70 + glEnable(GL_TEXTURE_2D); 1.71 + 1.72 + set_distance_function(dfunc); 1.73 + 1.74 + return true; 1.75 +} 1.76 + 1.77 +static void cleanup() 1.78 +{ 1.79 + glDeleteTextures(1, &tex); 1.80 +} 1.81 + 1.82 +static void display() 1.83 +{ 1.84 + Matrix4x4 cmat; 1.85 + cmat.translate(Vector3(0, 0, -cam_dist)); 1.86 + cmat.rotate(Vector3(1, 0, 0), DEG_TO_RAD(cam_phi)); 1.87 + cmat.rotate(Vector3(0, 1, 0), DEG_TO_RAD(cam_theta)); 1.88 + 1.89 + set_camera_matrix(cmat); 1.90 + render(); 1.91 + update_fbtex(); 1.92 + 1.93 + glMatrixMode(GL_TEXTURE); 1.94 + glLoadIdentity(); 1.95 + glScalef((float)tex_width / (float)width, (float)tex_height / (float)height, 1); 1.96 + 1.97 + glBegin(GL_QUADS); 1.98 + glTexCoord2f(0, 0); glVertex2f(-1, -1); 1.99 + glTexCoord2f(1, 0); glVertex2f(1, -1); 1.100 + glTexCoord2f(1, 1); glVertex2f(1, 1); 1.101 + glTexCoord2f(0, 1); glVertex2f(-1, 1); 1.102 + glEnd(); 1.103 + 1.104 + glutSwapBuffers(); 1.105 + assert(glGetError() == GL_NO_ERROR); 1.106 +} 1.107 + 1.108 +static void reshape(int x, int y) 1.109 +{ 1.110 + static int prev_x , prev_y; 1.111 + 1.112 + glViewport(0, 0, x, y); 1.113 + resize_fbtex(x, y); 1.114 + 1.115 + if(x != prev_x || y != prev_y) { 1.116 + delete [] pixels; 1.117 + pixels = new float[x * y * 4]; 1.118 + set_framebuffer(x, y, pixels); 1.119 + prev_x = x; 1.120 + prev_y = y; 1.121 + } 1.122 +} 1.123 + 1.124 +static void resize_fbtex(int xsz, int ysz) 1.125 +{ 1.126 + int txsz = next_pow2(xsz); 1.127 + int tysz = next_pow2(ysz); 1.128 + 1.129 + if(txsz > tex_width || tysz > tex_height) { 1.130 + tex_width = txsz; 1.131 + tex_height = tysz; 1.132 + 1.133 + glBindTexture(GL_TEXTURE_2D, tex); 1.134 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, txsz, tysz, 0, GL_RGBA, GL_FLOAT, 0); 1.135 + } 1.136 +} 1.137 + 1.138 +static void update_fbtex() 1.139 +{ 1.140 + glBindTexture(GL_TEXTURE_2D, tex); 1.141 + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, pixels); 1.142 +} 1.143 + 1.144 +static int next_pow2(int x) 1.145 +{ 1.146 + --x; 1.147 + x |= x >> 1; 1.148 + x |= x >> 2; 1.149 + x |= x >> 4; 1.150 + x |= x >> 8; 1.151 + x |= x >> 16; 1.152 + return x + 1; 1.153 +} 1.154 + 1.155 +static float dfunc(float x, float y, float z) 1.156 +{ 1.157 + return sqrt(x*x + y*y + z*z) - 1.0; 1.158 +} 1.159 + 1.160 +static void keyb(unsigned char key, int x, int y) 1.161 +{ 1.162 + switch(key) { 1.163 + case 27: 1.164 + exit(0); 1.165 + } 1.166 +} 1.167 + 1.168 +static int prev_x, prev_y; 1.169 +static bool bnstate[8]; 1.170 + 1.171 +static void mouse(int bn, int st, int x, int y) 1.172 +{ 1.173 + bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN; 1.174 + prev_x = x; 1.175 + prev_y = y; 1.176 +} 1.177 + 1.178 +static void motion(int x, int y) 1.179 +{ 1.180 + int dx = x - prev_x; 1.181 + int dy = y - prev_y; 1.182 + prev_x = x; 1.183 + prev_y = y; 1.184 + 1.185 + if(!dx && !dy) return; 1.186 + 1.187 + if(bnstate[0]) { 1.188 + cam_theta -= dx * 0.5; 1.189 + cam_phi -= dy * 0.5; 1.190 + 1.191 + if(cam_phi < -90) cam_phi = -90; 1.192 + if(cam_phi > 90) cam_phi = 90; 1.193 + glutPostRedisplay(); 1.194 + } 1.195 + if(bnstate[2]) { 1.196 + cam_dist += dy * 0.1; 1.197 + if(cam_dist < 0.0) cam_dist = 0.0; 1.198 + glutPostRedisplay(); 1.199 + } 1.200 +}