rayzor
changeset 17:79609d482762
the renderer renders, also fixed an unnoticed matrix conversion problem between scenegraph and min3d
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 14 Apr 2014 07:34:45 +0300 |
parents | 4d87b0aafbb0 |
children | 859ccadca671 |
files | Makefile src/camera.cc src/camera.h src/light.cc src/light.h src/main.cc src/material.h src/min3d.c src/min3d.h src/modeller.cc src/object.cc src/object.h src/raytrace.cc src/raytrace.h src/renderer.cc src/renderer.h src/scancode.h src/scene.cc src/scene.h src/screen.cc src/screen.h src/snode.cc src/snode.h src/vmath.cc src/vmath.h src/vmathmat.h |
diffstat | 26 files changed, 477 insertions(+), 56 deletions(-) [+] |
line diff
1.1 --- a/Makefile Sun Apr 13 09:54:51 2014 +0300 1.2 +++ b/Makefile Mon Apr 14 07:34:45 2014 +0300 1.3 @@ -1,6 +1,6 @@ 1.4 baseobj = main.obj logger.obj screen.obj scrman.obj swapbuf.obj rbtree.obj 1.5 modelobj = modeller.obj min3d.obj m3drast.obj lines.obj 1.6 -rendobj = renderer.obj vmath.obj 1.7 +rendobj = renderer.obj vmath.obj raytrace.obj 1.8 scnobj = scene.obj object.obj light.obj camera.obj snode.obj 1.9 sysobj = gfx.obj vbe.obj dpmi.obj timer.obj mouse.obj keyb.obj 1.10 obj = $(baseobj) $(modelobj) $(rendobj) $(scnobj) $(sysobj)
2.1 --- a/src/camera.cc Sun Apr 13 09:54:51 2014 +0300 2.2 +++ b/src/camera.cc Mon Apr 14 07:34:45 2014 +0300 2.3 @@ -41,7 +41,7 @@ 2.4 { 2.5 } 2.6 2.7 -bool Camera::intersect(const Ray &ray, float *dist) const 2.8 +bool Camera::intersect(const Ray &ray, RayHit *hit) const 2.9 { 2.10 return false; 2.11 }
3.1 --- a/src/camera.h Sun Apr 13 09:54:51 2014 +0300 3.2 +++ b/src/camera.h Mon Apr 14 07:34:45 2014 +0300 3.3 @@ -22,7 +22,7 @@ 3.4 3.5 void draw() const; 3.6 3.7 - bool intersect(const Ray &ray, float *dist = 0) const; 3.8 + bool intersect(const Ray &ray, RayHit *hit = 0) const; 3.9 3.10 Ray get_primary_ray(int x, int y) const; 3.11 };
4.1 --- a/src/light.cc Sun Apr 13 09:54:51 2014 +0300 4.2 +++ b/src/light.cc Mon Apr 14 07:34:45 2014 +0300 4.3 @@ -3,12 +3,23 @@ 4.4 Light::Light() 4.5 { 4.6 type = NODE_LIGHT; 4.7 + intens = 1.0; 4.8 color.x = color.y = color.z = 1.0; 4.9 atten.x = 1.0; 4.10 atten.y = 0.0; 4.11 atten.z = 0.0; 4.12 } 4.13 4.14 +void Light::set_intensity(float val) 4.15 +{ 4.16 + intens = val; 4.17 +} 4.18 + 4.19 +float Light::get_intensity() const 4.20 +{ 4.21 + return intens; 4.22 +} 4.23 + 4.24 void Light::set_color(const Vector3 &color) 4.25 { 4.26 this->color = color; 4.27 @@ -19,6 +30,11 @@ 4.28 return color; 4.29 } 4.30 4.31 +Vector3 Light::get_color(const Vector3 &pt) const 4.32 +{ 4.33 + float d = (get_position() - pt).length(); 4.34 + return color * calc_attenuation(d) * intens; 4.35 +} 4.36 4.37 void Light::set_attenuation(const Vector3 &atten) 4.38 { 4.39 @@ -30,11 +46,18 @@ 4.40 return atten; 4.41 } 4.42 4.43 +float Light::calc_attenuation(float d) const 4.44 +{ 4.45 + float denom = atten.x + atten.y * d + atten.z * d * d; 4.46 + float at = denom == 0.0 ? 1.0 : 1.0 / denom; 4.47 + return at > 1.0 ? 1.0 : at; 4.48 +} 4.49 + 4.50 void Light::draw() const 4.51 { 4.52 } 4.53 4.54 -bool Light::intersect(const Ray &ray, float *dist) 4.55 +bool Light::intersect(const Ray &ray, RayHit *hit) const 4.56 { 4.57 - return false; 4.58 + return false; // TODO 4.59 }
5.1 --- a/src/light.h Sun Apr 13 09:54:51 2014 +0300 5.2 +++ b/src/light.h Mon Apr 14 07:34:45 2014 +0300 5.3 @@ -6,21 +6,30 @@ 5.4 5.5 class Light : public SceneNode { 5.6 private: 5.7 + float intens; 5.8 Vector3 color; 5.9 Vector3 atten; 5.10 5.11 public: 5.12 Light(); 5.13 5.14 + void set_intensity(float val); 5.15 + float get_intensity() const; 5.16 + 5.17 void set_color(const Vector3 &color); 5.18 const Vector3 &get_color() const; 5.19 5.20 + // includes attenuation and intensity 5.21 + Vector3 get_color(const Vector3 &pt) const; 5.22 + 5.23 void set_attenuation(const Vector3 &atten); 5.24 const Vector3 &get_attenuation() const; 5.25 5.26 + float calc_attenuation(float d) const; 5.27 + 5.28 void draw() const; 5.29 5.30 - bool intersect(const Ray &ray, float *dist); 5.31 + bool intersect(const Ray &ray, RayHit *hit = 0) const; 5.32 }; 5.33 5.34 #endif // LIGHT_H_
6.1 --- a/src/main.cc Sun Apr 13 09:54:51 2014 +0300 6.2 +++ b/src/main.cc Mon Apr 14 07:34:45 2014 +0300 6.3 @@ -3,6 +3,7 @@ 6.4 #include <string.h> 6.5 #include <signal.h> 6.6 #include <errno.h> 6.7 +#include <float.h> 6.8 #include <direct.h> 6.9 #include "inttypes.h" 6.10 #include "gfx.h" 6.11 @@ -102,6 +103,9 @@ 6.12 signal(SIGILL, sig); 6.13 signal(SIGFPE, sig); 6.14 6.15 + // mask all fpe except invalid op 6.16 + _control87(~_EM_INVALID, _MCW_EM); 6.17 + 6.18 init_timer(128); 6.19 6.20 if(!novideo) { 6.21 @@ -144,11 +148,21 @@ 6.22 scene = new Scene; 6.23 6.24 Sphere *sph = new Sphere; 6.25 + sph->mtl.diffuse = Vector3(1.0, 0.3, 0.1); 6.26 + sph->mtl.roughness = 0.4; 6.27 scene->add(sph); 6.28 6.29 Box *box = new Box; 6.30 + box->mtl.diffuse = Vector3(0.1, 0.4, 1.0); 6.31 + box->mtl.roughness = 0.9; 6.32 + box->set_position(Vector3(0, -1.1, 0)); 6.33 + box->set_scaling(Vector3(4, 0.1, 4)); 6.34 scene->add(box); 6.35 - box->set_scaling(Vector3(2, 0.25, 2)); 6.36 + 6.37 + Light *lt = new Light; 6.38 + lt->set_intensity(0.8); 6.39 + lt->set_position(Vector3(-10, 10, 10)); 6.40 + scene->add(lt); 6.41 6.42 Modeller *modeller = new Modeller; 6.43 if(!modeller->init()) { 6.44 @@ -322,7 +336,7 @@ 6.45 return; 6.46 } 6.47 6.48 - fprintf(fp, "P6\n" PPM_COMMENT "\n%d %d\n255\n", fb_width, fb_height); 6.49 + fprintf(fp, "P6\n# " PPM_COMMENT "\n%d %d\n255\n", fb_width, fb_height); 6.50 for(int i=0; i<fb_width * fb_height; i++) { 6.51 uint32_t c = fb_pixels[i]; 6.52 fputc(UNPACK_RED(c), fp); 6.53 @@ -353,7 +367,6 @@ 6.54 } 6.55 break; 6.56 6.57 - case KB_SYSRQ: 6.58 case KB_F12: 6.59 cap_shot = true; 6.60 break; 6.61 @@ -467,5 +480,11 @@ 6.62 { 6.63 cleanup(); 6.64 fprintf(stderr, "signal caught: %d\n", s); 6.65 + 6.66 + if(s == SIGFPE) { 6.67 + unsigned int st = _status87(); 6.68 + fprintf(stderr, "fpu status: %x\n", st); 6.69 + } 6.70 + 6.71 exit(1); 6.72 }
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/material.h Mon Apr 14 07:34:45 2014 +0300 7.3 @@ -0,0 +1,22 @@ 7.4 +#ifndef MATERIAL_H_ 7.5 +#define MATERIAL_H_ 7.6 + 7.7 +#include "vmath.h" 7.8 + 7.9 +class Material { 7.10 +public: 7.11 + Vector3 diffuse, specular; 7.12 + float roughness; 7.13 + float reflect, refract; 7.14 + float ior; 7.15 + 7.16 + Material() 7.17 + : diffuse(0.75, 0.75, 0.75), specular(1, 1, 1) 7.18 + { 7.19 + roughness = 1.0; 7.20 + reflect = refract = 0.0; 7.21 + ior = 1.0; 7.22 + } 7.23 +}; 7.24 + 7.25 +#endif // MATERIAL_H_
8.1 --- a/src/min3d.c Sun Apr 13 09:54:51 2014 +0300 8.2 +++ b/src/min3d.c Mon Apr 14 07:34:45 2014 +0300 8.3 @@ -126,6 +126,19 @@ 8.4 memcpy(m3dctx->mstack[m3dctx->mmode].m[top], m, 16 * sizeof *m); 8.5 } 8.6 8.7 +void m3d_load_transpose_matrix(const float *m) 8.8 +{ 8.9 + int i, j, lin = 0; 8.10 + int top = m3dctx->mstack[m3dctx->mmode].top; 8.11 + float *dest = m3dctx->mstack[m3dctx->mmode].m[top]; 8.12 + 8.13 + for(i=0; i<4; i++) { 8.14 + for(j=0; j<4; j++) { 8.15 + *dest++ = m[j * 4 + i]; 8.16 + } 8.17 + } 8.18 +} 8.19 + 8.20 #define M(i,j) (((i) << 2) + (j)) 8.21 void m3d_mult_matrix(const float *m2) 8.22 { 8.23 @@ -137,7 +150,7 @@ 8.24 8.25 for(i=0; i<4; i++) { 8.26 for(j=0; j<4; j++) { 8.27 - dest[M(i,j)] = m1[M(0,j)] * m2[M(i,0)] + 8.28 + *dest++ = m1[M(0,j)] * m2[M(i,0)] + 8.29 m1[M(1,j)] * m2[M(i,1)] + 8.30 m1[M(2,j)] * m2[M(i,2)] + 8.31 m1[M(3,j)] * m2[M(i,3)]; 8.32 @@ -145,6 +158,24 @@ 8.33 } 8.34 } 8.35 8.36 +void m3d_mult_transpose_matrix(const float *m2) 8.37 +{ 8.38 + int i, j, top = m3dctx->mstack[m3dctx->mmode].top; 8.39 + float m1[16]; 8.40 + float *dest = m3dctx->mstack[m3dctx->mmode].m[top]; 8.41 + 8.42 + memcpy(m1, dest, sizeof m1); 8.43 + 8.44 + for(i=0; i<4; i++) { 8.45 + for(j=0; j<4; j++) { 8.46 + *dest++ = m1[M(0,j)] * m2[M(0,i)] + 8.47 + m1[M(1,j)] * m2[M(1,i)] + 8.48 + m1[M(2,j)] * m2[M(2,i)] + 8.49 + m1[M(3,j)] * m2[M(3,i)]; 8.50 + } 8.51 + } 8.52 +} 8.53 + 8.54 void m3d_translate(float x, float y, float z) 8.55 { 8.56 float m[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
9.1 --- a/src/min3d.h Sun Apr 13 09:54:51 2014 +0300 9.2 +++ b/src/min3d.h Mon Apr 14 07:34:45 2014 +0300 9.3 @@ -61,7 +61,9 @@ 9.4 void m3d_pop_matrix(void); 9.5 void m3d_load_identity(void); 9.6 void m3d_load_matrix(const float *m); 9.7 +void m3d_load_transpose_matrix(const float *m); 9.8 void m3d_mult_matrix(const float *m); 9.9 +void m3d_mult_transpose_matrix(const float *m); 9.10 void m3d_translate(float x, float y, float z); 9.11 void m3d_rotate(float angle, float x, float y, float z); 9.12 void m3d_scale(float x, float y, float z);
10.1 --- a/src/modeller.cc Sun Apr 13 09:54:51 2014 +0300 10.2 +++ b/src/modeller.cc Mon Apr 14 07:34:45 2014 +0300 10.3 @@ -11,7 +11,7 @@ 10.4 10.5 struct ModellerImpl { 10.6 int mx, my; 10.7 - float cam_theta, cam_phi, cam_dist; 10.8 + float cam_theta, cam_phi, cam_dist, cam_fov; 10.9 Camera *viewport_cam; 10.10 10.11 struct m3d_image rbuf; 10.12 @@ -41,6 +41,7 @@ 10.13 10.14 mod->cam_phi = 25; 10.15 mod->cam_dist = 5; 10.16 + mod->cam_fov = 50.0; 10.17 10.18 m3d_init(); 10.19 mod->rbuf.pixels = fb_pixels; 10.20 @@ -50,7 +51,7 @@ 10.21 10.22 m3d_matrix_mode(M3D_PROJECTION); 10.23 m3d_load_identity(); 10.24 - m3d_perspective(50.0, (float)fb_width / (float)fb_height, 0.5, 500.0); 10.25 + m3d_perspective(mod->cam_fov, (float)fb_width / (float)fb_height, 0.5, 500.0); 10.26 10.27 m3d_enable(M3D_CULL_FACE); 10.28 return true; 10.29 @@ -155,11 +156,14 @@ 10.30 scene->set_active_camera(mod->viewport_cam); 10.31 } 10.32 Vector3 dir; 10.33 - dir.x = sin(DEG2RAD(mod->cam_theta)) * cos(DEG2RAD(mod->cam_phi)) * mod->cam_dist; 10.34 - dir.y = sin(DEG2RAD(mod->cam_phi)); 10.35 - dir.z = cos(DEG2RAD(mod->cam_theta)) * cos(DEG2RAD(mod->cam_phi)) * mod->cam_dist; 10.36 + float theta = -DEG2RAD(mod->cam_theta); 10.37 + float phi = DEG2RAD(mod->cam_phi); 10.38 + dir.x = sin(theta) * cos(phi) * mod->cam_dist; 10.39 + dir.y = sin(phi) * mod->cam_dist; 10.40 + dir.z = cos(theta) * cos(phi) * mod->cam_dist; 10.41 mod->viewport_cam->set_position(dir); 10.42 mod->viewport_cam->set_target(Vector3(0, 0, 0)); 10.43 + mod->viewport_cam->set_fov(DEG2RAD(mod->cam_fov)); 10.44 10.45 rs->message(message_atom("start")); 10.46 }
11.1 --- a/src/object.cc Sun Apr 13 09:54:51 2014 +0300 11.2 +++ b/src/object.cc Mon Apr 14 07:34:45 2014 +0300 11.3 @@ -13,6 +13,11 @@ 11.4 { 11.5 } 11.6 11.7 +Vector3 Object::hit_normal(const RayHit &hit) const 11.8 +{ 11.9 + return Vector3(0, 0, 0); 11.10 +} 11.11 + 11.12 // ---- sphere ---- 11.13 Sphere::Sphere() 11.14 { 11.15 @@ -83,7 +88,7 @@ 11.16 post_draw(); 11.17 } 11.18 11.19 -bool Sphere::intersect(const Ray &wray, float *dist) const 11.20 +bool Sphere::intersect(const Ray &wray, RayHit *hit) const 11.21 { 11.22 Ray ray = transform(get_inv_matrix(), wray); 11.23 11.24 @@ -111,10 +116,21 @@ 11.25 if(t < 1e-4) 11.26 return false; 11.27 11.28 - if(dist) *dist = t; 11.29 + if(hit) { 11.30 + hit->ray = wray; 11.31 + hit->lray = ray; 11.32 + hit->dist = t; 11.33 + hit->obj = this; 11.34 + hit->subobj = 0; 11.35 + } 11.36 return true; 11.37 } 11.38 11.39 +Vector3 Sphere::hit_normal(const RayHit &hit) const 11.40 +{ 11.41 + return hit.lray.origin + hit.lray.dir * hit.dist; 11.42 +} 11.43 + 11.44 // ---- box ---- 11.45 11.46 Box::Box() 11.47 @@ -165,7 +181,57 @@ 11.48 post_draw(); 11.49 } 11.50 11.51 -bool Box::intersect(const Ray &ray, float *dist) const 11.52 +bool Box::intersect(const Ray &wray, RayHit *hit) const 11.53 { 11.54 - return false; // TODO 11.55 + Ray ray = transform(get_inv_matrix(), wray); 11.56 + 11.57 + Vector3 param[2] = { Vector3(-1, -1, -1), Vector3(1, 1, 1) }; 11.58 + Vector3 inv_dir(1.0 / ray.dir.x, 1.0 / ray.dir.y, 1.0 / ray.dir.z); 11.59 + int sign[3] = {inv_dir.x < 0, inv_dir.y < 0, inv_dir.z < 0}; 11.60 + 11.61 + float tmin = (param[sign[0]].x - ray.origin.x) * inv_dir.x; 11.62 + float tmax = (param[1 - sign[0]].x - ray.origin.x) * inv_dir.x; 11.63 + float tymin = (param[sign[1]].y - ray.origin.y) * inv_dir.y; 11.64 + float tymax = (param[1 - sign[1]].y - ray.origin.y) * inv_dir.y; 11.65 + 11.66 + if(tmin > tymax || tymin > tmax) { 11.67 + return false; 11.68 + } 11.69 + if(tymin > tmin) tmin = tymin; 11.70 + if(tymax < tmax) tmax = tymax; 11.71 + 11.72 + float tzmin = (param[sign[2]].z - ray.origin.z) * inv_dir.z; 11.73 + float tzmax = (param[1 - sign[2]].z - ray.origin.z) * inv_dir.z; 11.74 + 11.75 + if(tmin > tzmax || tzmin > tmax) { 11.76 + return false; 11.77 + } 11.78 + if(tzmin > tmin) tmin = tzmin; 11.79 + if(tzmax < tmax) tmax = tzmax; 11.80 + 11.81 + float t = tmin < 1e-4 ? tmax : tmin; 11.82 + if(t >= 1e-4) { 11.83 + if(hit) { 11.84 + hit->dist = t; 11.85 + hit->ray = wray; 11.86 + hit->lray = ray; 11.87 + hit->obj = this; 11.88 + hit->subobj = 0; 11.89 + } 11.90 + return true; 11.91 + } 11.92 + return false; 11.93 } 11.94 + 11.95 +Vector3 Box::hit_normal(const RayHit &hit) const 11.96 +{ 11.97 + Vector3 lpt = hit.lray.origin + hit.lray.dir * hit.dist; 11.98 + 11.99 + if(fabs(lpt.x) > fabs(lpt.y) && fabs(lpt.x) > fabs(lpt.z)) { 11.100 + return Vector3(lpt.x, 0, 0); 11.101 + } 11.102 + if(fabs(lpt.y) > fabs(lpt.z)) { 11.103 + return Vector3(0, lpt.y, 0); 11.104 + } 11.105 + return Vector3(0, 0, lpt.z); 11.106 +}
12.1 --- a/src/object.h Sun Apr 13 09:54:51 2014 +0300 12.2 +++ b/src/object.h Mon Apr 14 07:34:45 2014 +0300 12.3 @@ -3,11 +3,16 @@ 12.4 12.5 #include "vmath.h" 12.6 #include "snode.h" 12.7 +#include "material.h" 12.8 12.9 class Object : public SceneNode { 12.10 public: 12.11 + Material mtl; 12.12 + 12.13 Object(); 12.14 virtual ~Object(); 12.15 + 12.16 + virtual Vector3 hit_normal(const RayHit &hit) const; 12.17 }; 12.18 12.19 class Sphere : public Object { 12.20 @@ -17,7 +22,8 @@ 12.21 12.22 void draw(bool emph = false) const; 12.23 12.24 - bool intersect(const Ray &ray, float *dist = 0) const; 12.25 + bool intersect(const Ray &ray, RayHit *hit = 0) const; 12.26 + Vector3 hit_normal(const RayHit &hit) const; 12.27 }; 12.28 12.29 class Box : public Object { 12.30 @@ -27,7 +33,8 @@ 12.31 12.32 void draw(bool emph = false) const; 12.33 12.34 - bool intersect(const Ray &ray, float *dist = 0) const; 12.35 + bool intersect(const Ray &ray, RayHit *hit = 0) const; 12.36 + Vector3 hit_normal(const RayHit &hit) const; 12.37 }; 12.38 12.39 #endif // OBJECT_H_
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/src/raytrace.cc Mon Apr 14 07:34:45 2014 +0300 13.3 @@ -0,0 +1,58 @@ 13.4 +#include <assert.h> 13.5 +#include <float.h> 13.6 +#include "raytrace.h" 13.7 +#include "rayzor.h" 13.8 +#include "scene.h" 13.9 +#include "logger.h" 13.10 + 13.11 +Vector3 ray_trace(const Ray &ray, int iter) 13.12 +{ 13.13 + RayHit hit; 13.14 + if(!scene->intersect(ray, &hit)) { 13.15 + return scene->get_background(ray); 13.16 + } 13.17 + 13.18 + return shade(hit, iter); 13.19 +} 13.20 + 13.21 +static inline float positive(float x) 13.22 +{ 13.23 + return x < 0.0f ? 0.0f : x; 13.24 +} 13.25 + 13.26 +Vector3 shade(const RayHit &hit, int iter) 13.27 +{ 13.28 + Vector3 pos = hit.ray.origin + hit.ray.dir * hit.dist; 13.29 + Vector3 norm = hit.obj->hit_normal(hit); 13.30 + norm = normalize(transform(normal_matrix(hit.obj->get_matrix()), norm)); 13.31 + Vector3 vdir = -normalize(hit.ray.dir); 13.32 + 13.33 + Vector3 color = scene->get_ambient(); 13.34 + 13.35 + const Vector3 &kd = hit.obj->mtl.diffuse; 13.36 + const Vector3 &ks = hit.obj->mtl.specular; 13.37 + float roughness = hit.obj->mtl.roughness; 13.38 + 13.39 + int num_lights = scene->get_light_count(); 13.40 + for(int i=0; i<num_lights; i++) { 13.41 + const Light *lt = scene->get_light(i); 13.42 + Vector3 ldir = lt->get_position() - pos; 13.43 + Vector3 lcol = lt->get_color(pos); 13.44 + 13.45 + RayHit hit; 13.46 + if(!scene->intersect(Ray(pos, ldir), &hit) || hit.dist > 1.0) { 13.47 + // if we can see the light, calculate and add its contribution 13.48 + ldir.normalize(); 13.49 + float ndotl = positive(dot(norm, ldir)); 13.50 + Vector3 diffuse = kd * lcol * ndotl; 13.51 + 13.52 + Vector3 hdir = normalize(ldir + vdir); 13.53 + float ndoth = positive(dot(norm, hdir)); 13.54 + Vector3 specular = ks * lcol * pow(ndoth, roughness * 128.0); 13.55 + 13.56 + color = color + lerp(specular, diffuse, roughness); 13.57 + } 13.58 + } 13.59 + 13.60 + return color; 13.61 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/src/raytrace.h Mon Apr 14 07:34:45 2014 +0300 14.3 @@ -0,0 +1,20 @@ 14.4 +#ifndef RAYTRACE_H_ 14.5 +#define RAYTRACE_H_ 14.6 + 14.7 +#include "vmath.h" 14.8 +#include "vmathray.h" 14.9 + 14.10 +class Object; 14.11 + 14.12 +struct RayHit { 14.13 + Ray ray; // the ray in world coordinates 14.14 + Ray lray; // the local coordinate system ray 14.15 + float dist; // parametric distance along the ray 14.16 + const Object *obj; // pointer to the object that has been hit 14.17 + const void *subobj; // object-specific subobject pointer (can be null). 14.18 +}; 14.19 + 14.20 +Vector3 ray_trace(const Ray &ray, int iter = 0); 14.21 +Vector3 shade(const RayHit &hit, int iter); 14.22 + 14.23 +#endif // RAYTRACE_H_
15.1 --- a/src/renderer.cc Sun Apr 13 09:54:51 2014 +0300 15.2 +++ b/src/renderer.cc Mon Apr 14 07:34:45 2014 +0300 15.3 @@ -1,4 +1,5 @@ 15.4 #include <string.h> 15.5 +#include <stdarg.h> 15.6 #include "renderer.h" 15.7 #include "rayzor.h" 15.8 #include "scene.h" 15.9 @@ -6,6 +7,15 @@ 15.10 #include "scrman.h" 15.11 #include "timer.h" 15.12 #include "logger.h" 15.13 +#include "raytrace.h" 15.14 + 15.15 +enum { 15.16 + MSG_START, 15.17 + MSG_GAMMA, 15.18 + MSG_USE_GAMMA, 15.19 + 15.20 + NUM_MESSAGES 15.21 +}; 15.22 15.23 struct RendererImpl { 15.24 bool in_progress; 15.25 @@ -13,14 +23,13 @@ 15.26 15.27 uint32_t *pixels; 15.28 15.29 - MsgAtom msg_start; 15.30 + float gamma, inv_gamma; 15.31 + bool use_gamma; 15.32 + 15.33 + MsgAtom msg[NUM_MESSAGES]; 15.34 }; 15.35 15.36 15.37 -static Vector3 ray_trace(const Ray &ray, int iter = 0); 15.38 -static Vector3 shade(const Ray &ray, float t, int iter); 15.39 - 15.40 - 15.41 Renderer::Renderer() 15.42 { 15.43 set_name("renderer"); 15.44 @@ -37,7 +46,13 @@ 15.45 } 15.46 memset(rend->pixels, 0, fb_width * fb_height * 4); 15.47 15.48 - rend->msg_start = message_atom("start"); 15.49 + rend->gamma = 1.8; 15.50 + rend->inv_gamma = 1.0 / rend->gamma; 15.51 + rend->use_gamma = true; 15.52 + 15.53 + rend->msg[MSG_START] = message_atom("start"); 15.54 + rend->msg[MSG_GAMMA] = message_atom("gamma"); 15.55 + rend->msg[MSG_USE_GAMMA] = message_atom("use-gamma"); 15.56 15.57 return true; 15.58 } 15.59 @@ -69,6 +84,13 @@ 15.60 Ray ray = cam->get_primary_ray(rend->cur_x, rend->cur_y); 15.61 Vector3 color = ray_trace(ray); 15.62 15.63 + // gamma-correct before storing the pixel 15.64 + if(rend->use_gamma) { 15.65 + color.x = pow(color.x, rend->inv_gamma); 15.66 + color.y = pow(color.y, rend->inv_gamma); 15.67 + color.z = pow(color.z, rend->inv_gamma); 15.68 + } 15.69 + 15.70 int r = color.x > 1.0 ? 255 : (int)(color.x * 255.0); 15.71 int g = color.y > 1.0 ? 255 : (int)(color.y * 255.0); 15.72 int b = color.z > 1.0 ? 255 : (int)(color.z * 255.0); 15.73 @@ -104,24 +126,33 @@ 15.74 } 15.75 } 15.76 15.77 -void Renderer::message(MsgAtom msg) 15.78 +void Renderer::message(MsgAtom msg, ...) 15.79 { 15.80 - if(msg == rend->msg_start) { 15.81 - rend->cur_x = rend->cur_y = 0; 15.82 - rend->in_progress = true; 15.83 - memset(rend->pixels, 0, fb_width * fb_height * 4); 15.84 + va_list ap; 15.85 + va_start(ap, msg); 15.86 15.87 - printlog("starting a new rendering!\n"); 15.88 + for(int i=0; i<NUM_MESSAGES; i++) { 15.89 + if(msg == rend->msg[i]) { 15.90 + switch(i) { 15.91 + case MSG_START: 15.92 + rend->cur_x = rend->cur_y = 0; 15.93 + rend->in_progress = true; 15.94 + memset(rend->pixels, 0, fb_width * fb_height * 4); 15.95 + 15.96 + printlog("starting a new rendering!\n"); 15.97 + break; 15.98 + 15.99 + case MSG_GAMMA: 15.100 + rend->gamma = va_arg(ap, float); 15.101 + rend->inv_gamma = 1.0 / rend->gamma; 15.102 + break; 15.103 + 15.104 + case MSG_USE_GAMMA: 15.105 + rend->use_gamma = va_arg(ap, bool); 15.106 + break; 15.107 + } 15.108 + } 15.109 } 15.110 + 15.111 + va_end(ap); 15.112 } 15.113 - 15.114 - 15.115 -static Vector3 ray_trace(const Ray &ray, int iter) 15.116 -{ 15.117 - return shade(ray, 0, iter); 15.118 -} 15.119 - 15.120 -static Vector3 shade(const Ray &ray, float t, int iter) 15.121 -{ 15.122 - return Vector3(1.0, 0.0, 0.0); 15.123 -}
16.1 --- a/src/renderer.h Sun Apr 13 09:54:51 2014 +0300 16.2 +++ b/src/renderer.h Mon Apr 14 07:34:45 2014 +0300 16.3 @@ -19,7 +19,7 @@ 16.4 16.5 void handle_keyboard(int key, bool press); 16.6 16.7 - void message(MsgAtom msg); 16.8 + void message(MsgAtom msg, ...); 16.9 }; 16.10 16.11 #endif // RENDERER_H_
17.1 --- a/src/scancode.h Sun Apr 13 09:54:51 2014 +0300 17.2 +++ b/src/scancode.h Mon Apr 14 07:34:45 2014 +0300 17.3 @@ -8,9 +8,9 @@ 17.4 '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* f - 1c */ 17.5 KB_LCTRL, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', /* 1d - 29 */ 17.6 KB_LSHIFT, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', KB_RSHIFT, /* 2a - 36 */ 17.7 - KB_NUM_KB_MUL, KB_LALT, ' ', KB_CAPSLK, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, /* 37 - 44 */ 17.8 - KB_NUMLK, KB_SCRLK, KB_NUM_7, KB_NUM_8, KB_NUM_9, KB_NUM_KB_MINUS, KB_NUM_4, KB_NUM_5, KB_NUM_6, KB_NUM_KB_PLUS, /* 45 - 4e */ 17.9 - KB_NUM_1, KB_NUM_2, KB_NUM_3, KB_NUM_0, KB_NUM_KB_DOT, KB_SYSRQ, 0, 0, KB_F11, KB_F12, /* 4d - 58 */ 17.10 + KB_NUM_MUL, KB_LALT, ' ', KB_CAPSLK, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, /* 37 - 44 */ 17.11 + KB_NUMLK, KB_SCRLK, KB_NUM_7, KB_NUM_8, KB_NUM_9, KB_NUM_MINUS, KB_NUM_4, KB_NUM_5, KB_NUM_6, KB_NUM_PLUS, /* 45 - 4e */ 17.12 + KB_NUM_1, KB_NUM_2, KB_NUM_3, KB_NUM_0, KB_NUM_DOT, KB_SYSRQ, 0, 0, KB_F11, KB_F12, /* 4d - 58 */ 17.13 0, 0, 0, 0, 0, 0, 0, /* 59 - 5f */ 17.14 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6f */ 17.15 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 70 - 7f */
18.1 --- a/src/scene.cc Sun Apr 13 09:54:51 2014 +0300 18.2 +++ b/src/scene.cc Mon Apr 14 07:34:45 2014 +0300 18.3 @@ -1,4 +1,5 @@ 18.4 #include <string.h> 18.5 +#include <float.h> 18.6 #include "scene.h" 18.7 #include "min3d.h" 18.8 18.9 @@ -6,6 +7,14 @@ 18.10 { 18.11 name = 0; 18.12 active_cam = 0; 18.13 + 18.14 + fog_exp = 1.0; 18.15 + 18.16 + set_ambient(Vector3(0.05, 0.05, 0.05)); 18.17 + 18.18 + set_background(Vector3(0.4, 0.3, 0.05), SCN_BG_LOW); 18.19 + set_background(Vector3(0.6, 0.6, 0.6), SCN_BG_MID); 18.20 + set_background(Vector3(0.1, 0.5, 1.0), SCN_BG_HIGH); 18.21 } 18.22 18.23 Scene::~Scene() 18.24 @@ -41,6 +50,51 @@ 18.25 return name ? name : "<unknown>"; 18.26 } 18.27 18.28 +void Scene::set_background(const Vector3 &col, int idx) 18.29 +{ 18.30 + if(idx == -1) { 18.31 + bg[0] = bg[1] = bg[2] = col; 18.32 + } else { 18.33 + bg[idx] = col; 18.34 + } 18.35 +} 18.36 + 18.37 +const Vector3 &Scene::get_background(int idx) const 18.38 +{ 18.39 + return bg[idx == -1 ? 0 : idx]; 18.40 +} 18.41 + 18.42 +#define LERP(a, b, t) ((a) + ((b) - (a)) * t) 18.43 + 18.44 +Vector3 Scene::get_background(const Ray &ray) const 18.45 +{ 18.46 + Vector3 dir = normalize(ray.dir); 18.47 + 18.48 + float v; 18.49 + if(dir.z == 0.0) { 18.50 + v = dir.y > 0.0 ? 1.0 : -1.0; 18.51 + } else { 18.52 + float angle = atan2(dir.z, dir.y); 18.53 + v = angle / M_PI; 18.54 + } 18.55 + 18.56 + float r = v >= 0.0 ? LERP(bg[1].x, bg[2].x, v) : LERP(bg[1].x, bg[0].x, -v); 18.57 + float g = v >= 0.0 ? LERP(bg[1].y, bg[2].y, v) : LERP(bg[1].y, bg[0].y, -v); 18.58 + float b = v >= 0.0 ? LERP(bg[1].z, bg[2].z, v) : LERP(bg[1].z, bg[0].z, -v); 18.59 + return Vector3(r, g, b); 18.60 +} 18.61 + 18.62 +void Scene::set_ambient(const Vector3 &col) 18.63 +{ 18.64 + ambient = col; 18.65 +} 18.66 + 18.67 +const Vector3 &Scene::get_ambient() const 18.68 +{ 18.69 + return ambient; 18.70 +} 18.71 + 18.72 + 18.73 void Scene::add(SceneNode *node) 18.74 { 18.75 nodes.push_back(node); 18.76 @@ -180,3 +234,23 @@ 18.77 { 18.78 return idx >= 0 && idx < (int)sel.size() ? sel[idx] : -1; 18.79 } 18.80 + 18.81 +bool Scene::intersect(const Ray &ray, RayHit *hit) const 18.82 +{ 18.83 + if(hit) { 18.84 + hit->dist = FLT_MAX; 18.85 + hit->obj = 0; 18.86 + } 18.87 + 18.88 + int num_obj = (int)objects.size(); 18.89 + for(int i=0; i<num_obj; i++) { 18.90 + RayHit tmphit; 18.91 + if(objects[i]->intersect(ray, hit ? &tmphit : 0)) { 18.92 + if(!hit) return true; 18.93 + if(tmphit.dist < hit->dist) { 18.94 + *hit = tmphit; 18.95 + } 18.96 + } 18.97 + } 18.98 + return hit && hit->obj; 18.99 +}
19.1 --- a/src/scene.h Sun Apr 13 09:54:51 2014 +0300 19.2 +++ b/src/scene.h Mon Apr 14 07:34:45 2014 +0300 19.3 @@ -7,6 +7,9 @@ 19.4 #include "object.h" 19.5 #include "light.h" 19.6 #include "camera.h" 19.7 +#include "raytrace.h" 19.8 + 19.9 +enum { SCN_BG_LOW, SCN_BG_MID, SCN_BG_HIGH }; 19.10 19.11 class Scene { 19.12 private: 19.13 @@ -18,6 +21,10 @@ 19.14 vector<Camera*> cameras; 19.15 Camera *active_cam; 19.16 19.17 + Vector3 bg[3]; 19.18 + Vector3 ambient; 19.19 + float fog_exp; 19.20 + 19.21 vector<int> sel; 19.22 19.23 public: 19.24 @@ -29,6 +36,13 @@ 19.25 void set_name(const char *name); 19.26 const char *get_name() const; 19.27 19.28 + void set_background(const Vector3 &col, int idx = -1); 19.29 + const Vector3 &get_background(int idx = -1) const; 19.30 + Vector3 get_background(const Ray &ray) const; 19.31 + 19.32 + void set_ambient(const Vector3 &col); 19.33 + const Vector3 &get_ambient() const; 19.34 + 19.35 void add(SceneNode *node); 19.36 19.37 int get_node_count() const; 19.38 @@ -54,6 +68,8 @@ 19.39 void clear_selection(); 19.40 int get_selection_count() const; 19.41 int get_selection(int idx = 0) const; 19.42 + 19.43 + bool intersect(const Ray &ray, RayHit *hit = 0) const; 19.44 }; 19.45 19.46 #endif // SCENE_H_
20.1 --- a/src/screen.cc Sun Apr 13 09:54:51 2014 +0300 20.2 +++ b/src/screen.cc Mon Apr 14 07:34:45 2014 +0300 20.3 @@ -78,6 +78,6 @@ 20.4 { 20.5 } 20.6 20.7 -void Screen::message(MsgAtom ma) 20.8 +void Screen::message(MsgAtom msg, ...) 20.9 { 20.10 }
21.1 --- a/src/screen.h Sun Apr 13 09:54:51 2014 +0300 21.2 +++ b/src/screen.h Mon Apr 14 07:34:45 2014 +0300 21.3 @@ -26,7 +26,7 @@ 21.4 virtual void handle_mbutton(int bn, bool press, int x, int y); 21.5 virtual void handle_mmotion(int x, int y); 21.6 21.7 - virtual void message(MsgAtom ma); 21.8 + virtual void message(MsgAtom msg, ...); 21.9 }; 21.10 21.11 #endif // SCREEN_H_
22.1 --- a/src/snode.cc Sun Apr 13 09:54:51 2014 +0300 22.2 +++ b/src/snode.cc Mon Apr 14 07:34:45 2014 +0300 22.3 @@ -192,7 +192,7 @@ 22.4 { 22.5 m3d_matrix_mode(M3D_MODELVIEW); 22.6 m3d_push_matrix(); 22.7 - m3d_mult_matrix(get_matrix()[0]); 22.8 + m3d_mult_transpose_matrix(get_matrix()[0]); 22.9 } 22.10 22.11 void SceneNode::post_draw() const 22.12 @@ -228,7 +228,7 @@ 22.13 } 22.14 } 22.15 22.16 -bool SceneNode::intersect(const Ray &ray, float *dist) const 22.17 +bool SceneNode::intersect(const Ray &ray, RayHit *hit) const 22.18 { 22.19 return false; 22.20 }
23.1 --- a/src/snode.h Sun Apr 13 09:54:51 2014 +0300 23.2 +++ b/src/snode.h Mon Apr 14 07:34:45 2014 +0300 23.3 @@ -6,6 +6,7 @@ 23.4 #include "quat.h" 23.5 #include "vmathmat.h" 23.6 #include "vmathray.h" 23.7 +#include "raytrace.h" 23.8 23.9 enum NodeType { 23.10 NODE_NULL, 23.11 @@ -82,7 +83,7 @@ 23.12 23.13 virtual void draw(bool emph = false) const; 23.14 23.15 - virtual bool intersect(const Ray &ray, float *dist = 0) const; 23.16 + virtual bool intersect(const Ray &ray, RayHit *hit = 0) const; 23.17 }; 23.18 23.19 #endif /* SCENE_NODE_H_ */
24.1 --- a/src/vmath.cc Sun Apr 13 09:54:51 2014 +0300 24.2 +++ b/src/vmath.cc Mon Apr 14 07:34:45 2014 +0300 24.3 @@ -8,13 +8,17 @@ 24.4 Vector3 vi = normalize(cross(vk, vj)); 24.5 vj = cross(vi, vk); 24.6 24.7 - Matrix4x4 m( 24.8 + Matrix4x4 rm( 24.9 vi.x, vi.y, vi.z, 0, 24.10 vj.x, vj.y, vj.z, 0, 24.11 -vk.x, -vk.y, -vk.z, 0, 24.12 0, 0, 0, 1); 24.13 - translate(-pos.x, -pos.y, -pos.z); 24.14 - *this = *this * m; 24.15 + Matrix4x4 tm( 24.16 + 1, 0, 0, -pos.x, 24.17 + 0, 1, 0, -pos.y, 24.18 + 0, 0, 1, -pos.z, 24.19 + 0, 0, 0, 1); 24.20 + *this = *this * (rm * tm); 24.21 } 24.22 24.23 void Matrix4x4::transpose()
25.1 --- a/src/vmath.h Sun Apr 13 09:54:51 2014 +0300 25.2 +++ b/src/vmath.h Mon Apr 14 07:34:45 2014 +0300 25.3 @@ -50,6 +50,11 @@ 25.4 return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); 25.5 } 25.6 25.7 +inline Vector3 operator -(const Vector3 &v) 25.8 +{ 25.9 + return Vector3(-v.x, -v.y, -v.z); 25.10 +} 25.11 + 25.12 inline Vector3 operator *(const Vector3 &a, const Vector3 &b) 25.13 { 25.14 return Vector3(a.x * b.x, a.y * b.y, a.z * b.z); 25.15 @@ -85,6 +90,13 @@ 25.16 return Vector3(x, y, z); 25.17 } 25.18 25.19 +inline Vector3 lerp(const Vector3 &a, const Vector3 &b, float t) 25.20 +{ 25.21 + return Vector3(a.x + (b.x - a.x) * t, 25.22 + a.y + (b.y - a.y) * t, 25.23 + a.z + (b.z - a.z) * t); 25.24 +} 25.25 + 25.26 // ---- Vector4 ---- 25.27 25.28 class Vector4 { 25.29 @@ -129,6 +141,11 @@ 25.30 return Vector4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); 25.31 } 25.32 25.33 +inline Vector4 operator -(const Vector4 &v) 25.34 +{ 25.35 + return Vector4(-v.x, -v.y, -v.z, -v.w); 25.36 +} 25.37 + 25.38 inline Vector4 operator *(const Vector4 &v, float s) 25.39 { 25.40 return Vector4(v.x * s, v.y * s, v.z * s, v.w * s); 25.41 @@ -153,4 +170,13 @@ 25.42 return Vector4(x, y, z, w); 25.43 } 25.44 25.45 +inline Vector4 lerp(const Vector4 &a, const Vector4 &b, float t) 25.46 +{ 25.47 + return Vector4(a.x + (b.x - a.x) * t, 25.48 + a.y + (b.y - a.y) * t, 25.49 + a.z + (b.z - a.z) * t, 25.50 + a.w + (b.w - a.w) * t); 25.51 +} 25.52 + 25.53 + 25.54 #endif // VMATH_H_
26.1 --- a/src/vmathmat.h Sun Apr 13 09:54:51 2014 +0300 26.2 +++ b/src/vmathmat.h Mon Apr 14 07:34:45 2014 +0300 26.3 @@ -130,4 +130,12 @@ 26.4 *this = *this * m; 26.5 } 26.6 26.7 +inline Matrix4x4 normal_matrix(const Matrix4x4 &m) 26.8 +{ 26.9 + return Matrix4x4(m[0][0], m[0][1], m[0][2], 0, 26.10 + m[1][0], m[1][1], m[1][2], 0, 26.11 + m[2][0], m[2][1], m[2][2], 0, 26.12 + m[3][0], m[3][1], m[3][2], 1); 26.13 +} 26.14 + 26.15 #endif // VMATH_MATRIX_H_