132001f49Smrg/* -*- mode: c; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3; coding: utf-8-unix -*- */
232001f49Smrg/*
332001f49Smrg  Copyright (c) 2013 Kristóf Ralovich
432001f49Smrg
532001f49Smrg  Permission is hereby granted, free of charge, to any person obtaining a copy
632001f49Smrg  of this software and associated documentation files (the "Software"), to deal
732001f49Smrg  in the Software without restriction, including without limitation the rights
832001f49Smrg  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
932001f49Smrg  copies of the Software, and to permit persons to whom the Software is
1032001f49Smrg  furnished to do so, subject to the following conditions:
1132001f49Smrg
1232001f49Smrg  The above copyright notice and this permission notice shall be included in
1332001f49Smrg  all copies or substantial portions of the Software.
1432001f49Smrg
1532001f49Smrg  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1632001f49Smrg  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1732001f49Smrg  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1832001f49Smrg  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1932001f49Smrg  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2032001f49Smrg  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2132001f49Smrg  THE SOFTWARE.
2232001f49Smrg*/
2332001f49Smrg
2432001f49Smrg// Simplified version of the algorithm described in
2532001f49Smrg// K. Ralovich, M. Magdics: Recursive Ray Tracing in Geometry Shader,
2632001f49Smrg// Proceedings of the Fifth Hungarian Conference on Computer Graphics and
2732001f49Smrg// Geometry, Budapest, Hungary, 26 Jan 2010.
2832001f49Smrg
2932001f49Smrg#include <stdio.h>
3032001f49Smrg#include <stdlib.h>
3132001f49Smrg#include <GL/glew.h>
3232001f49Smrg#include "glut_wrap.h"
3332001f49Smrg#include "shaderutil.h"
3432001f49Smrg#include <math.h>
3532001f49Smrg#include <stddef.h> // offsetof
3632001f49Smrg
3732001f49Smrg// TODO: port to piglit too
3832001f49Smrg
3932001f49Smrg#define STRINGIFY_(x) #x
4032001f49Smrg#define STRINGIFY(x) STRINGIFY_(x)
4132001f49Smrg#define S__LINE__ STRINGIFY(__LINE__)
4232001f49Smrg
4332001f49Smrgstatic const float INF=9999.9F;
4432001f49Smrg
4532001f49Smrgstatic int Win;
4632001f49Smrgstatic int WinWidth = 256, WinHeight = 256;
4732001f49Smrgstatic GLboolean mouseGrabbed = GL_FALSE;
4832001f49Smrg
4932001f49Smrgstatic GLuint vertShader;
5032001f49Smrgstatic GLuint geomShader;
5132001f49Smrgstatic GLuint fragShader;
5232001f49Smrgstatic GLuint program;
5332001f49Smrg
5432001f49Smrgstatic GLuint pgQuery;
5532001f49Smrg
5632001f49Smrgstatic GLuint dst;
5732001f49Smrgstatic GLuint eyeRaysAsPoints;
5832001f49Smrg
5932001f49Smrgint posAttribLoc;
6032001f49Smrgint orig_tAttribLoc;
6132001f49Smrgint dir_idxAttribLoc;
6232001f49Smrgint uv_stateAttribLoc;
6332001f49Smrgint posVaryingLoc;
6432001f49Smrgint orig_tVaryingLoc;
6532001f49Smrgint dir_idxVaryingLoc;
6632001f49Smrgint uv_stateVaryingLoc;
6732001f49Smrgsize_t nRayGens=3;
6832001f49Smrg
6932001f49Smrgfloat rot[9] = {1,0,0,  0,1,0,   0,0,1};
7032001f49Smrg
7132001f49Smrgstatic const char* vsSource =
7232001f49Smrg"                                                                  \n"
7332001f49Smrg"#version 150 core                                                 \n"
7432001f49Smrg"#line " S__LINE__ "\n"
7532001f49Smrg"#define SHADOWS                                                   \n"
7632001f49Smrg"#define RECURSION                                                 \n"
7732001f49Smrg"                                                                  \n"
7832001f49Smrg"const float INF=9999.9;                                           \n"
7932001f49Smrg"const float EPSILON = 0.00001;                                    \n"
8032001f49Smrg"                                                                  \n"
8132001f49Smrg"uniform vec3 cameraPos;                                           \n"
8232001f49Smrg"uniform mat3 rot3;                                                \n"
8332001f49Smrg"uniform vec3 lightPos;                                            \n"
8432001f49Smrg"uniform vec4 backgroundColor;                                     \n"
8532001f49Smrg"uniform int emitNoMore;                                           \n"
8632001f49Smrg"                                                                  \n"
8732001f49Smrg"in vec4 pos;                                                      \n"
8832001f49Smrg"in vec4 orig_t;                                                   \n"
8932001f49Smrg"in vec4 dir_idx;                                                  \n"
9032001f49Smrg"in vec4 uv_state;                                                 \n"
9132001f49Smrg"// uv_state.z = state                                             \n"
9232001f49Smrg"// uv_state.w = type (ray generation)                             \n"
9332001f49Smrg"                                                                  \n"
9432001f49Smrg"//int state // inFB                                               \n"
9532001f49Smrg"//    0: generation of ray dirs needed                            \n"
9632001f49Smrg"//    1: do not generate ray dirs, keep in GS, intersect, not in FB\n"
9732001f49Smrg"//    3: cull in next GS, already in FB                           \n"
9832001f49Smrg"//int type  // isShadow                                           \n"
9932001f49Smrg"//   -1: not shadow ray, reflected                                \n"
10032001f49Smrg"//    0: not shadow ray, eye ray                                  \n"
10132001f49Smrg"//    1: shadow ray                                               \n"
10232001f49Smrg"                                                                  \n"
10332001f49Smrg"out vec4 orig_t1;                                                 \n"
10432001f49Smrg"out vec4 dir_idx1;                                                \n"
10532001f49Smrg"out vec4 uv_state1;                                               \n"
10632001f49Smrg"                                                                  \n"
10732001f49Smrg"                                                                  \n"
10832001f49Smrg"//----------------------------------------------------------------\n"
10932001f49Smrg"                                                                  \n"
11032001f49Smrg"struct Ray                                                        \n"
11132001f49Smrg"{                                                                 \n"
11232001f49Smrg"  vec3 orig;                                                      \n"
11332001f49Smrg"  vec3 dir;                                                       \n"
11432001f49Smrg"};                                                                \n"
11532001f49Smrg"                                                                  \n"
11632001f49Smrg"struct Sphere                                                     \n"
11732001f49Smrg"{                                                                 \n"
11832001f49Smrg"  vec3 c;                                                         \n"
11932001f49Smrg"  float r;                                                        \n"
12032001f49Smrg"};                                                                \n"
12132001f49Smrg"                                                                  \n"
12232001f49Smrg"struct Isec                                                       \n"
12332001f49Smrg"{                                                                 \n"
12432001f49Smrg"  float t;                                                        \n"
12532001f49Smrg"  int idx;                                                        \n"
12632001f49Smrg"                                                                  \n"
12732001f49Smrg"  vec3 hit;                                                       \n"
12832001f49Smrg"  vec3 n;                                                         \n"
12932001f49Smrg"};                                                                \n"
13032001f49Smrg"                                                                  \n"
13132001f49Smrg"const Sphere spheres0 = Sphere( vec3(0.0,0.0,-1.0), 0.5 );        \n"
13232001f49Smrg"const Sphere spheres1 = Sphere( vec3(-3.0,0.0,-1.0), 1.5 );       \n"
13332001f49Smrg"const Sphere spheres2 = Sphere( vec3(0.0,3.0,-1.0), 0.5 );        \n"
13432001f49Smrg"const Sphere spheres3 = Sphere( vec3(2.0,0.0,-1.0), 1.0 );        \n"
13532001f49Smrg"const Sphere spheres4 = Sphere( vec3(0.0,-11.0,-1.0), 10.0 );     \n"
13632001f49Smrg"const int nSpheres = 5;                                           \n"
13732001f49Smrg"const Sphere spheres[5]=Sphere[5](spheres0, spheres1, spheres2, spheres3, spheres4);\n"
13832001f49Smrg"                                                                  \n"
13932001f49Smrg"Isec                                                              \n"
14032001f49Smrg"lookupNormal(const in Ray ray, in Isec isec)                      \n"
14132001f49Smrg"{                                                                 \n"
14232001f49Smrg"  Sphere sph=spheres[isec.idx];                                   \n"
14332001f49Smrg"  vec3 c = sph.c;                                                 \n"
14432001f49Smrg"  float r = sph.r;                                                \n"
14532001f49Smrg"  isec.hit  = ray.orig + ray.dir * isec.t;                        \n"
14632001f49Smrg"  isec.n = (isec.hit - c) / r;                                    \n"
14732001f49Smrg"  return isec;                                                    \n"
14832001f49Smrg"}                                                                 \n"
14932001f49Smrg"                                                                  \n"
15032001f49Smrg"void                                                              \n"
15132001f49Smrg"intersect(const in Ray ray,                                       \n"
15232001f49Smrg"          const in Sphere sph,                                    \n"
15332001f49Smrg"          const in int idx,                                       \n"
15432001f49Smrg"          inout Isec isec)                                        \n"
15532001f49Smrg"{                                                                 \n"
15632001f49Smrg"  // Project both o and the sphere to the plane perpendicular to d\n"
15732001f49Smrg"  // and containing c. Let x be the point where the ray intersects\n"
15832001f49Smrg"  // the plane. If |x-c| < r, the ray intersects the sphere.      \n"
15932001f49Smrg"  vec3 o = ray.orig;                                              \n"
16032001f49Smrg"  vec3 d = ray.dir;                                               \n"
16132001f49Smrg"  vec3 n = -d;                                                    \n"
16232001f49Smrg"  vec3 c = sph.c;                                                 \n"
16332001f49Smrg"  float r = sph.r;                                                \n"
16432001f49Smrg"  float t = dot(c-o,n)/dot(n,d);//ray parameter for point x       \n"
16532001f49Smrg"  vec3 x = o+d*t;                                                 \n"
16632001f49Smrg"  float e = length(x-c);                                          \n"
16732001f49Smrg"  if (e > r)                                                      \n"
16832001f49Smrg"  {                                                               \n"
16932001f49Smrg"    // no intersection                                            \n"
17032001f49Smrg"    return;                                                       \n"
17132001f49Smrg"  }                                                               \n"
17232001f49Smrg"                                                                  \n"
17332001f49Smrg"  // Apply Pythagorean theorem on the (intersection,x,c) triangle \n"
17432001f49Smrg"  // to get the distance between c and the intersection.          \n"
17532001f49Smrg"  float f = sqrt(r*r - e*e);                                      \n"
17632001f49Smrg"  float dist = t - f;                                             \n"
17732001f49Smrg"  if (dist < 0.0)                                                 \n"
17832001f49Smrg"  {                                                               \n"
17932001f49Smrg"    // inside the sphere                                          \n"
18032001f49Smrg"    return;                                                       \n"
18132001f49Smrg"  }                                                               \n"
18232001f49Smrg"                                                                  \n"
18332001f49Smrg"  if (dist < EPSILON)                                             \n"
18432001f49Smrg"    return;                                                       \n"
18532001f49Smrg"                                                                  \n"
18632001f49Smrg"  if (dist > isec.t)                                              \n"
18732001f49Smrg"    return;                                                       \n"
18832001f49Smrg"                                                                  \n"
18932001f49Smrg"  isec.t = dist;                                                  \n"
19032001f49Smrg" isec.idx = idx;                                                  \n"
19132001f49Smrg"}                                                                 \n"
19232001f49Smrg"                                                                  \n"
19332001f49Smrg"Isec\n"
19432001f49Smrg"intersect_spheres(const in Ray ray,\n"
19532001f49Smrg"                  const in float max_t /*= INF*/)\n"
19632001f49Smrg"{\n"
19732001f49Smrg"  Isec nearest;\n"
19832001f49Smrg"  nearest.t = max_t;\n"
19932001f49Smrg"  nearest.idx = -1;\n"
20032001f49Smrg"\n"
20132001f49Smrg"  intersect(ray, spheres0, 0, nearest);\n"
20232001f49Smrg"  intersect(ray, spheres1, 1, nearest);\n"
20332001f49Smrg"  intersect(ray, spheres2, 2, nearest);\n"
20432001f49Smrg"  intersect(ray, spheres3, 3, nearest);\n"
20532001f49Smrg"  intersect(ray, spheres4, 4, nearest);                                \n"
20632001f49Smrg"                                                                       \n"
20732001f49Smrg"  return nearest;                                                      \n"
20832001f49Smrg"}                                                                      \n"
20932001f49Smrg"                                                                       \n"
21032001f49Smrg"                                                                       \n"
21132001f49Smrg"                                                                       \n"
21232001f49Smrg"//---------------------------------------------------------------------\n"
21332001f49Smrg"                                                                       \n"
21432001f49Smrg"                                                                       \n"
21532001f49Smrg"                                                                       \n"
21632001f49Smrg"                                                                       \n"
21732001f49Smrg"void                                                                   \n"
21832001f49Smrg"main()                                                                 \n"
21932001f49Smrg"{                                                                      \n"
22032001f49Smrg"  //inVS();                                                            \n"
22132001f49Smrg"  Ray  ray   = Ray(orig_t.xyz, dir_idx.xyz);                                \n"
22232001f49Smrg"  Isec isec  = Isec(orig_t.w, int(dir_idx.w), vec3(0,0,0), vec3(0,0,0));    \n"
22332001f49Smrg"  int  state = int(uv_state.z);                                             \n"
22432001f49Smrg"  int  type  = int(uv_state.w);                                             \n"
22532001f49Smrg"                                                                            \n"
22632001f49Smrg"  if (state == 0)                                                            \n"
22732001f49Smrg"  {                                                                         \n"
22832001f49Smrg"    // generate eye rays\n"
22932001f49Smrg"    ray = Ray(cameraPos, normalize(vec3(pos.x, pos.y, -1.0) * rot3));   \n"
23032001f49Smrg"    isec.t = INF;\n"
23132001f49Smrg"    isec.idx = -1;\n"
23232001f49Smrg"    state = 1;\n"
23332001f49Smrg"    type = 0;                                                           \n"
23432001f49Smrg"    isec = intersect_spheres(ray, isec.t);                              \n"
23532001f49Smrg"  }                                                                     \n"
23632001f49Smrg"#if defined(SHADOWS) || defined(RECURSION)                              \n"
23732001f49Smrg"  else if (state == 1)                                                  \n"
23832001f49Smrg"  {                                                                     \n"
23932001f49Smrg"    isec = intersect_spheres(ray, isec.t);                              \n"
24032001f49Smrg"  }                                                                     \n"
24132001f49Smrg"#endif                                                                  \n"
24232001f49Smrg"  //else state == 3                                                     \n"
24332001f49Smrg"                                                                        \n"
24432001f49Smrg"  //outVS();                                                            \n"
24532001f49Smrg"  gl_Position  = pos;                                                   \n"
24632001f49Smrg"  orig_t1.xyz  = ray.orig;                                              \n"
24732001f49Smrg"  orig_t1.w    = isec.t;                                                \n"
24832001f49Smrg"  dir_idx1.xyz = ray.dir;                                               \n"
24932001f49Smrg"  dir_idx1.w   = float(isec.idx);                                       \n"
25032001f49Smrg"  uv_state1.z  = float(state);                                          \n"
25132001f49Smrg"  uv_state1.w  = float(type);                                           \n"
25232001f49Smrg"}\n";
25332001f49Smrg
25432001f49Smrg
25532001f49Smrgstatic const char* gsSource =
25632001f49Smrg"#version 150 core                                                        \n"
25732001f49Smrg"#line " S__LINE__ "\n"
25832001f49Smrg"layout(points) in;                                                       \n"
25932001f49Smrg"layout(points, max_vertices = 3) out;                                    \n"
26032001f49Smrg"                                                                         \n"
26132001f49Smrg"#define SHADOWS                                                          \n"
26232001f49Smrg"#define RECURSION                                                        \n"
26332001f49Smrg"                                                                         \n"
26432001f49Smrg"const float INF=9999.9;                                                  \n"
26532001f49Smrg"const float EPSILON = 0.00001;                                           \n"
26632001f49Smrg"                                                                         \n"
26732001f49Smrg"uniform vec3 cameraPos;                                                  \n"
26832001f49Smrg"uniform mat3 rot3;                                                       \n"
26932001f49Smrg"uniform vec3 lightPos;                                                   \n"
27032001f49Smrg"uniform vec4 backgroundColor;                                            \n"
27132001f49Smrg"uniform int emitNoMore;                                                  \n"
27232001f49Smrg"                                                                         \n"
27332001f49Smrg"                                                                         \n"
27432001f49Smrg"//-----------------------------------------------------------------------\n"
27532001f49Smrg"                                                                         \n"
27632001f49Smrg"struct Ray                                                               \n"
27732001f49Smrg"{                                                                        \n"
27832001f49Smrg"  vec3 orig;                                                             \n"
27932001f49Smrg"  vec3 dir;                                                              \n"
28032001f49Smrg"};                                                                       \n"
28132001f49Smrg"                                                                         \n"
28232001f49Smrg"struct Sphere                                                            \n"
28332001f49Smrg"{                                                                        \n"
28432001f49Smrg"  vec3 c;                                                                \n"
28532001f49Smrg"  float r;                                                               \n"
28632001f49Smrg"};                                                                       \n"
28732001f49Smrg"                                                                         \n"
28832001f49Smrg"struct Isec                                                              \n"
28932001f49Smrg"{                                                                        \n"
29032001f49Smrg"  float t;                                                               \n"
29132001f49Smrg"  int idx;                                                               \n"
29232001f49Smrg"                                                                         \n"
29332001f49Smrg"  vec3 hit;                                                              \n"
29432001f49Smrg"  vec3 n;                                                                \n"
29532001f49Smrg"};                                                                       \n"
29632001f49Smrg"                                                                         \n"
29732001f49Smrg"const Sphere spheres0 = Sphere( vec3(0.0,0.0,-1.0), 0.5 );\n"
29832001f49Smrg"const Sphere spheres1 = Sphere( vec3(-3.0,0.0,-1.0), 1.5 );\n"
29932001f49Smrg"const Sphere spheres2 = Sphere( vec3(0.0,3.0,-1.0), 0.5 );\n"
30032001f49Smrg"const Sphere spheres3 = Sphere( vec3(2.0,0.0,-1.0), 1.0 );\n"
30132001f49Smrg"const Sphere spheres4 = Sphere( vec3(0.0,-11.0,-1.0), 10.0 );\n"
30232001f49Smrg"const int nSpheres = 5;\n"
30332001f49Smrg"const Sphere spheres[5]=Sphere[5](spheres0, spheres1, spheres2, spheres3, spheres4);\n"
30432001f49Smrg"                                                                         \n"
30532001f49Smrg"Isec                                                                     \n"
30632001f49Smrg"lookupNormal(const in Ray ray, in Isec isec)                             \n"
30732001f49Smrg"{                                                                        \n"
30832001f49Smrg"  Sphere sph=spheres[isec.idx];                                          \n"
30932001f49Smrg"  vec3 c = sph.c;                                                        \n"
31032001f49Smrg"  float r = sph.r;                                                       \n"
31132001f49Smrg"  isec.hit  = ray.orig + ray.dir * isec.t;                               \n"
31232001f49Smrg"  isec.n = (isec.hit - c) / r;                                           \n"
31332001f49Smrg"  return isec;                                                           \n"
31432001f49Smrg"}                                                                        \n"
31532001f49Smrg"                                                                         \n"
31632001f49Smrg"in vec4 orig_t1[1];                                                      \n"
31732001f49Smrg"in vec4 dir_idx1[1];                                                     \n"
31832001f49Smrg"in vec4 uv_state1[1];                                                    \n"
31932001f49Smrg"                                                                         \n"
32032001f49Smrg"out vec4 orig_t2;                                                        \n"
32132001f49Smrg"out vec4 dir_idx2;                                                       \n"
32232001f49Smrg"out vec4 uv_state2;                                                      \n"
32332001f49Smrg"                                                                         \n"
32432001f49Smrg"                                                                         \n"
32532001f49Smrg"void                                                                     \n"
32632001f49Smrg"main()                                                                   \n"
32732001f49Smrg"{                                                                        \n"
32832001f49Smrg"  //inGS();                                                              \n"
32932001f49Smrg"  Ray  ray   = Ray(orig_t1[0].xyz, dir_idx1[0].xyz);                     \n"
33032001f49Smrg"  Isec isec  = Isec(orig_t1[0].w, int(dir_idx1[0].w), vec3(0,0,0), vec3(0,0,0));  \n"
33132001f49Smrg"  int  state = int(uv_state1[0].z);                                      \n"
33232001f49Smrg"  int  type  = int(uv_state1[0].w);                                      \n"
33332001f49Smrg"                                                                         \n"
33432001f49Smrg"  if (state > 1)                                                         \n"
33532001f49Smrg"    return;                                                              \n"
33632001f49Smrg"                                                                         \n"
33732001f49Smrg"  if (isec.idx == -1)                                                    \n"
33832001f49Smrg"    return;                                                              \n"
33932001f49Smrg"                                                                         \n"
34032001f49Smrg"  // emitPassThrough();                          \n"
34132001f49Smrg"  gl_Position  = gl_in[0].gl_Position;           \n"
34232001f49Smrg"  orig_t2      = orig_t1[0];                     \n"
34332001f49Smrg"  dir_idx2     = dir_idx1[0];                    \n"
34432001f49Smrg"  uv_state2.xyw= uv_state1[0].xyw;               \n"
34532001f49Smrg"  uv_state2.z = 3.0; /*state*/                   \n"
34632001f49Smrg"  EmitVertex();                                  \n"
34732001f49Smrg"  EndPrimitive();                                                        \n"
34832001f49Smrg"                                                                         \n"
34932001f49Smrg"  if (type != 0 || emitNoMore>0)                                         \n"
35032001f49Smrg"    return;                                                              \n"
35132001f49Smrg"                                                                         \n"
35232001f49Smrg"#if defined(SHADOWS) || defined(RECURSION)\n"
35332001f49Smrg"  isec = lookupNormal(ray, isec);\n"
35432001f49Smrg"  vec3 hitN = isec.n;\n"
35532001f49Smrg"  vec3 hitP = ray.orig + ray.dir*isec.t + hitN*EPSILON;\n"
35632001f49Smrg"#endif                                                                \n"
35732001f49Smrg"#ifdef SHADOWS                                                          \n"
35832001f49Smrg"  vec3 toLight = lightPos - hitP;\n"
35932001f49Smrg"  float lightDist = length(toLight);\n"
36032001f49Smrg"  Ray shadowRay = Ray(hitP, toLight/lightDist);\n"
36132001f49Smrg"  Isec shadowHit = Isec(lightDist, -1, vec3(0,0,0), vec3(0,0,0));\n"
36232001f49Smrg"  state = 1;                                       \n"
36332001f49Smrg"  type = 1;                                        \n"
36432001f49Smrg"                                                   \n"
36532001f49Smrg"  //emitShadowRay();                               \n"
36632001f49Smrg"  gl_Position  = gl_in[0].gl_Position;             \n"
36732001f49Smrg"  orig_t2.xyz  = shadowRay.orig;                   \n"
36832001f49Smrg"  orig_t2.w    = shadowHit.t;                      \n"
36932001f49Smrg"  dir_idx2.xyz = shadowRay.dir;                    \n"
37032001f49Smrg"  dir_idx2.w   = float(shadowHit.idx);             \n"
37132001f49Smrg"  uv_state2.z  = float(state);                     \n"
37232001f49Smrg"  uv_state2.w  = float(type);                      \n"
37332001f49Smrg"  EmitVertex();                                    \n"
37432001f49Smrg"  EndPrimitive();                                  \n"
37532001f49Smrg"#endif                                             \n"
37632001f49Smrg"#ifdef RECURSION                                   \n"
37732001f49Smrg"  Ray  reflRay = Ray(hitP, reflect(ray.dir, hitN));\n"
37832001f49Smrg"  Isec reflHit = Isec(INF, -1, vec3(0,0,0), vec3(0,0,0));\n"
37932001f49Smrg"  state = 1;          // intersect in next pass, FS discard in this pass\n"
38032001f49Smrg"  type  = -1;                                   \n"
38132001f49Smrg"                                                \n"
38232001f49Smrg"  //emitReflRay();                              \n"
38332001f49Smrg"  gl_Position  = gl_in[0].gl_Position;          \n"
38432001f49Smrg"  orig_t2.xyz  = reflRay.orig;                  \n"
38532001f49Smrg"  orig_t2.w    = reflHit.t;                     \n"
38632001f49Smrg"  dir_idx2.xyz = reflRay.dir;                   \n"
38732001f49Smrg"  dir_idx2.w   = float(reflHit.idx);            \n"
38832001f49Smrg"  uv_state2.z  = float(state);                  \n"
38932001f49Smrg"  uv_state2.w  = float(type);                   \n"
39032001f49Smrg"  EmitVertex();                                 \n"
39132001f49Smrg"  EndPrimitive();                               \n"
39232001f49Smrg"#endif\n"
39332001f49Smrg"}\n";
39432001f49Smrg
39532001f49Smrgstatic const char* fsSource =
39632001f49Smrg"#version 150 core                                                        \n"
39732001f49Smrg"#line " S__LINE__ "\n"
39832001f49Smrg"                                                                         \n"
39932001f49Smrg"#define SHADOWS                                                          \n"
40032001f49Smrg"#define RECURSION                                                        \n"
40132001f49Smrg"                                                                         \n"
40232001f49Smrg"const float INF=9999.9;                                                  \n"
40332001f49Smrg"const float EPSILON = 0.00001;                                           \n"
40432001f49Smrg"                                                                         \n"
40532001f49Smrg"uniform vec3 cameraPos;                                                  \n"
40632001f49Smrg"uniform mat3 rot3;                                                       \n"
40732001f49Smrg"uniform vec3 lightPos;                                                   \n"
40832001f49Smrg"uniform vec4 backgroundColor;                                            \n"
40932001f49Smrg"uniform int emitNoMore;                                                  \n"
41032001f49Smrg"                                                                         \n"
41132001f49Smrg"out vec4 frag_color;                                                     \n"
41232001f49Smrg"                                                                         \n"
41332001f49Smrg"//-----------------------------------------------------------------------\n"
41432001f49Smrg"                                                                         \n"
41532001f49Smrg"struct Ray\n"
41632001f49Smrg"{\n"
41732001f49Smrg"  vec3 orig;\n"
41832001f49Smrg"  vec3 dir;\n"
41932001f49Smrg"};\n"
42032001f49Smrg"\n"
42132001f49Smrg"struct Sphere\n"
42232001f49Smrg"{\n"
42332001f49Smrg"  vec3 c;\n"
42432001f49Smrg"  float r;\n"
42532001f49Smrg"};\n"
42632001f49Smrg"\n"
42732001f49Smrg"struct Isec\n"
42832001f49Smrg"{\n"
42932001f49Smrg"  float t;\n"
43032001f49Smrg"  int idx;\n"
43132001f49Smrg"\n"
43232001f49Smrg"  vec3 hit;\n"
43332001f49Smrg"  vec3 n;\n"
43432001f49Smrg"};\n"
43532001f49Smrg"\n"
43632001f49Smrg"const Sphere spheres0 = Sphere( vec3(0.0,0.0,-1.0), 0.5 );\n"
43732001f49Smrg"const Sphere spheres1 = Sphere( vec3(-3.0,0.0,-1.0), 1.5 );\n"
43832001f49Smrg"const Sphere spheres2 = Sphere( vec3(0.0,3.0,-1.0), 0.5 );\n"
43932001f49Smrg"const Sphere spheres3 = Sphere( vec3(2.0,0.0,-1.0), 1.0 );\n"
44032001f49Smrg"const Sphere spheres4 = Sphere( vec3(0.0,-11.0,-1.0), 10.0 );\n"
44132001f49Smrg"const int nSpheres = 5;\n"
44232001f49Smrg"const Sphere spheres[5]=Sphere[5](spheres0, spheres1, spheres2, spheres3, spheres4);\n"
44332001f49Smrg"\n"
44432001f49Smrg"Isec\n"
44532001f49Smrg"lookupNormal(const in Ray ray, in Isec isec)\n"
44632001f49Smrg"{\n"
44732001f49Smrg"  Sphere sph=spheres[isec.idx];\n"
44832001f49Smrg"  vec3 c = sph.c;\n"
44932001f49Smrg"  float r = sph.r;\n"
45032001f49Smrg"  isec.hit  = ray.orig + ray.dir * isec.t;\n"
45132001f49Smrg"  isec.n = (isec.hit - c) / r;\n"
45232001f49Smrg"  return isec;\n"
45332001f49Smrg"}\n"
45432001f49Smrg"\n"
45532001f49Smrg"in vec4 orig_t2;\n"
45632001f49Smrg"in vec4 dir_idx2;\n"
45732001f49Smrg"in vec4 uv_state2;\n"
45832001f49Smrg"\n"
45932001f49Smrg"vec3\n"
46032001f49Smrg"idx2color(const in int idx)\n"
46132001f49Smrg"{\n"
46232001f49Smrg"  vec3 diff;\n"
46332001f49Smrg"  if (idx == 0)\n"
46432001f49Smrg"    diff = vec3(1.0, 0.0, 0.0);\n"
46532001f49Smrg"  else if (idx == 1)\n"
46632001f49Smrg"    diff = vec3(0.0, 1.0, 0.0);\n"
46732001f49Smrg"  else if (idx == 2)\n"
46832001f49Smrg"    diff = vec3(0.0, 0.0, 1.0);\n"
46932001f49Smrg"  else if (idx == 3)\n"
47032001f49Smrg"    diff = vec3(1.0, 1.0, 0.0);\n"
47132001f49Smrg"  else if (idx == 4)\n"
47232001f49Smrg"    diff = vec3(0.7, 0.7, 0.7);\n"
47332001f49Smrg"  return diff;\n"
47432001f49Smrg"}\n"
47532001f49Smrg"\n"
47632001f49Smrg"\n"
47732001f49Smrg"void\n"
47832001f49Smrg"main()\n"
47932001f49Smrg"{\n"
48032001f49Smrg"  Ray  ray   = Ray(orig_t2.xyz, dir_idx2.xyz);\n"
48132001f49Smrg"  Isec isec  = Isec(orig_t2.w, int(dir_idx2.w), vec3(0,0,0), vec3(0,0,0));\n"
48232001f49Smrg"  int  state = int(uv_state2.z);\n"
48332001f49Smrg"  int  type  = int(uv_state2.w);\n"
48432001f49Smrg"\n"
48532001f49Smrg"  if (state < 3)\n"
48632001f49Smrg"  {\n"
48732001f49Smrg"    discard;\n"
48832001f49Smrg"  }\n"
48932001f49Smrg"\n"
49032001f49Smrg"\n"
49132001f49Smrg"  if (type == 0)\n"
49232001f49Smrg"  {\n"
49332001f49Smrg"    Ray eyeRay = ray;\n"
49432001f49Smrg"    Isec eyeHit = isec;\n"
49532001f49Smrg"    if (eyeHit.idx == -1)\n"
49632001f49Smrg"    {\n"
49732001f49Smrg"      frag_color = vec4(backgroundColor.rgb, 0.0);\n"
49832001f49Smrg"      return;\n"
49932001f49Smrg"    }\n"
50032001f49Smrg"    vec3 eyeHitPosition = eyeRay.orig + eyeRay.dir * eyeHit.t;\n"
50132001f49Smrg"    vec3 lightVec = lightPos - eyeHitPosition;\n"
50232001f49Smrg"    eyeHit = lookupNormal(eyeRay, eyeHit);\n"
50332001f49Smrg"    vec3  N      = eyeHit.n;\n"
50432001f49Smrg"    vec3  L      = normalize(lightVec);                                         \n"
50532001f49Smrg"    float NdotL  = max(dot(N, L), 0.0);                                         \n"
50632001f49Smrg"    vec3 diffuse = idx2color(eyeHit.idx); // material color of the visible point\n"
50732001f49Smrg"    frag_color = vec4(diffuse * NdotL, 1.0);                                  \n"
50832001f49Smrg"    return;                                                                \n"
50932001f49Smrg"  }                                                                        \n"
51032001f49Smrg"#ifdef SHADOWS                                                             \n"
51132001f49Smrg"  if (type > 0)                                                            \n"
51232001f49Smrg"  {                                                               \n"
51332001f49Smrg"    Isec shadowHit = isec;                                        \n"
51432001f49Smrg"    if (shadowHit.idx == -1)                                      \n"
51532001f49Smrg"    {                                                             \n"
51632001f49Smrg"      discard;                                                    \n"
51732001f49Smrg"    }                                                             \n"
51832001f49Smrg"    frag_color = vec4(-1,-1,-1, 0.0);                           \n"
51932001f49Smrg"    return;                                                       \n"
52032001f49Smrg"  }                                                               \n"
52132001f49Smrg"#endif                                                            \n"
52232001f49Smrg"#ifdef RECURSION                                                  \n"
52332001f49Smrg"  // else type < 0                                                \n"
52432001f49Smrg"  {                                                               \n"
52532001f49Smrg"    Ray reflRay = ray;                                            \n"
52632001f49Smrg"    Isec reflHit = isec;                                          \n"
52732001f49Smrg"    if (reflHit.idx == -1)                                        \n"
52832001f49Smrg"    {                                                             \n"
52932001f49Smrg"      discard;                                                    \n"
53032001f49Smrg"    }                                                             \n"
53132001f49Smrg"    vec3 reflHitPosition = reflRay.orig + reflRay.dir * reflHit.t;\n"
53232001f49Smrg"    vec3 lightVec = lightPos - reflHitPosition;                   \n"
53332001f49Smrg"    reflHit = lookupNormal(reflRay, reflHit);                     \n"
53432001f49Smrg"    vec3  N      = reflHit.n;                                     \n"
53532001f49Smrg"    vec3  L      = normalize(lightVec);                           \n"
53632001f49Smrg"    float NdotL  = max(dot(N, L), 0.0);                           \n"
53732001f49Smrg"    vec3 diffuse = idx2color(reflHit.idx);                        \n"
53832001f49Smrg"    frag_color = vec4(diffuse * NdotL * 0.25, 1.0); // material color of the visible point\n"
53932001f49Smrg"    return;                                                       \n"
54032001f49Smrg"  }                                                               \n"
54132001f49Smrg"#endif                                                            \n"
54232001f49Smrg"}                                                                 \n";
54332001f49Smrg
54432001f49Smrgstruct vec4
54532001f49Smrg{
54632001f49Smrg   union {
54732001f49Smrg      float _[4];
54832001f49Smrg      struct { float x,y,z,w; };
54932001f49Smrg   };
55032001f49Smrg   vec4(float a, float b, float c, float d) : x(a), y(b), z(c), w(d) {}
55132001f49Smrg};
55232001f49Smrg
55332001f49Smrgstruct GSRay
55432001f49Smrg{
55532001f49Smrg   vec4 pos;
55632001f49Smrg   vec4 orig_t;
55732001f49Smrg   vec4 dir_idx;
55832001f49Smrg   vec4 uv_state;
55932001f49Smrg};
56032001f49Smrg
56132001f49Smrgstatic float
56232001f49Smrgdeg2rad(const float degree)
56332001f49Smrg{
56432001f49Smrg   return( degree * 0.017453292519943295769236907684886F);
56532001f49Smrg}
56632001f49Smrg
56732001f49Smrgstatic void
56832001f49Smrgrotate_xy(float* mat3, const float degreesAroundX, const float degreesAroundY)
56932001f49Smrg{
57032001f49Smrg   const float radX = deg2rad(degreesAroundX);
57132001f49Smrg   const float c1 = cosf(radX);
57232001f49Smrg   const float s1 = sinf(radX);
57332001f49Smrg   const float radY = deg2rad(degreesAroundY);
57432001f49Smrg   const float c2 = cosf(radY);
57532001f49Smrg   const float s2 = sinf(radY);
57632001f49Smrg   mat3[0] = c2;    mat3[3] = 0.0F; mat3[6] = s2;
57732001f49Smrg   mat3[1] = s1*s2; mat3[4] = c1;   mat3[7] = -s1*c2;
57832001f49Smrg   mat3[2] = -c1*s2;mat3[5] = s1;   mat3[8] = c1*c2;
57932001f49Smrg}
58032001f49Smrg
58132001f49Smrgstatic void
58232001f49Smrgidentity(float* mat3)
58332001f49Smrg{
58432001f49Smrg   mat3[0] = 1.0F; mat3[3] = 0.0F; mat3[6] = 0.0F;
58532001f49Smrg   mat3[1] = 0.0F; mat3[4] = 1.0F; mat3[7] = 0.0F;
58632001f49Smrg   mat3[2] = 0.0F; mat3[5] = 0.0F; mat3[8] = 1.0F;
58732001f49Smrg}
58832001f49Smrg
58932001f49Smrgstatic void
59032001f49SmrgDraw(void)
59132001f49Smrg{
59232001f49Smrg   glClearColor( 0.2, 0.5, 0.3, 0.0 );
59332001f49Smrg   glClearDepth(0.11F);
59432001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
59532001f49Smrg
59632001f49Smrg   glDisable(GL_DEPTH_TEST);
59732001f49Smrg   glEnable(GL_CULL_FACE);
59832001f49Smrg
59932001f49Smrg   glUseProgram(program);
60032001f49Smrg
60132001f49Smrg   glUniformMatrix3fv(glGetUniformLocation(program, "rot3"), 1, 0, rot);
60232001f49Smrg
60332001f49Smrg   //gs.gs->getVertexAttribLocation("pos", gs.posAttribLoc);
60432001f49Smrg   //gs.gs->getVertexAttribLocation("orig_t", gs.orig_tAttribLoc);
60532001f49Smrg   //gs.gs->getVertexAttribLocation("dir_idx", gs.dir_idxAttribLoc);
60632001f49Smrg   //gs.gs->getVertexAttribLocation("uv_state", gs.uv_stateAttribLoc);
60732001f49Smrg   posAttribLoc = glGetAttribLocation(program, "pos");
60832001f49Smrg   orig_tAttribLoc = glGetAttribLocation(program, "orig_t");
60932001f49Smrg   dir_idxAttribLoc = glGetAttribLocation(program, "dir_idx");
61032001f49Smrg   uv_stateAttribLoc = glGetAttribLocation(program, "uv_state");
61132001f49Smrg
61232001f49Smrg   glBindFragDataLocation(program, 0, "frag_color");
61332001f49Smrg
61432001f49Smrg   ////printf("%d\n", i);
61532001f49Smrg   //gs.fpwQuery->beginQuery();
61632001f49Smrg   //gs.pgQuery->beginQuery();
61732001f49Smrg   glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, dst);
61832001f49Smrg   glBeginQuery(GL_PRIMITIVES_GENERATED, pgQuery);
61932001f49Smrg   glBeginTransformFeedback(GL_POINTS);
62032001f49Smrg   //gs.eyeRaysAsPoints->bindAs(ARRAY);
62132001f49Smrg   glBindBuffer(GL_ARRAY_BUFFER, eyeRaysAsPoints);
62232001f49Smrg   {
62332001f49Smrg      glEnableVertexAttribArray(posAttribLoc);
62432001f49Smrg      glVertexAttribPointer(posAttribLoc, 4, GL_FLOAT, GL_FALSE,
62532001f49Smrg                            sizeof(GSRay), (void*)offsetof(GSRay, pos));
62632001f49Smrg
62732001f49Smrg      glEnableVertexAttribArray(orig_tAttribLoc);
62832001f49Smrg      glVertexAttribPointer(orig_tAttribLoc, 4, GL_FLOAT, GL_FALSE,
62932001f49Smrg                            sizeof(GSRay), (void*)offsetof(GSRay, orig_t));
63032001f49Smrg
63132001f49Smrg      glEnableVertexAttribArray(dir_idxAttribLoc);
63232001f49Smrg      glVertexAttribPointer(dir_idxAttribLoc, 4, GL_FLOAT, GL_FALSE,
63332001f49Smrg                            sizeof(GSRay), (void*)offsetof(GSRay, dir_idx));
63432001f49Smrg
63532001f49Smrg      glEnableVertexAttribArray(uv_stateAttribLoc);
63632001f49Smrg      glVertexAttribPointer(uv_stateAttribLoc, 4, GL_FLOAT, GL_FALSE,
63732001f49Smrg                            sizeof(GSRay), (void*)offsetof(GSRay, uv_state));
63832001f49Smrg
63932001f49Smrg      //if (getShadows() || getMaxRecursion() > 0)
64032001f49Smrg      //gs.gs->set_uniform("emitNoMore", 1, 0);
64132001f49Smrg      glUniform1i(glGetUniformLocation(program, "emitNoMore"), 0);
64232001f49Smrg
64332001f49Smrg      //glEnable(GL_RASTERIZER_DISCARD);
64432001f49Smrg      glDrawArrays(GL_POINTS, 0, WinWidth*WinHeight);
64532001f49Smrg      //glDisable(GL_RASTERIZER_DISCARD);
64632001f49Smrg
64732001f49Smrg      glDisableVertexAttribArray(uv_stateAttribLoc);
64832001f49Smrg
64932001f49Smrg      glDisableVertexAttribArray(dir_idxAttribLoc);
65032001f49Smrg
65132001f49Smrg      glDisableVertexAttribArray(orig_tAttribLoc);
65232001f49Smrg
65332001f49Smrg      glDisableVertexAttribArray(posAttribLoc);
65432001f49Smrg   }
65532001f49Smrg   //gs.eyeRaysAsPoints->unbindAs(ARRAY);
65632001f49Smrg   glBindBuffer(GL_ARRAY_BUFFER, 0);
65732001f49Smrg   glEndTransformFeedback();
65832001f49Smrg   //gs.pgQuery->endQuery();
65932001f49Smrg   glEndQuery(GL_PRIMITIVES_GENERATED);
66032001f49Smrg   //gs.fpwQuery->endQuery();
66132001f49Smrg
66232001f49Smrg   ////psoLog(LOG_RAW) << "1st: " << gs.fpwQuery->getQueryResult() << ", " << gs.pgQuery->getQueryResult() << "\n";
66332001f49Smrg
66432001f49Smrg
66532001f49Smrg   ////swap(src, dst);
66632001f49Smrg   glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
66732001f49Smrg
66832001f49Smrg   ////clear();
66932001f49Smrg
67032001f49Smrg   ////fpwQuery->beginQuery();
67132001f49Smrg   ////pgQuery->beginQuery();
67232001f49Smrg   //// With GL_ARB_color_buffer_float we can use negative color values
67332001f49Smrg   //// and disable clamping with ClampColorARB. This might be better for
67432001f49Smrg   //// compositing the pixels in shadow.
67532001f49Smrg   glEnable(GL_BLEND);
67632001f49Smrg   glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX); // modeRGB, modeA
67732001f49Smrg   glBlendFuncSeparate(GL_ONE, GL_SRC_ALPHA,     // srcRGB, dstRGB
67832001f49Smrg                       GL_ONE, GL_ONE);          // arcA,   dstA
67932001f49Smrg   //gs.dst->bindAs(ARRAY);
68032001f49Smrg   glBindBuffer(GL_ARRAY_BUFFER, dst);
68132001f49Smrg   {
68232001f49Smrg      glEnableVertexAttribArray(posAttribLoc);
68332001f49Smrg      glVertexAttribPointer(posAttribLoc, 4, GL_FLOAT, GL_FALSE,
68432001f49Smrg                            sizeof(GSRay), (void*)offsetof(GSRay, pos));
68532001f49Smrg
68632001f49Smrg      glEnableVertexAttribArray(orig_tAttribLoc);
68732001f49Smrg      glVertexAttribPointer(orig_tAttribLoc, 4, GL_FLOAT, GL_FALSE,
68832001f49Smrg                            sizeof(GSRay), (void*)offsetof(GSRay, orig_t));
68932001f49Smrg
69032001f49Smrg      glEnableVertexAttribArray(dir_idxAttribLoc);
69132001f49Smrg      glVertexAttribPointer(dir_idxAttribLoc, 4, GL_FLOAT, GL_FALSE,
69232001f49Smrg                            sizeof(GSRay), (void*)offsetof(GSRay, dir_idx));
69332001f49Smrg
69432001f49Smrg      glEnableVertexAttribArray(uv_stateAttribLoc);
69532001f49Smrg      glVertexAttribPointer(uv_stateAttribLoc, 4, GL_FLOAT, GL_FALSE,
69632001f49Smrg                            sizeof(GSRay), (void*)offsetof(GSRay, uv_state));
69732001f49Smrg
69832001f49Smrg      //if (getShadows() || getMaxRecursion() > 0)
69932001f49Smrg      //gs.gs->set_uniform("emitNoMore", 1, 1);
70032001f49Smrg      glUniform1i(glGetUniformLocation(program, "emitNoMore"), 1);
70132001f49Smrg      //GLint fpw = gs.fpwQuery->getQueryResult();
70232001f49Smrg      //GLint pg = gs.pgQuery->getQueryResult();
70332001f49Smrg      GLint pg;
70432001f49Smrg      glGetQueryObjectiv(pgQuery, GL_QUERY_RESULT, &pg);
70532001f49Smrg      //pso_runtime_check(fpw == pg);
70632001f49Smrg      glDrawArrays(GL_POINTS, 0, pg);
70732001f49Smrg
70832001f49Smrg      glDisableVertexAttribArray(uv_stateAttribLoc);
70932001f49Smrg
71032001f49Smrg      glDisableVertexAttribArray(dir_idxAttribLoc);
71132001f49Smrg
71232001f49Smrg      glDisableVertexAttribArray(orig_tAttribLoc);
71332001f49Smrg
71432001f49Smrg      glDisableVertexAttribArray(posAttribLoc);
71532001f49Smrg   }
71632001f49Smrg   //gs.dst->unbindAs(ARRAY);
71732001f49Smrg   glBindBuffer(GL_ARRAY_BUFFER, 0);
71832001f49Smrg   glDisable(GL_BLEND);
71932001f49Smrg   ////pgQuery->endQuery();
72032001f49Smrg   ////fpwQuery->endQuery();
72132001f49Smrg
72232001f49Smrg   ////psoLog(LOG_RAW) << "2nd: " << fpwQuery->getQueryResult() << ", " << pgQuery->getQueryResult() << "\n\n";
72332001f49Smrg   ////pso_runtime_check(fpwQuery->getQueryResult() == pgQuery->getQueryResult());
72432001f49Smrg
72532001f49Smrg   ////swap(src, dst);
72632001f49Smrg   ////for(;;);
72732001f49Smrg
72832001f49Smrg   glUseProgram(0);
72932001f49Smrg
73032001f49Smrg   glDisable(GL_CULL_FACE);
73132001f49Smrg
73232001f49Smrg//////////////////////////////////////////////////////////////////////
73332001f49Smrg
73432001f49Smrg   glutSwapBuffers();
73532001f49Smrg
73632001f49Smrg   {
73732001f49Smrg      static int frames = 0;
73832001f49Smrg      static int t0 = 0;
73932001f49Smrg      static int t1 = 0;
74032001f49Smrg      float dt;
74132001f49Smrg      frames++;
74232001f49Smrg      t1 = glutGet(GLUT_ELAPSED_TIME);
74332001f49Smrg      dt = (float)(t1-t0)/1000.0F;
74432001f49Smrg      if (dt >= 5.0F)
74532001f49Smrg      {
74632001f49Smrg         float fps = (float)frames / dt;
74732001f49Smrg         printf("%f FPS (%d frames in %f seconds)\n", fps, frames, dt);
74832001f49Smrg         frames = 0;
74932001f49Smrg         t0 = t1;
75032001f49Smrg      }
75132001f49Smrg   }
75232001f49Smrg}
75332001f49Smrg
75432001f49Smrg
75532001f49Smrgstatic void
75632001f49SmrgReshape(int width, int height)
75732001f49Smrg{
75832001f49Smrg   WinWidth = width;
75932001f49Smrg   WinHeight = height;
76032001f49Smrg   glViewport(0, 0, width, height);
76132001f49Smrg
76232001f49Smrg   {
76332001f49Smrg      size_t nElem = WinWidth*WinHeight*nRayGens;
76432001f49Smrg      glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, dst);
76532001f49Smrg      glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, nElem*sizeof(GSRay), 0, GL_STREAM_DRAW);
76632001f49Smrg      GSRay* d = (GSRay*)glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_WRITE);
76732001f49Smrg      for (size_t i = 0; i < nElem; i++)
76832001f49Smrg      {
76932001f49Smrg         d[i].dir_idx = vec4(0.0F, 0.0F, 0.0F, -1.0F);
77032001f49Smrg      }
77132001f49Smrg      glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
77232001f49Smrg      glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
77332001f49Smrg      //printf("Ping-pong VBO size 2x%d Kbytes.\n", (int)nElem*sizeof(GSRay)/1024);
77432001f49Smrg   }
77532001f49Smrg
77632001f49Smrg   {
77732001f49Smrg      glBindBuffer(GL_ARRAY_BUFFER, eyeRaysAsPoints);
77832001f49Smrg      glBufferData(GL_ARRAY_BUFFER, WinWidth*WinHeight*sizeof(GSRay), 0, GL_STATIC_DRAW);
77932001f49Smrg      GSRay* d = (GSRay*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
78032001f49Smrg      const float w = 0.5F * WinWidth;
78132001f49Smrg      const float h = 0.5F * WinHeight;
78232001f49Smrg      for (int y = 0; y < WinHeight; y++)
78332001f49Smrg      {
78432001f49Smrg         for (int x = 0; x < WinWidth; x++)
78532001f49Smrg         {
78632001f49Smrg            unsigned int i = y*WinWidth+x;
78732001f49Smrg            const float posx = x / w - 1.0F;
78832001f49Smrg            const float posy = y / h - 1.0F;
78932001f49Smrg            d[i].pos     = vec4(posx, posy, 0.5F, 1.0F);
79032001f49Smrg            d[i].orig_t  = vec4(0.0F, 0.0F, 0.0F, INF);
79132001f49Smrg            d[i].dir_idx = vec4(0.0F, 0.0F, 0.0F, -0.0F);
79232001f49Smrg            d[i].uv_state = vec4(0, 0, 0, 0);
79332001f49Smrg         }
79432001f49Smrg      }
79532001f49Smrg      glUnmapBuffer(GL_ARRAY_BUFFER);
79632001f49Smrg      glBindBuffer(GL_ARRAY_BUFFER, 0);
79732001f49Smrg   }
79832001f49Smrg}
79932001f49Smrg
80032001f49Smrg
80132001f49Smrgstatic void
80232001f49SmrgKey(unsigned char key, int x, int y)
80332001f49Smrg{
80432001f49Smrg   if (key == 27)
80532001f49Smrg   {
80632001f49Smrg      glutDestroyWindow(Win);
80732001f49Smrg      exit(0);
80832001f49Smrg   }
80932001f49Smrg   glutPostRedisplay();
81032001f49Smrg}
81132001f49Smrg
81232001f49Smrg
81332001f49Smrgstatic void
81432001f49Smrgdrag(int x, int y)
81532001f49Smrg{
81632001f49Smrg   float scale = 1.5F;
81732001f49Smrg   if (mouseGrabbed)
81832001f49Smrg   {
81932001f49Smrg      static GLfloat xRot = 0, yRot = 0;
82032001f49Smrg      xRot = (float)(x - WinWidth/2) / scale;
82132001f49Smrg      yRot = (float)(y - WinHeight/2) / scale;
82232001f49Smrg      identity(rot);
82332001f49Smrg      rotate_xy(rot, yRot, xRot);
82432001f49Smrg      glutPostRedisplay();
82532001f49Smrg   }
82632001f49Smrg}
82732001f49Smrg
82832001f49Smrg
82932001f49Smrgstatic void
83032001f49Smrgmouse(int button, int state, int x, int y)
83132001f49Smrg{
83232001f49Smrg   mouseGrabbed = (state == GLUT_DOWN);
83332001f49Smrg}
83432001f49Smrg
83532001f49Smrg
83632001f49Smrgstatic void
83732001f49SmrgInit(void)
83832001f49Smrg{
83932001f49Smrg   glDisable(GL_DEPTH_TEST);
84032001f49Smrg
84132001f49Smrg   if (!ShadersSupported())
84232001f49Smrg   {
84332001f49Smrg      fprintf(stderr, "Shaders are not supported!\n");
84432001f49Smrg      exit(-1);
84532001f49Smrg   }
84632001f49Smrg
84732001f49Smrg   if (!GLEW_VERSION_3_2)
84832001f49Smrg   {
84932001f49Smrg      fprintf(stderr, "OpenGL 3.2 (needed for transform feedback and "
85032001f49Smrg              "geometry shaders) not supported!\n");
85132001f49Smrg      exit(-1);
85232001f49Smrg   }
85332001f49Smrg
85432001f49Smrg   vertShader = CompileShaderText(GL_VERTEX_SHADER, vsSource);
85532001f49Smrg   geomShader = CompileShaderText(GL_GEOMETRY_SHADER_ARB, gsSource);
85632001f49Smrg   fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fsSource);
85732001f49Smrg   program = LinkShaders3(vertShader, geomShader, fragShader);
85832001f49Smrg
85932001f49Smrg   const char *varyings[] = {
86032001f49Smrg      "gl_Position",
86132001f49Smrg      "orig_t2",
86232001f49Smrg      "dir_idx2",
86332001f49Smrg      "uv_state2"
86432001f49Smrg   };
86532001f49Smrg   // I think it will be a performance win to use multiple buffer objects to write to
86632001f49Smrg   // instead of using the interleaved mode.
86732001f49Smrg   glTransformFeedbackVaryings(program, 4, varyings, GL_INTERLEAVED_ATTRIBS);
86832001f49Smrg   glLinkProgram(program);
86932001f49Smrg
87032001f49Smrg   if (glGetError() != 0)
87132001f49Smrg   {
87232001f49Smrg      fprintf(stderr, "Shaders were not loaded!\n");
87332001f49Smrg      exit(-1);
87432001f49Smrg   }
87532001f49Smrg
87632001f49Smrg   if (!glIsShader(vertShader))
87732001f49Smrg   {
87832001f49Smrg      fprintf(stderr, "Vertex shader failed!\n");
87932001f49Smrg      exit(-1);
88032001f49Smrg   }
88132001f49Smrg
88232001f49Smrg   if (!glIsShader(geomShader))
88332001f49Smrg   {
88432001f49Smrg      fprintf(stderr, "Geometry shader failed!\n");
88532001f49Smrg      exit(-1);
88632001f49Smrg   }
88732001f49Smrg
88832001f49Smrg   if (!glIsShader(fragShader))
88932001f49Smrg   {
89032001f49Smrg      fprintf(stderr, "Fragment shader failed!\n");
89132001f49Smrg      exit(-1);
89232001f49Smrg   }
89332001f49Smrg
89432001f49Smrg   if (!glIsProgram(program))
89532001f49Smrg   {
89632001f49Smrg      fprintf(stderr, "Shader program failed!\n");
89732001f49Smrg      exit(-1);
89832001f49Smrg   }
89932001f49Smrg
90032001f49Smrg   glUseProgram(program);
90132001f49Smrg   glUniform3f(glGetUniformLocation(program, "cameraPos"), 0,3,5);
90232001f49Smrg   glUniform4f(glGetUniformLocation(program, "backgroundColor"), 0,0,0,1);
90332001f49Smrg   glUniform1i(glGetUniformLocation(program, "emitNoMore"), 1);
90432001f49Smrg   glUniform3f(glGetUniformLocation(program, "lightPos"), 0,8,1);
90532001f49Smrg   glUseProgram(0);
90632001f49Smrg
90732001f49Smrg   printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
90832001f49Smrg
90932001f49Smrg   glGenQueries(1, &pgQuery);
91032001f49Smrg   glGenBuffers(1, &dst);
91132001f49Smrg   glGenBuffers(1, &eyeRaysAsPoints);
91232001f49Smrg
91332001f49Smrg   GLuint vao;
91432001f49Smrg   glGenVertexArrays(1, &vao);
91532001f49Smrg   glBindVertexArray(vao);
91632001f49Smrg
91732001f49Smrg   printf("\nESC                 = exit demo\nleft mouse + drag   = rotate camera\n\n");
91832001f49Smrg}
91932001f49Smrg
92032001f49Smrg
92132001f49Smrgint
92232001f49Smrgmain(int argc, char *argv[])
92332001f49Smrg{
92432001f49Smrg   glutInitWindowSize(WinWidth, WinHeight);
92532001f49Smrg   glutInit(&argc, argv);
92632001f49Smrg
92732001f49Smrg#ifdef HAVE_FREEGLUT
92832001f49Smrg   glutInitContextVersion(3, 2);
92932001f49Smrg   glutInitContextProfile(GLUT_CORE_PROFILE);
93032001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
93132001f49Smrg#elif defined __APPLE__
93232001f49Smrg   glutInitDisplayMode(GLUT_3_2_CORE_PROFILE | GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
93332001f49Smrg#else
93432001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
93532001f49Smrg#endif
93632001f49Smrg   Win = glutCreateWindow(argv[0]);
93732001f49Smrg
93832001f49Smrg   // glewInit requires glewExperimentel set to true for core profiles.
93932001f49Smrg   // Depending on the glew version it also generates GL_INVALID_ENUM.
94032001f49Smrg   glewExperimental = GL_TRUE;
94132001f49Smrg   glewInit();
94232001f49Smrg   glGetError();
94332001f49Smrg
94432001f49Smrg   glutReshapeFunc(Reshape);
94532001f49Smrg   glutKeyboardFunc(Key);
94632001f49Smrg   glutDisplayFunc(Draw);
94732001f49Smrg   glutIdleFunc(Draw);
94832001f49Smrg   glutMouseFunc(mouse);
94932001f49Smrg   glutMotionFunc(drag);
95032001f49Smrg   Init();
95132001f49Smrg   Reshape(WinWidth, WinHeight ); // fix crash under nvidia driver, as Reshape() not being called before rendering, and thus the BO-s were not created
95232001f49Smrg   glutMainLoop();
95332001f49Smrg   glutDestroyWindow(Win);
95432001f49Smrg   return 0;
95532001f49Smrg}
95632001f49Smrg
957