src/raytracer.cc
branchpyrit
changeset 31 b4e09433934a
parent 30 33f95441790e
child 32 8af5c17d368b
equal deleted inserted replaced
30:33f95441790e 31:b4e09433934a
    97 	Shape *nearest_shape = top->nearest_intersection(origin_shape, ray, nearest_distance);
    97 	Shape *nearest_shape = top->nearest_intersection(origin_shape, ray, nearest_distance);
    98 
    98 
    99 	if (nearest_shape == NULL) {
    99 	if (nearest_shape == NULL) {
   100 		return bg_colour;
   100 		return bg_colour;
   101 	} else {
   101 	} else {
   102 		Colour acc = Colour();
   102 		Colour col = Colour();
   103 		Vector3 P = ray.o + ray.dir * nearest_distance; // point of intersection
   103 		Vector3 P = ray.o + ray.dir * nearest_distance; // point of intersection
   104 		Vector3 normal = nearest_shape->normal(P);
   104 		Vector3 normal = nearest_shape->normal(P);
       
   105 		bool from_inside = false;
       
   106 
   105 		// make shapes double sided
   107 		// make shapes double sided
   106 		if (dot(normal, ray.dir) > 0.0)
   108 		if (dot(normal, ray.dir) > 0.0)
       
   109 		{
   107 			normal = - normal;
   110 			normal = - normal;
   108 		acc = PhongShader_ambient(*nearest_shape->material, P);
   111 			from_inside = true;
       
   112 		}
       
   113 
       
   114 		col = PhongShader_ambient(*nearest_shape->material, P);
   109 
   115 
   110 		vector<Light*>::iterator light;
   116 		vector<Light*>::iterator light;
   111 		for (light = lights.begin(); light != lights.end(); light++) {
   117 		for (light = lights.begin(); light != lights.end(); light++) {
   112 			Vector3 jo, L = (*light)->pos - P; // direction vector to light
   118 			Vector3 jo, L = (*light)->pos - P; // direction vector to light
   113 			L.normalize();
   119 			L.normalize();
   121 						continue;
   127 						continue;
   122 				}
   128 				}
   123 
   129 
   124 				// shading function
   130 				// shading function
   125 				Vector3 R = L - 2.0 * L_dot_N * normal;
   131 				Vector3 R = L - 2.0 * L_dot_N * normal;
   126 				acc += PhongShader_calculate(*nearest_shape->material,
   132 				col += PhongShader_calculate(*nearest_shape->material,
   127 					P, normal, R, ray.dir, **light);
   133 					P, normal, R, ray.dir, **light);
   128 			}
   134 			}
   129 		}
   135 		}
   130 
   136 
   131 		// reflection
   137 		if (depth < max_depth)
   132 		Vector3 newdir = ray.dir - 2.0 * dot(ray.dir, normal) * normal;
   138 		{
   133 		if (depth < max_depth && nearest_shape->material->reflection > 0.01) {
   139 			Colour trans_col, refl_col;
   134 			Ray newray = Ray(P, newdir);
   140 			Float trans = nearest_shape->material->transmissivity;
   135 			Colour refl_col = raytrace(newray, depth + 1, nearest_shape);
   141 			Float refl = nearest_shape->material->reflectivity;
   136 			acc += nearest_shape->material->reflection * refl_col;
   142 			const Float cos_i = - dot(normal, ray.dir);
   137 		}
   143 
   138 
   144 			// reflection
   139 		// refraction
   145 			if (refl > 0.01)
   140 		/* ... */
   146 			{
       
   147 				Vector3 newdir = ray.dir + 2.0 * cos_i * normal;
       
   148 				Ray newray = Ray(P, newdir);
       
   149 				refl_col = raytrace(newray, depth + 1, nearest_shape);
       
   150 			}
       
   151 
       
   152 			// refraction
       
   153 		 	if (trans > 0.01)
       
   154 			{
       
   155 				Float n, n1, n2;
       
   156 				if (from_inside)
       
   157 				{
       
   158 					n1 = nearest_shape->material->refract_index;
       
   159 					n2 = 1.0;
       
   160 					n = n1;
       
   161 				}
       
   162 				else
       
   163 				{
       
   164 					n1 = 1.0;
       
   165 					n2 = nearest_shape->material->refract_index;
       
   166 					n = 1.0 / n2;
       
   167 				}
       
   168 				const Float sin2_t = n*n * (1 - cos_i*cos_i);
       
   169 				if (sin2_t >= 1.0)
       
   170 				{
       
   171 					 // totally reflected
       
   172 					 refl += trans;
       
   173 					 trans = 0;
       
   174 				}
       
   175 				else
       
   176 				{
       
   177 					const Float cos_t = sqrtf(1 - sin2_t);
       
   178 					const Float Rdiv = 1.0/(n1*cos_i + n2*cos_t);
       
   179 					const Float Rper = (n1*cos_i - n2*cos_t)*Rdiv;
       
   180 					const Float Rpar = (n2*cos_i - n1*cos_t)*Rdiv;
       
   181 					const Float R = (Rper*Rper + Rpar*Rpar)/2;
       
   182 					refl += R*trans;
       
   183 					trans = (1-R)*trans;
       
   184 					Vector3 newdir = n * ray.dir + (n*cos_i - cos_t) * normal;
       
   185 					Ray newray = Ray(P, newdir);
       
   186 					trans_col = raytrace(newray, depth + 1, nearest_shape);
       
   187 				}
       
   188 			}
       
   189 			col = (1-refl-trans)*col + refl*refl_col + trans*trans_col;
       
   190 		}
   141 
   191 
   142 		// ambient occlusion
   192 		// ambient occlusion
   143 		if (ao_samples)
   193 		if (ao_samples)
   144 		{
   194 		{
   145 			Float miss = 0;
   195 			Float miss = 0;
   152 					miss += 1.0;
   202 					miss += 1.0;
   153 				else
   203 				else
   154 					miss += dist / ao_distance;
   204 					miss += dist / ao_distance;
   155 			}
   205 			}
   156 			Float ao_intensity = miss / ao_samples;
   206 			Float ao_intensity = miss / ao_samples;
   157 			acc = acc * ao_intensity;
   207 			col = col * ao_intensity;
   158 		}
   208 		}
   159 
   209 
   160 		return acc;
   210 		return col;
   161 	}
   211 	}
   162 }
   212 }
   163 
   213 
   164 static void *renderrow(void *data)
   214 static void *renderrow(void *data)
   165 {
   215 {