1 /* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; coding: utf-8-unix -*- */
3 Copyright (c) 2010 Kristóf Ralovich
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 #include "glut_wrap.h"
29 #include "shaderutil.h"
33 static int WinWidth
= 256, WinHeight
= 256;
34 static GLboolean mouseGrabbed
= GL_FALSE
;
35 static GLuint vertShader
;
36 static GLuint program
;
37 float rot
[9] = {1,0,0, 0,1,0, 0,0,1};
39 static const char* vsSource
=
40 "const float INF = 9999.9; \n"
41 "const float EPSILON = 0.00001; \n"
42 "const vec3 lightPos = vec3(0.0, 8.0, 1.0); \n"
43 "const vec4 backgroundColor = vec4(0.2,0.3,0.4,1); \n"
45 "uniform mat3 rot; \n"
68 "Sphere spheres0 = Sphere( vec3(0.0,0.0,-1.0), 0.5 ); \n"
69 "Sphere spheres1 = Sphere( vec3(-3.0,0.0,-1.0), 1.5 ); \n"
70 "Sphere spheres2 = Sphere( vec3(0.0,3.0,-1.0), 0.5 ); \n"
71 "Sphere spheres3 = Sphere( vec3(2.0,0.0,-1.0), 1.0 ); \n"
73 "const Sphere spheres0 = Sphere( vec3(0.0,0.0,-1.0), 0.5 ); \n"
74 "const Sphere spheres1 = Sphere( vec3(-3.0,0.0,-1.0), 1.5 ); \n"
75 "const Sphere spheres2 = Sphere( vec3(0.0,3.0,-1.0), 0.5 ); \n"
76 "const Sphere spheres3 = Sphere( vec3(2.0,0.0,-1.0), 1.0 ); \n"
79 "// Mesa intel gen4 generates \"unsupported IR in fragment shader 13\" for\n"
80 "// sqrt, let's work around. \n"
82 "sqrt_hack(float f2) \n"
84 " vec3 v = vec3(f2,0.0,0.0); \n"
85 " return length(v); \n"
89 "intersect(const in Ray ray, \n"
90 " const in Sphere sph, \n"
91 " const in int idx, \n"
92 " inout Isec isec) \n"
94 " // Project both o and the sphere to the plane perpendicular to d \n"
95 " // and containing c. Let x be the point where the ray intersects \n"
96 " // the plane. If |x-c| < r, the ray intersects the sphere. \n"
97 " vec3 o = ray.orig; \n"
98 " vec3 d = ray.dir; \n"
100 " vec3 c = sph.c; \n"
101 " float r = sph.r; \n"
102 " float t = dot(c-o,n)/dot(n,d); \n"
103 " vec3 x = o+d*t; \n"
104 " float e = length(x-c); \n"
107 " // no intersection \n"
111 " // Apply Pythagorean theorem on the (intersection,x,c) triangle \n"
112 " // to get the distance between c and the intersection. \n"
113 "#define BUGGY_INTEL_GEN4_GLSL 1 \n"
114 "#ifndef BUGGY_INTEL_GEN4_GLSL \n"
115 " float f = sqrt(r*r - e*e); \n"
117 " float f = sqrt_hack(r*r - e*e); \n"
119 " float dist = t - f; \n"
122 " // inside the sphere \n"
126 " if(dist < EPSILON) \n"
129 " if(dist > isec.t) \n"
133 " isec.idx = idx; \n"
135 " isec.hit = ray.orig + ray.dir * isec.t; \n"
136 " isec.n = (isec.hit - c) / r; \n"
140 "intersect(const in Ray ray, \n"
141 " const in float max_t /*= INF*/) \n"
144 " nearest.t = max_t; \n"
145 " nearest.idx = -1; \n"
147 " intersect(ray, spheres0, 0, nearest); \n"
148 " intersect(ray, spheres1, 1, nearest); \n"
149 " intersect(ray, spheres2, 2, nearest); \n"
150 " intersect(ray, spheres3, 3, nearest); \n"
152 " return nearest; \n"
156 "idx2color(const in int idx) \n"
160 " diff = vec4(1.0, 0.0, 0.0, 0.0); \n"
161 " else if(idx == 1) \n"
162 " diff = vec4(0.0, 1.0, 0.0, 0.0); \n"
163 " else if(idx == 2) \n"
164 " diff = vec4(0.0, 0.0, 1.0, 0.0); \n"
165 " else if(idx == 3) \n"
166 " diff = vec4(1.0, 1.0, 0.0, 0.0); \n"
171 "trace0(const in Ray ray) \n"
173 " Isec isec = intersect(ray, INF); \n"
175 " if(isec.idx == -1) \n"
177 " return backgroundColor; \n"
180 " vec4 diff = idx2color(isec.idx); \n"
182 " vec3 N = isec.n; \n"
183 " vec3 L = normalize(lightPos-isec.hit); \n"
184 " vec3 camera_dir = normalize(ray.orig - isec.hit); \n"
185 " return dot(N,L)*diff + pow( \n"
186 " clamp(dot(reflect(-L,N),camera_dir),0.0,1.0),16.0); \n"
190 "trace1(const in Ray ray) \n"
192 " Isec isec = intersect(ray, INF); \n"
194 " if(isec.idx == -1) \n"
196 " return backgroundColor; \n"
199 " Ray reflRay = Ray(isec.hit, reflect(ray.dir, isec.n)); \n"
201 " vec4 reflCol = trace0(reflRay); \n"
203 " vec4 diff = idx2color(isec.idx) + reflCol; \n"
205 " vec3 N = isec.n; \n"
206 " vec3 L = normalize(lightPos-isec.hit); \n"
207 " vec3 camera_dir = normalize(ray.orig - isec.hit); \n"
208 " return dot(N,L)*diff + pow( \n"
209 " clamp(dot(reflect(-L,N),camera_dir),0.0,1.0),16.0); \n"
214 " const vec3 cameraPos = vec3(0,0,3); \n"
215 " vec3 rayDir = normalize(vec3(gl_Vertex.x, gl_Vertex.y, -1.0) * rot);\n"
216 " Ray ray = Ray(cameraPos, rayDir); \n"
217 " gl_Position = gl_Vertex; \n"
218 " gl_FrontColor = trace1(ray); \n"
224 deg2rad(const float degree
)
226 return( degree
* 0.017453292519943295769236907684886F
);
230 rotate_xy(float* mat3
, const float degreesAroundX
, const float degreesAroundY
)
232 const float radX
= deg2rad(degreesAroundX
);
233 const float c1
= cosf(radX
);
234 const float s1
= sinf(radX
);
235 const float radY
= deg2rad(degreesAroundY
);
236 const float c2
= cosf(radY
);
237 const float s2
= sinf(radY
);
238 mat3
[0] = c2
; mat3
[3] = 0.0F
; mat3
[6] = s2
;
239 mat3
[1] = s1
*s2
; mat3
[4] = c1
; mat3
[7] = -s1
*c2
;
240 mat3
[2] = -c1
*s2
;mat3
[5] = s1
; mat3
[8] = c1
*c2
;
244 identity(float* mat3
)
246 mat3
[0] = 1.0F
; mat3
[3] = 0.0F
; mat3
[6] = 0.0F
;
247 mat3
[1] = 0.0F
; mat3
[4] = 1.0F
; mat3
[7] = 0.0F
;
248 mat3
[2] = 0.0F
; mat3
[5] = 0.0F
; mat3
[8] = 1.0F
;
254 const float w
= 0.5F
* WinWidth
;
255 const float h
= 0.5F
* WinHeight
;
258 GLint location
= glGetUniformLocation(program
, "rot");
260 glUseProgram(program
);
261 glUniformMatrix3fv(location
, 1, 0, rot
);
263 for(y
= 0; y
< WinHeight
; y
++)
265 for(x
= 0; x
< WinWidth
; x
++)
267 const float posx
= x
/ w
- 1.0F
;
268 const float posy
= y
/ h
- 1.0F
;
269 glVertex2f(posx
, posy
);
278 static int frames
= 0;
283 t1
= glutGet(GLUT_ELAPSED_TIME
);
284 dt
= (float)(t1
-t0
)/1000.0F
;
287 float fps
= (float)frames
/ dt
;
288 printf("%f FPS (%d frames in %f seconds)\n", fps
, frames
, dt
);
297 Reshape(int width
, int height
)
301 glViewport(0, 0, width
, height
);
302 glMatrixMode(GL_PROJECTION
);
304 glMatrixMode(GL_MODELVIEW
);
310 Key(unsigned char key
, int x
, int y
)
314 glutDestroyWindow(Win
);
328 static GLfloat xRot
= 0, yRot
= 0;
329 xRot
= (float)(x
- WinWidth
/2) / scale
;
330 yRot
= (float)(y
- WinHeight
/2) / scale
;
332 rotate_xy(rot
, yRot
, xRot
);
340 mouse(int button
, int state
, int x
, int y
)
342 mouseGrabbed
= (state
== GLUT_DOWN
);
349 glDisable(GL_DEPTH_TEST
);
351 if(!ShadersSupported())
353 fprintf(stderr
, "Shaders are not supported!\n");
357 vertShader
= CompileShaderText(GL_VERTEX_SHADER
, vsSource
);
358 program
= LinkShaders(vertShader
, 0);
361 if(glGetError() != 0)
363 fprintf(stderr
, "Shaders were not loaded!\n");
367 if(!glIsShader(vertShader
))
369 fprintf(stderr
, "Vertex shader failed!\n");
373 if(!glIsProgram(program
))
375 fprintf(stderr
, "Shader program failed!\n");
379 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER
));
384 main(int argc
, char *argv
[])
386 glutInitWindowSize(WinWidth
, WinHeight
);
387 glutInit(&argc
, argv
);
388 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
389 Win
= glutCreateWindow(argv
[0]);
391 glutReshapeFunc(Reshape
);
392 glutKeyboardFunc(Key
);
393 glutDisplayFunc(Draw
);
395 glutMouseFunc(mouse
);
396 glutMotionFunc(drag
);