Raytracing demonstration for Pokitto
Dependencies: PokittoLib
main.cpp@3:c5e3a23c9ff3, 2018-05-02 (annotated)
- Committer:
- Pokitto
- Date:
- Wed May 02 06:52:50 2018 +0000
- Revision:
- 3:c5e3a23c9ff3
- Parent:
- 0:398e251490fd
New pokittolib with improved volume controls & better button handling
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Pokitto | 0:398e251490fd | 1 | // [header] |
Pokitto | 0:398e251490fd | 2 | // A very basic raytracer example. |
Pokitto | 0:398e251490fd | 3 | // [/header] |
Pokitto | 0:398e251490fd | 4 | // [compile] |
Pokitto | 0:398e251490fd | 5 | // c++ -o raytracer -O3 -Wall raytracer.cpp |
Pokitto | 0:398e251490fd | 6 | // [/compile] |
Pokitto | 0:398e251490fd | 7 | // [ignore] |
Pokitto | 0:398e251490fd | 8 | // Copyright (C) 2012 www.scratchapixel.com |
Pokitto | 0:398e251490fd | 9 | // |
Pokitto | 0:398e251490fd | 10 | // This program is free software: you can redistribute it and/or modify |
Pokitto | 0:398e251490fd | 11 | // it under the terms of the GNU General Public License as published by |
Pokitto | 0:398e251490fd | 12 | // the Free Software Foundation, either version 3 of the License, or |
Pokitto | 0:398e251490fd | 13 | // (at your option) any later version. |
Pokitto | 0:398e251490fd | 14 | // |
Pokitto | 0:398e251490fd | 15 | // This program is distributed in the hope that it will be useful, |
Pokitto | 0:398e251490fd | 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
Pokitto | 0:398e251490fd | 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
Pokitto | 0:398e251490fd | 18 | // GNU General Public License for more details. |
Pokitto | 0:398e251490fd | 19 | // |
Pokitto | 0:398e251490fd | 20 | // You should have received a copy of the GNU General Public License |
Pokitto | 0:398e251490fd | 21 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
Pokitto | 0:398e251490fd | 22 | // [/ignore] |
Pokitto | 0:398e251490fd | 23 | #include "Pokitto.h" |
Pokitto | 0:398e251490fd | 24 | #include <cstdlib> |
Pokitto | 0:398e251490fd | 25 | #include <cstdio> |
Pokitto | 0:398e251490fd | 26 | #include <cmath> |
Pokitto | 0:398e251490fd | 27 | //#include <fstream> |
Pokitto | 0:398e251490fd | 28 | #include <vector> |
Pokitto | 0:398e251490fd | 29 | //#include <iostream> |
Pokitto | 0:398e251490fd | 30 | //#include <cassert> |
Pokitto | 0:398e251490fd | 31 | |
Pokitto | 0:398e251490fd | 32 | Pokitto::Core g; |
Pokitto | 0:398e251490fd | 33 | |
Pokitto | 0:398e251490fd | 34 | #if defined __linux__ || defined __APPLE__ |
Pokitto | 0:398e251490fd | 35 | // "Compiled for Linux |
Pokitto | 0:398e251490fd | 36 | #else |
Pokitto | 0:398e251490fd | 37 | // Windows doesn't define these values by default, Linux does |
Pokitto | 0:398e251490fd | 38 | #define M_PI 3.141592653589793 |
Pokitto | 0:398e251490fd | 39 | #define INFINITY 1e8 |
Pokitto | 0:398e251490fd | 40 | #endif |
Pokitto | 0:398e251490fd | 41 | |
Pokitto | 0:398e251490fd | 42 | template<typename T> |
Pokitto | 0:398e251490fd | 43 | class Vec3 |
Pokitto | 0:398e251490fd | 44 | { |
Pokitto | 0:398e251490fd | 45 | public: |
Pokitto | 0:398e251490fd | 46 | T x, y, z; |
Pokitto | 0:398e251490fd | 47 | Vec3() : x(T(0)), y(T(0)), z(T(0)) {} |
Pokitto | 0:398e251490fd | 48 | Vec3(T xx) : x(xx), y(xx), z(xx) {} |
Pokitto | 0:398e251490fd | 49 | Vec3(T xx, T yy, T zz) : x(xx), y(yy), z(zz) {} |
Pokitto | 0:398e251490fd | 50 | Vec3& normalize() |
Pokitto | 0:398e251490fd | 51 | { |
Pokitto | 0:398e251490fd | 52 | T nor2 = length2(); |
Pokitto | 0:398e251490fd | 53 | if (nor2 > 0) { |
Pokitto | 0:398e251490fd | 54 | T invNor = 1 / sqrt(nor2); |
Pokitto | 0:398e251490fd | 55 | x *= invNor, y *= invNor, z *= invNor; |
Pokitto | 0:398e251490fd | 56 | } |
Pokitto | 0:398e251490fd | 57 | return *this; |
Pokitto | 0:398e251490fd | 58 | } |
Pokitto | 0:398e251490fd | 59 | Vec3<T> operator * (const T &f) const { return Vec3<T>(x * f, y * f, z * f); } |
Pokitto | 0:398e251490fd | 60 | Vec3<T> operator * (const Vec3<T> &v) const { return Vec3<T>(x * v.x, y * v.y, z * v.z); } |
Pokitto | 0:398e251490fd | 61 | T dot(const Vec3<T> &v) const { return x * v.x + y * v.y + z * v.z; } |
Pokitto | 0:398e251490fd | 62 | Vec3<T> operator - (const Vec3<T> &v) const { return Vec3<T>(x - v.x, y - v.y, z - v.z); } |
Pokitto | 0:398e251490fd | 63 | Vec3<T> operator + (const Vec3<T> &v) const { return Vec3<T>(x + v.x, y + v.y, z + v.z); } |
Pokitto | 0:398e251490fd | 64 | Vec3<T>& operator += (const Vec3<T> &v) { x += v.x, y += v.y, z += v.z; return *this; } |
Pokitto | 0:398e251490fd | 65 | Vec3<T>& operator *= (const Vec3<T> &v) { x *= v.x, y *= v.y, z *= v.z; return *this; } |
Pokitto | 0:398e251490fd | 66 | Vec3<T> operator - () const { return Vec3<T>(-x, -y, -z); } |
Pokitto | 0:398e251490fd | 67 | T length2() const { return x * x + y * y + z * z; } |
Pokitto | 0:398e251490fd | 68 | T length() const { return sqrt(length2()); } |
Pokitto | 0:398e251490fd | 69 | |
Pokitto | 0:398e251490fd | 70 | }; |
Pokitto | 0:398e251490fd | 71 | |
Pokitto | 0:398e251490fd | 72 | typedef Vec3<float> Vec3f; |
Pokitto | 0:398e251490fd | 73 | |
Pokitto | 0:398e251490fd | 74 | class Sphere |
Pokitto | 0:398e251490fd | 75 | { |
Pokitto | 0:398e251490fd | 76 | public: |
Pokitto | 0:398e251490fd | 77 | Vec3f center; /// position of the sphere |
Pokitto | 0:398e251490fd | 78 | float radius, radius2; /// sphere radius and radius^2 |
Pokitto | 0:398e251490fd | 79 | Vec3f surfaceColor, emissionColor; /// surface color and emission (light) |
Pokitto | 0:398e251490fd | 80 | float transparency, reflection; /// surface transparency and reflectivity |
Pokitto | 0:398e251490fd | 81 | Sphere( |
Pokitto | 0:398e251490fd | 82 | const Vec3f &c, |
Pokitto | 0:398e251490fd | 83 | const float &r, |
Pokitto | 0:398e251490fd | 84 | const Vec3f &sc, |
Pokitto | 0:398e251490fd | 85 | const float &refl = 0, |
Pokitto | 0:398e251490fd | 86 | const float &transp = 0, |
Pokitto | 0:398e251490fd | 87 | const Vec3f &ec = 0) : |
Pokitto | 0:398e251490fd | 88 | center(c), radius(r), radius2(r * r), surfaceColor(sc), emissionColor(ec), |
Pokitto | 0:398e251490fd | 89 | transparency(transp), reflection(refl) |
Pokitto | 0:398e251490fd | 90 | { /* empty */ } |
Pokitto | 0:398e251490fd | 91 | //[comment] |
Pokitto | 0:398e251490fd | 92 | // Compute a ray-sphere intersection using the geometric solution |
Pokitto | 0:398e251490fd | 93 | //[/comment] |
Pokitto | 0:398e251490fd | 94 | bool intersect(const Vec3f &rayorig, const Vec3f &raydir, float &t0, float &t1) const |
Pokitto | 0:398e251490fd | 95 | { |
Pokitto | 0:398e251490fd | 96 | Vec3f l = center - rayorig; |
Pokitto | 0:398e251490fd | 97 | float tca = l.dot(raydir); |
Pokitto | 0:398e251490fd | 98 | if (tca < 0) return false; |
Pokitto | 0:398e251490fd | 99 | float d2 = l.dot(l) - tca * tca; |
Pokitto | 0:398e251490fd | 100 | if (d2 > radius2) return false; |
Pokitto | 0:398e251490fd | 101 | float thc = sqrt(radius2 - d2); |
Pokitto | 0:398e251490fd | 102 | t0 = tca - thc; |
Pokitto | 0:398e251490fd | 103 | t1 = tca + thc; |
Pokitto | 0:398e251490fd | 104 | |
Pokitto | 0:398e251490fd | 105 | return true; |
Pokitto | 0:398e251490fd | 106 | } |
Pokitto | 0:398e251490fd | 107 | }; |
Pokitto | 0:398e251490fd | 108 | |
Pokitto | 0:398e251490fd | 109 | //[comment] |
Pokitto | 0:398e251490fd | 110 | // This variable controls the maximum recursion depth |
Pokitto | 0:398e251490fd | 111 | //[/comment] |
Pokitto | 0:398e251490fd | 112 | #define MAX_RAY_DEPTH 5 |
Pokitto | 0:398e251490fd | 113 | |
Pokitto | 0:398e251490fd | 114 | float mix(const float &a, const float &b, const float &mix) |
Pokitto | 0:398e251490fd | 115 | { |
Pokitto | 0:398e251490fd | 116 | return b * mix + a * (1 - mix); |
Pokitto | 0:398e251490fd | 117 | } |
Pokitto | 0:398e251490fd | 118 | |
Pokitto | 0:398e251490fd | 119 | //[comment] |
Pokitto | 0:398e251490fd | 120 | // This is the main trace function. It takes a ray as argument (defined by its origin |
Pokitto | 0:398e251490fd | 121 | // and direction). We test if this ray intersects any of the geometry in the scene. |
Pokitto | 0:398e251490fd | 122 | // If the ray intersects an object, we compute the intersection point, the normal |
Pokitto | 0:398e251490fd | 123 | // at the intersection point, and shade this point using this information. |
Pokitto | 0:398e251490fd | 124 | // Shading depends on the surface property (is it transparent, reflective, diffuse). |
Pokitto | 0:398e251490fd | 125 | // The function returns a color for the ray. If the ray intersects an object that |
Pokitto | 0:398e251490fd | 126 | // is the color of the object at the intersection point, otherwise it returns |
Pokitto | 0:398e251490fd | 127 | // the background color. |
Pokitto | 0:398e251490fd | 128 | //[/comment] |
Pokitto | 0:398e251490fd | 129 | Vec3f trace( |
Pokitto | 0:398e251490fd | 130 | const Vec3f &rayorig, |
Pokitto | 0:398e251490fd | 131 | const Vec3f &raydir, |
Pokitto | 0:398e251490fd | 132 | const std::vector<Sphere> &spheres, |
Pokitto | 0:398e251490fd | 133 | const int &depth) |
Pokitto | 0:398e251490fd | 134 | { |
Pokitto | 0:398e251490fd | 135 | //if (raydir.length() != 1) std::cerr << "Error " << raydir << std::endl; |
Pokitto | 0:398e251490fd | 136 | float tnear = INFINITY; |
Pokitto | 0:398e251490fd | 137 | const Sphere* sphere = NULL; |
Pokitto | 0:398e251490fd | 138 | // find intersection of this ray with the sphere in the scene |
Pokitto | 0:398e251490fd | 139 | for (unsigned i = 0; i < spheres.size(); ++i) { |
Pokitto | 0:398e251490fd | 140 | float t0 = INFINITY, t1 = INFINITY; |
Pokitto | 0:398e251490fd | 141 | if (spheres[i].intersect(rayorig, raydir, t0, t1)) { |
Pokitto | 0:398e251490fd | 142 | if (t0 < 0) t0 = t1; |
Pokitto | 0:398e251490fd | 143 | if (t0 < tnear) { |
Pokitto | 0:398e251490fd | 144 | tnear = t0; |
Pokitto | 0:398e251490fd | 145 | sphere = &spheres[i]; |
Pokitto | 0:398e251490fd | 146 | } |
Pokitto | 0:398e251490fd | 147 | } |
Pokitto | 0:398e251490fd | 148 | } |
Pokitto | 0:398e251490fd | 149 | // if there's no intersection return black or background color |
Pokitto | 0:398e251490fd | 150 | if (!sphere) return Vec3f(2); |
Pokitto | 0:398e251490fd | 151 | Vec3f surfaceColor = 0; // color of the ray/surfaceof the object intersected by the ray |
Pokitto | 0:398e251490fd | 152 | Vec3f phit = rayorig + raydir * tnear; // point of intersection |
Pokitto | 0:398e251490fd | 153 | Vec3f nhit = phit - sphere->center; // normal at the intersection point |
Pokitto | 0:398e251490fd | 154 | nhit.normalize(); // normalize normal direction |
Pokitto | 0:398e251490fd | 155 | // If the normal and the view direction are not opposite to each other |
Pokitto | 0:398e251490fd | 156 | // reverse the normal direction. That also means we are inside the sphere so set |
Pokitto | 0:398e251490fd | 157 | // the inside bool to true. Finally reverse the sign of IdotN which we want |
Pokitto | 0:398e251490fd | 158 | // positive. |
Pokitto | 0:398e251490fd | 159 | float bias = 1e-4; // add some bias to the point from which we will be tracing |
Pokitto | 0:398e251490fd | 160 | bool inside = false; |
Pokitto | 0:398e251490fd | 161 | if (raydir.dot(nhit) > 0) nhit = -nhit, inside = true; |
Pokitto | 0:398e251490fd | 162 | if ((sphere->transparency > 0 || sphere->reflection > 0) && depth < MAX_RAY_DEPTH) { |
Pokitto | 0:398e251490fd | 163 | float facingratio = -raydir.dot(nhit); |
Pokitto | 0:398e251490fd | 164 | // change the mix value to tweak the effect |
Pokitto | 0:398e251490fd | 165 | float fresneleffect = mix(pow(1 - facingratio, 3), 1, 0.1); |
Pokitto | 0:398e251490fd | 166 | // compute reflection direction (not need to normalize because all vectors |
Pokitto | 0:398e251490fd | 167 | // are already normalized) |
Pokitto | 0:398e251490fd | 168 | Vec3f refldir = raydir - nhit * 2 * raydir.dot(nhit); |
Pokitto | 0:398e251490fd | 169 | refldir.normalize(); |
Pokitto | 0:398e251490fd | 170 | Vec3f reflection = trace(phit + nhit * bias, refldir, spheres, depth + 1); |
Pokitto | 0:398e251490fd | 171 | Vec3f refraction = 0; |
Pokitto | 0:398e251490fd | 172 | // if the sphere is also transparent compute refraction ray (transmission) |
Pokitto | 0:398e251490fd | 173 | if (sphere->transparency) { |
Pokitto | 0:398e251490fd | 174 | float ior = 1.1, eta = (inside) ? ior : 1 / ior; // are we inside or outside the surface? |
Pokitto | 0:398e251490fd | 175 | float cosi = -nhit.dot(raydir); |
Pokitto | 0:398e251490fd | 176 | float k = 1 - eta * eta * (1 - cosi * cosi); |
Pokitto | 0:398e251490fd | 177 | Vec3f refrdir = raydir * eta + nhit * (eta * cosi - sqrt(k)); |
Pokitto | 0:398e251490fd | 178 | refrdir.normalize(); |
Pokitto | 0:398e251490fd | 179 | refraction = trace(phit - nhit * bias, refrdir, spheres, depth + 1); |
Pokitto | 0:398e251490fd | 180 | } |
Pokitto | 0:398e251490fd | 181 | // the result is a mix of reflection and refraction (if the sphere is transparent) |
Pokitto | 0:398e251490fd | 182 | surfaceColor = ( |
Pokitto | 0:398e251490fd | 183 | reflection * fresneleffect + |
Pokitto | 0:398e251490fd | 184 | refraction * (1 - fresneleffect) * sphere->transparency) * sphere->surfaceColor; |
Pokitto | 0:398e251490fd | 185 | } |
Pokitto | 0:398e251490fd | 186 | else { |
Pokitto | 0:398e251490fd | 187 | // it's a diffuse object, no need to raytrace any further |
Pokitto | 0:398e251490fd | 188 | for (unsigned i = 0; i < spheres.size(); ++i) { |
Pokitto | 0:398e251490fd | 189 | if (spheres[i].emissionColor.x > 0) { |
Pokitto | 0:398e251490fd | 190 | // this is a light |
Pokitto | 0:398e251490fd | 191 | Vec3f transmission = 1; |
Pokitto | 0:398e251490fd | 192 | Vec3f lightDirection = spheres[i].center - phit; |
Pokitto | 0:398e251490fd | 193 | lightDirection.normalize(); |
Pokitto | 0:398e251490fd | 194 | for (unsigned j = 0; j < spheres.size(); ++j) { |
Pokitto | 0:398e251490fd | 195 | if (i != j) { |
Pokitto | 0:398e251490fd | 196 | float t0, t1; |
Pokitto | 0:398e251490fd | 197 | if (spheres[j].intersect(phit + nhit * bias, lightDirection, t0, t1)) { |
Pokitto | 0:398e251490fd | 198 | transmission = 0; |
Pokitto | 0:398e251490fd | 199 | break; |
Pokitto | 0:398e251490fd | 200 | } |
Pokitto | 0:398e251490fd | 201 | } |
Pokitto | 0:398e251490fd | 202 | } |
Pokitto | 0:398e251490fd | 203 | surfaceColor += sphere->surfaceColor * transmission * |
Pokitto | 0:398e251490fd | 204 | std::max(float(0), nhit.dot(lightDirection)) * spheres[i].emissionColor; |
Pokitto | 0:398e251490fd | 205 | } |
Pokitto | 0:398e251490fd | 206 | } |
Pokitto | 0:398e251490fd | 207 | } |
Pokitto | 0:398e251490fd | 208 | |
Pokitto | 0:398e251490fd | 209 | return surfaceColor + sphere->emissionColor; |
Pokitto | 0:398e251490fd | 210 | } |
Pokitto | 0:398e251490fd | 211 | |
Pokitto | 0:398e251490fd | 212 | //[comment] |
Pokitto | 0:398e251490fd | 213 | // Main rendering function. We compute a camera ray for each pixel of the image |
Pokitto | 0:398e251490fd | 214 | // trace it and return a color. If the ray hits a sphere, we return the color of the |
Pokitto | 0:398e251490fd | 215 | // sphere at the intersection point, else we return the background color. |
Pokitto | 0:398e251490fd | 216 | //[/comment] |
Pokitto | 0:398e251490fd | 217 | void render(const std::vector<Sphere> &spheres, int rscale) |
Pokitto | 0:398e251490fd | 218 | { |
Pokitto | 0:398e251490fd | 219 | unsigned width = 220, height = 176; |
Pokitto | 0:398e251490fd | 220 | //Vec3f *image = new Vec3f[width * height], *pixel = image; |
Pokitto | 0:398e251490fd | 221 | Vec3f pixel; //jonne |
Pokitto | 0:398e251490fd | 222 | float invWidth = 1 / float(width), invHeight = 1 / float(height); |
Pokitto | 0:398e251490fd | 223 | float fov = 30, aspectratio = width / float(height); |
Pokitto | 0:398e251490fd | 224 | float angle = tan(M_PI * 0.5 * fov / 180.); |
Pokitto | 0:398e251490fd | 225 | // Trace rays |
Pokitto | 0:398e251490fd | 226 | for (unsigned y = 1; y < height+1; y+=rscale) { |
Pokitto | 0:398e251490fd | 227 | for (unsigned x = 1; x < width+1; x+=rscale) { //, ++pixel) { |
Pokitto | 0:398e251490fd | 228 | float xx = (2 * ((x + 0.5*rscale) * invWidth) - 1) * angle * aspectratio; |
Pokitto | 0:398e251490fd | 229 | float yy = (1 - 2 * ((y + 0.5*rscale) * invHeight)) * angle; |
Pokitto | 0:398e251490fd | 230 | Vec3f raydir(xx, yy, -1); |
Pokitto | 0:398e251490fd | 231 | raydir.normalize(); |
Pokitto | 0:398e251490fd | 232 | //*pixel = trace(Vec3f(0), raydir, spheres, 0); |
Pokitto | 0:398e251490fd | 233 | pixel = trace(Vec3f(0), raydir, spheres, 0); |
Pokitto | 0:398e251490fd | 234 | //g.display.directPixel(x,y,g.display.RGBto565(pixel.x*255,pixel.y*255,pixel.z*255)); |
Pokitto | 0:398e251490fd | 235 | g.display.directRectangle(x,y,x+rscale,y+rscale,g.display.RGBto565(pixel.x*255,pixel.y*255,pixel.z*255)); |
Pokitto | 0:398e251490fd | 236 | //g.wait(100); |
Pokitto | 0:398e251490fd | 237 | } |
Pokitto | 0:398e251490fd | 238 | } |
Pokitto | 0:398e251490fd | 239 | // Save result to a PPM image (keep these flags if you compile under Windows) |
Pokitto | 0:398e251490fd | 240 | /*std::ofstream ofs("./untitled.ppm", std::ios::out | std::ios::binary); |
Pokitto | 0:398e251490fd | 241 | ofs << "P6\n" << width << " " << height << "\n255\n"; |
Pokitto | 0:398e251490fd | 242 | for (unsigned i = 0; i < width * height; ++i) { |
Pokitto | 0:398e251490fd | 243 | ofs << (unsigned char)(std::min(float(1), image[i].x) * 255) << |
Pokitto | 0:398e251490fd | 244 | (unsigned char)(std::min(float(1), image[i].y) * 255) << |
Pokitto | 0:398e251490fd | 245 | (unsigned char)(std::min(float(1), image[i].z) * 255); |
Pokitto | 0:398e251490fd | 246 | } |
Pokitto | 0:398e251490fd | 247 | ofs.close();*/ |
Pokitto | 0:398e251490fd | 248 | //delete [] image; |
Pokitto | 0:398e251490fd | 249 | } |
Pokitto | 0:398e251490fd | 250 | |
Pokitto | 0:398e251490fd | 251 | //[comment] |
Pokitto | 0:398e251490fd | 252 | // In the main function, we will create the scene which is composed of 5 spheres |
Pokitto | 0:398e251490fd | 253 | // and 1 light (which is also a sphere). Then, once the scene description is complete |
Pokitto | 0:398e251490fd | 254 | // we render that scene, by calling the render() function. |
Pokitto | 0:398e251490fd | 255 | //[/comment] |
Pokitto | 0:398e251490fd | 256 | int main() |
Pokitto | 0:398e251490fd | 257 | { |
Pokitto | 0:398e251490fd | 258 | g.begin(); |
Pokitto | 0:398e251490fd | 259 | //srand48(13); |
Pokitto | 0:398e251490fd | 260 | std::vector<Sphere> spheres; |
Pokitto | 0:398e251490fd | 261 | // position, radius, surface color, reflectivity, transparency, emission color |
Pokitto | 0:398e251490fd | 262 | spheres.push_back(Sphere(Vec3f( 0.0, -10004, -20), 10000, Vec3f(0.20, 0.20, 0.20), 0, 0.0)); |
Pokitto | 0:398e251490fd | 263 | spheres.push_back(Sphere(Vec3f( 0.0, 0, -20), 4, Vec3f(0.32, 1.00, 0.16), 1, 0.5)); //green middle sphere |
Pokitto | 0:398e251490fd | 264 | spheres.push_back(Sphere(Vec3f( 5.0, -1, -15), 2, Vec3f(1.00, 0.16, 1.00), 1, 0.5)); //magenta |
Pokitto | 0:398e251490fd | 265 | spheres.push_back(Sphere(Vec3f( 5.0, 0, -25), 3, Vec3f(0.36, 0.16, 0.97), 1, 0.5)); //blue |
Pokitto | 0:398e251490fd | 266 | spheres.push_back(Sphere(Vec3f(-5.5, 0, -15), 3, Vec3f(1.00, 0.65, 0.30), 1, 0.5)); //orange |
Pokitto | 0:398e251490fd | 267 | // light |
Pokitto | 0:398e251490fd | 268 | spheres.push_back(Sphere(Vec3f( 0.0, 20, -30), 3, Vec3f(0.00, 0.00, 0.00), 0, 0.0, Vec3f(3))); |
Pokitto | 0:398e251490fd | 269 | render(spheres,32); |
Pokitto | 0:398e251490fd | 270 | render(spheres,16); |
Pokitto | 0:398e251490fd | 271 | render(spheres,8); |
Pokitto | 0:398e251490fd | 272 | render(spheres,4); |
Pokitto | 0:398e251490fd | 273 | render(spheres,2); |
Pokitto | 0:398e251490fd | 274 | render(spheres,1); |
Pokitto | 0:398e251490fd | 275 | while (g.isRunning()) { |
Pokitto | 0:398e251490fd | 276 | if(g.update(true)) { |
Pokitto | 0:398e251490fd | 277 | |
Pokitto | 0:398e251490fd | 278 | } |
Pokitto | 0:398e251490fd | 279 | } |
Pokitto | 0:398e251490fd | 280 | return 0; |
Pokitto | 0:398e251490fd | 281 | } |