distray

view 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 source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <GL/glew.h>
5 #include <GL/glut.h>
6 #include <vmath/vmath.h>
7 #include "rend.h"
9 static bool init();
10 static void cleanup();
11 static void display();
12 static void reshape(int x, int y);
13 static void keyb(unsigned char key, int x, int y);
14 static void mouse(int bn, int st, int x, int y);
15 static void motion(int x, int y);
16 static void resize_fbtex(int xsz, int ysz);
17 static void update_fbtex();
18 static int next_pow2(int x);
19 static float dfunc(float x, float y, float z);
21 static int pix_scale = 2;
22 static int width = 640;
23 static int height = 384;
24 static int win_width = width * pix_scale;
25 static int win_height = height * pix_scale;
27 static float *pixels;
28 static unsigned int tex;
29 static int tex_width, tex_height;
31 static float cam_theta, cam_phi = 25, cam_dist = 10;
34 int main(int argc, char **argv)
35 {
36 glutInit(&argc, argv);
37 glutInitWindowSize(win_width, win_height);
38 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
39 glutCreateWindow("distance field raytracer");
41 glutDisplayFunc(display);
42 glutReshapeFunc(reshape);
43 glutKeyboardFunc(keyb);
44 glutMouseFunc(mouse);
45 glutMotionFunc(motion);
47 if(!init()) {
48 return 1;
49 }
50 atexit(cleanup);
52 glutMainLoop();
53 return 0;
54 }
56 static bool init()
57 {
58 glewInit();
60 glEnable(GL_CULL_FACE);
62 glGenTextures(1, &tex);
63 glBindTexture(GL_TEXTURE_2D, tex);
64 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
65 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
67 glEnable(GL_TEXTURE_2D);
69 set_distance_function(dfunc);
71 return true;
72 }
74 static void cleanup()
75 {
76 glDeleteTextures(1, &tex);
77 }
79 static void display()
80 {
81 Matrix4x4 cmat;
82 cmat.translate(Vector3(0, 0, -cam_dist));
83 cmat.rotate(Vector3(1, 0, 0), DEG_TO_RAD(cam_phi));
84 cmat.rotate(Vector3(0, 1, 0), DEG_TO_RAD(cam_theta));
86 set_camera_matrix(cmat);
87 render();
88 update_fbtex();
90 glMatrixMode(GL_TEXTURE);
91 glLoadIdentity();
92 glScalef((float)tex_width / (float)width, (float)tex_height / (float)height, 1);
94 glBegin(GL_QUADS);
95 glTexCoord2f(0, 0); glVertex2f(-1, -1);
96 glTexCoord2f(1, 0); glVertex2f(1, -1);
97 glTexCoord2f(1, 1); glVertex2f(1, 1);
98 glTexCoord2f(0, 1); glVertex2f(-1, 1);
99 glEnd();
101 glutSwapBuffers();
102 assert(glGetError() == GL_NO_ERROR);
103 }
105 static void reshape(int x, int y)
106 {
107 static int prev_x , prev_y;
109 glViewport(0, 0, x, y);
110 resize_fbtex(x, y);
112 if(x != prev_x || y != prev_y) {
113 delete [] pixels;
114 pixels = new float[x * y * 4];
115 set_framebuffer(x, y, pixels);
116 prev_x = x;
117 prev_y = y;
118 }
119 }
121 static void resize_fbtex(int xsz, int ysz)
122 {
123 int txsz = next_pow2(xsz);
124 int tysz = next_pow2(ysz);
126 if(txsz > tex_width || tysz > tex_height) {
127 tex_width = txsz;
128 tex_height = tysz;
130 glBindTexture(GL_TEXTURE_2D, tex);
131 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, txsz, tysz, 0, GL_RGBA, GL_FLOAT, 0);
132 }
133 }
135 static void update_fbtex()
136 {
137 glBindTexture(GL_TEXTURE_2D, tex);
138 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, pixels);
139 }
141 static int next_pow2(int x)
142 {
143 --x;
144 x |= x >> 1;
145 x |= x >> 2;
146 x |= x >> 4;
147 x |= x >> 8;
148 x |= x >> 16;
149 return x + 1;
150 }
152 static float dfunc(float x, float y, float z)
153 {
154 return sqrt(x*x + y*y + z*z) - 1.0;
155 }
157 static void keyb(unsigned char key, int x, int y)
158 {
159 switch(key) {
160 case 27:
161 exit(0);
162 }
163 }
165 static int prev_x, prev_y;
166 static bool bnstate[8];
168 static void mouse(int bn, int st, int x, int y)
169 {
170 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN;
171 prev_x = x;
172 prev_y = y;
173 }
175 static void motion(int x, int y)
176 {
177 int dx = x - prev_x;
178 int dy = y - prev_y;
179 prev_x = x;
180 prev_y = y;
182 if(!dx && !dy) return;
184 if(bnstate[0]) {
185 cam_theta -= dx * 0.5;
186 cam_phi -= dy * 0.5;
188 if(cam_phi < -90) cam_phi = -90;
189 if(cam_phi > 90) cam_phi = 90;
190 glutPostRedisplay();
191 }
192 if(bnstate[2]) {
193 cam_dist += dy * 0.1;
194 if(cam_dist < 0.0) cam_dist = 0.0;
195 glutPostRedisplay();
196 }
197 }