212 } |
212 } |
213 |
213 |
214 static void *renderrow(void *data) |
214 static void *renderrow(void *data) |
215 { |
215 { |
216 RenderrowData *d = (RenderrowData*) data; |
216 RenderrowData *d = (RenderrowData*) data; |
217 int subsample = d->rt->getSubsample(); |
217 const int subsample = d->rt->getSubsample(); |
218 Float subsample2 = 1.0/(subsample*subsample); |
218 const Float subsample2 = 1.0/(subsample*subsample); |
219 int ww = d->w*3; |
219 const int oversample = d->rt->getOversample(); |
|
220 const int ww = d->w*3; |
220 Vector3 dir = d->dfix; |
221 Vector3 dir = d->dfix; |
221 for (int x = 0; x < d->w; x += subsample) { |
222 for (int x = 0; x < d->w; x += subsample) { |
222 // generate a ray from eye passing through this pixel |
223 // generate a ray from eye passing through this pixel |
223 #if OVERSAMPLING |
|
224 // 5x oversampling |
|
225 Colour c = Colour(); |
|
226 |
|
227 for (int i = 0; i < 5; i++) |
|
228 { |
|
229 Float osax[] = {0.0, -0.4, +0.4, +0.4, -0.4}; |
|
230 Float osay[] = {0.0, -0.4, -0.4, +0.4, +0.4}; |
|
231 Vector3 tmpdir = dir + osax[i]*d->dx + osay[i]*d->dy; |
|
232 tmpdir.normalize(); |
|
233 Ray ray(d->eye, tmpdir); |
|
234 c += d->rt->raytrace(ray, 0, NULL); |
|
235 } |
|
236 c = c * (1./5); |
|
237 #else |
|
238 // no oversampling |
|
239 dir.normalize(); |
|
240 Ray ray(d->eye, dir); |
|
241 Colour c = d->rt->raytrace(ray, 0, NULL); |
|
242 if (subsample > 1) |
224 if (subsample > 1) |
243 { |
225 { |
244 Colour ic; |
226 Colour ic; |
245 // top-left is 'c' |
227 // top-left |
|
228 dir.normalize(); |
|
229 Ray ray(d->eye, dir); |
|
230 Colour c1 = d->rt->raytrace(ray, 0, NULL); |
246 // top-right |
231 // top-right |
247 Vector3 tmpdir = dir + (subsample-1)*d->dx; |
232 Vector3 tmpdir = dir + (subsample-1)*d->dx; |
248 tmpdir.normalize(); |
233 tmpdir.normalize(); |
249 Ray ray(d->eye, tmpdir); |
234 ray.dir = tmpdir; |
250 Colour c2 = d->rt->raytrace(ray, 0, NULL); |
235 Colour c2 = d->rt->raytrace(ray, 0, NULL); |
251 // bottom right |
236 // bottom right |
252 tmpdir += (subsample-1)*d->dy; |
237 tmpdir += (subsample-1)*d->dy; |
253 tmpdir.normalize(); |
238 tmpdir.normalize(); |
254 ray.dir = tmpdir; |
239 ray.dir = tmpdir; |
257 tmpdir = dir + (subsample-1)*d->dy; |
242 tmpdir = dir + (subsample-1)*d->dy; |
258 tmpdir.normalize(); |
243 tmpdir.normalize(); |
259 ray.dir = tmpdir; |
244 ray.dir = tmpdir; |
260 Colour c3 = d->rt->raytrace(ray, 0, NULL); |
245 Colour c3 = d->rt->raytrace(ray, 0, NULL); |
261 // are the colors similar? |
246 // are the colors similar? |
262 Float m = (c-c2).mag2(); |
247 Float m = (c1-c2).mag2(); |
263 m = max(m, (c2-c3).mag2()); |
248 m = max(m, (c2-c3).mag2()); |
264 m = max(m, (c3-c4).mag2()); |
249 m = max(m, (c3-c4).mag2()); |
265 m = max(m, (c4-c).mag2()); |
250 m = max(m, (c4-c1).mag2()); |
266 if (m < 0.001) |
251 if (m < 0.001) |
267 { |
252 { |
268 // interpolate |
253 // interpolate |
269 Float *i = d->iter; |
254 Float *i = d->iter; |
270 for (int x = 0; x < subsample; x++) |
255 for (int x = 0; x < subsample; x++) |
271 { |
256 { |
272 for (int y = 0; y < subsample; y++) |
257 for (int y = 0; y < subsample; y++) |
273 { |
258 { |
274 ic = c*(subsample-x)*(subsample-y)*subsample2 |
259 ic = c1*(subsample-x)*(subsample-y)*subsample2 |
275 + c2*(x)*(subsample-y)*subsample2 |
260 + c2*(x)*(subsample-y)*subsample2 |
276 + c3*(subsample-x)*(y)*subsample2 |
261 + c3*(subsample-x)*(y)*subsample2 |
277 + c4*(x)*(y)*subsample2; |
262 + c4*(x)*(y)*subsample2; |
278 *(i + ww*y) = ic.r; |
263 *(i + ww*y) = ic.r; |
279 *(i + ww*y + 1) = ic.g; |
264 *(i + ww*y + 1) = ic.g; |
340 *(d->iter + ww*(subsample-1) + 1) = c4.g; |
325 *(d->iter + ww*(subsample-1) + 1) = c4.g; |
341 *(d->iter + ww*(subsample-1) + 2) = c4.b; |
326 *(d->iter + ww*(subsample-1) + 2) = c4.b; |
342 d->iter += 3; |
327 d->iter += 3; |
343 } |
328 } |
344 } |
329 } |
345 #endif |
330 else // subsample <= 1 |
346 if (subsample <= 1) |
|
347 { |
331 { |
|
332 Colour c; |
|
333 if (oversample <= 0) |
|
334 { |
|
335 // no oversampling |
|
336 dir.normalize(); |
|
337 Ray ray(d->eye, dir); |
|
338 c = d->rt->raytrace(ray, 0, NULL); |
|
339 } |
|
340 else |
|
341 if (oversample <= 3) |
|
342 { |
|
343 // grid oversampling |
|
344 static const int gridsamples[] = {5,9,16}; |
|
345 static const Float osa5x[] = {0.0, -0.4, +0.4, +0.4, -0.4}; |
|
346 static const Float osa5y[] = {0.0, -0.4, -0.4, +0.4, +0.4}; |
|
347 static const Float osa9x[] = {-0.34, 0.00, +0.34, |
|
348 -0.34, 0.00, +0.34, -0.34, 0.00, +0.34}; |
|
349 static const Float osa9y[] = {-0.34, -0.34, -0.34, |
|
350 0.00, 0.00, 0.00, +0.34, +0.34, +0.34}; |
|
351 static const Float osa16x[] = {-0.375, -0.125, +0.125, +0.375, |
|
352 -0.375, -0.125, +0.125, +0.375, -0.375, -0.125, +0.125, +0.375, |
|
353 -0.375, -0.125, +0.125, +0.375}; |
|
354 static const Float osa16y[] = {-0.375, -0.375, -0.375, -0.375, |
|
355 -0.125, -0.125, -0.125, -0.125, +0.125, +0.125, +0.125, +0.125, |
|
356 +0.375, +0.375, +0.375, +0.375}; |
|
357 static const Float *osaSx[] = {osa5x, osa9x, osa16x}; |
|
358 static const Float *osaSy[] = {osa5y, osa9y, osa16y}; |
|
359 const int samples = gridsamples[oversample-1]; |
|
360 const Float *osax = osaSx[oversample-1]; |
|
361 const Float *osay = osaSy[oversample-1]; |
|
362 for (int i = 0; i < samples; i++) |
|
363 { |
|
364 Vector3 tmpdir = dir + osax[i]*d->dx + osay[i]*d->dy; |
|
365 tmpdir.normalize(); |
|
366 Ray ray(d->eye, tmpdir); |
|
367 c += d->rt->raytrace(ray, 0, NULL); |
|
368 } |
|
369 c = c * (1.0/samples); |
|
370 } |
|
371 else |
|
372 { |
|
373 // stochastic oversampling |
|
374 // ...todo |
|
375 } |
|
376 // write color to buffer |
348 *d->iter++ = c.r; |
377 *d->iter++ = c.r; |
349 *d->iter++ = c.g; |
378 *d->iter++ = c.g; |
350 *d->iter++ = c.b; |
379 *d->iter++ = c.b; |
351 } |
380 } |
352 dir += d->dx*subsample; |
381 dir += d->dx*subsample; |