00001 #include <gra/render/RTRender.h>
00002 #include <esg/explorer/RayIntExplorer.h>
00003 #include <gra/shader/RTShader.h>
00004 #include <esg/Statistics.h>
00005 #include <time.h>
00006
00007 using namespace gra;
00008
00009 void RTRender::_render_pixel_point(RayIntExplorer& explorer,
00010 SceneGraphObject& scene,
00011 Shader& shader,
00012 const Vector3& point,
00013 Vector3 dir,
00014 Color3f& pixelColor)
00015 {
00016 Color3f * pEnergy = NULL;
00017
00018
00019
00020
00021
00022 explorer.reinit(point, dir, _pIntersector);
00023 _pIntersector->init(ENV_WANT_INTERSECTION |
00024 ENV_WANT_NORMAL |
00025 ENV_WANT_ASOC_PRIMITIVE |
00026 ENV_WANT_N_DOT_D);
00027 explorer.explore(scene);
00028
00029
00030
00031
00032
00033 PointEnv* pSurr = explorer.result();
00034 if (!pSurr) {
00035 pixelColor.set(_background);
00036 return;
00037 }
00038 if (!(pSurr->mask & (ENV_HAVE_INTERSECTION|
00039 ENV_HAVE_NORMAL|
00040 ENV_HAVE_ASOC_PRIMITIVE))) {
00041 delete pSurr;
00042 pixelColor.set(_background);
00043 return;
00044 }
00045
00046
00047
00048
00049
00050 dir.negate();
00051
00052 double nv = ((pSurr->mask & ENV_HAVE_N_DOT_D) ?
00053 -(pSurr->nd) :
00054 pSurr->normal.dot(dir));
00055
00056 if (pSurr->normalOrientation == PointEnv::RANDOM_NORMAL &&
00057 pSurr->normal.dot(dir) < 0) pSurr->normal.negate();
00058
00059 if (pSurr->mask & ENV_HAVE_TRANSFORMATION) {
00060 shader.setRenderedShape(pSurr->pVisitableObj, &(pSurr->trMat));
00061 pEnergy = shader.illuminatePoint(pSurr->intersection,
00062 pSurr->normal,
00063 dir, 0, &nv,
00064 &(pSurr->trMat));
00065 } else {
00066 shader.setRenderedShape(pSurr->pVisitableObj, NULL);
00067 pEnergy = shader.illuminatePoint(pSurr->intersection,
00068 pSurr->normal,
00069 dir, 0, &nv, NULL);
00070 }
00071
00072 delete pSurr;
00073
00074 if (pEnergy) {
00075 pixelColor.set(*pEnergy);
00076 delete pEnergy;
00077 }
00078 }
00079
00080 unsigned RTRender::_render_pixel_centroid(RayIntExplorer& explorer,
00081 SceneGraphObject& scene,
00082 Shader& shader,
00083 Camera& camera,
00084 const Vector3& centroid,
00085 unsigned row,
00086 unsigned col,
00087 unsigned resX,
00088 unsigned resY,
00089 Color3f& pixelColor)
00090 {
00091 Color3f c;
00092 _render_pixel_point(explorer, scene, shader, centroid,
00093 camera.getProjectionDirection(camera.mapPixelToProjPlane(col, row, resX, resY, Camera::PS_CENTROID)), c);
00094 pixelColor.add(c);
00095 return 1;
00096 }
00097
00098 unsigned RTRender::_render_pixel_corners(RayIntExplorer& explorer,
00099 SceneGraphObject& scene,
00100 Shader& shader,
00101 Camera& camera,
00102 const Vector3d& point,
00103 const Vector3d& xDir,
00104 const Vector3d& yDir,
00105 unsigned row,
00106 unsigned col,
00107 unsigned resX,
00108 unsigned resY,
00109 Color3f* cRow,
00110 Color3f& cCol,
00111 Color3f& pixelColor)
00112 {
00113 Vector3d p(point);
00114 Color3f c00(0,0,0);
00115 unsigned numRays = 0;
00116
00117 if (row == 0 && col == 0) {
00118 _render_pixel_point(explorer, scene, shader, p,
00119 camera.getProjectionDirection(camera.mapPixelToProjPlane(col, row, resX, resY, Camera::PS_UPPER_LEFT_CORNER)),
00120 c00);
00121 p.add(xDir);
00122 _render_pixel_point(explorer, scene, shader, p,
00123 camera.getProjectionDirection(camera.mapPixelToProjPlane(col, row, resX, resY, Camera::PS_UPPER_RIGHT_CORNER)),
00124 cRow[col+1]);
00125 p.set(point);
00126 p.add(yDir);
00127 _render_pixel_point(explorer, scene, shader, p,
00128 camera.getProjectionDirection(camera.mapPixelToProjPlane(col, row, resX, resY, Camera::PS_LOWER_LEFT_CORNER)),
00129 cRow[col]);
00130 p.add(xDir);
00131 _render_pixel_point(explorer, scene, shader, p,
00132 camera.getProjectionDirection(camera.mapPixelToProjPlane(col, row, resX, resY, Camera::PS_LOWER_RIGHT_CORNER)),
00133 cCol);
00134 numRays = 4;
00135 }
00136
00137 if (row == 0 && col > 0) {
00138 c00.set(cRow[col]);
00139 cRow[col].set(cCol);
00140 p.add(xDir);
00141 _render_pixel_point(explorer, scene, shader, p,
00142 camera.getProjectionDirection(camera.mapPixelToProjPlane(col, row, resX, resY, Camera::PS_UPPER_RIGHT_CORNER)),
00143 cRow[col+1]);
00144 p.add(yDir);
00145 _render_pixel_point(explorer, scene, shader, p,
00146 camera.getProjectionDirection(camera.mapPixelToProjPlane(col, row, resX, resY, Camera::PS_LOWER_RIGHT_CORNER)),
00147 cCol);
00148 numRays = 2;
00149 }
00150
00151 if (row > 0 && col == 0) {
00152 c00.set(cRow[col]);
00153 p.add(yDir);
00154 _render_pixel_point(explorer, scene, shader, p,
00155 camera.getProjectionDirection(camera.mapPixelToProjPlane(col, row, resX, resY, Camera::PS_LOWER_LEFT_CORNER)),
00156 cRow[col]);
00157 p.add(xDir);
00158 _render_pixel_point(explorer, scene, shader, p,
00159 camera.getProjectionDirection(camera.mapPixelToProjPlane(col, row, resX, resY, Camera::PS_LOWER_RIGHT_CORNER)),
00160 cCol);
00161 numRays = 2;
00162 }
00163
00164 if (row > 0 && col > 0) {
00165 c00.set(cRow[col]);
00166 cRow[col].set(cCol);
00167 p.add(yDir);
00168 p.add(xDir);
00169 _render_pixel_point(explorer, scene, shader, p,
00170 camera.getProjectionDirection(camera.mapPixelToProjPlane(col, row, resX, resY, Camera::PS_LOWER_RIGHT_CORNER)),
00171 cCol);
00172 numRays = 1;
00173 }
00174
00175 c00.add(cRow[col]);
00176 c00.add(cRow[col+1]);
00177 c00.add(cCol);
00178 c00.scale(.25);
00179 pixelColor.add(c00);
00180
00181 return numRays;
00182 }
00183
00184 unsigned RTRender::_render_pixel_randomly(RayIntExplorer& explorer,
00185 SceneGraphObject& scene,
00186 Shader& shader,
00187 Camera& camera,
00188 const Vector3& centroid,
00189 unsigned row,
00190 unsigned col,
00191 unsigned resX,
00192 unsigned resY,
00193 Color3f& pixelColor)
00194 {
00195 Color3f c;
00196 _render_pixel_point(explorer, scene, shader, centroid,
00197 camera.getProjectionDirection(camera.mapPixelToProjPlane(col, row, resX, resY, Camera::PS_RANDOM)), c);
00198 pixelColor.add(c);
00199 return 1;
00200 }
00201
00202 unsigned RTRender::_render_pixel_stratified(RayIntExplorer& explorer,
00203 SceneGraphObject& scene,
00204 Shader& shader,
00205 Camera& camera,
00206 const Vector3d& point,
00207 const Vector3d& xDir,
00208 const Vector3d& yDir,
00209 double xDirLength,
00210 double yDirLength,
00211 Color3f& pixelColor)
00212 {
00213 Color3f color(0,0,0);
00214 Color3f c(0,0,0);
00215
00216 if (_raysPerPixel <= 0) return 0;
00217
00218 unsigned m = (unsigned) sqrt((float)_raysPerPixel);
00219 double xd = xDirLength / (double) m;
00220 double yd = yDirLength / (double) m;
00221
00222 for (unsigned i = 0; i < m; i++) {
00223 for (unsigned j = 0; j < m; j++) {
00224 Vector3d u(xDir);
00225 u.scale(i * xd + ESG_DBL_RAND * xd);
00226 Vector3d p(yDir);
00227 p.scale(j * yd + ESG_DBL_RAND * yd);
00228 p.add(u);
00229 p.add(point);
00230 _render_pixel_point(explorer, scene, shader, p,
00231 camera.getProjectionDirection(camera.project(p)),
00232 c);
00233 color.add(c);
00234 }
00235 }
00236
00237
00238 if (m > 1) color.scale(1. / (double) (m * m));
00239 pixelColor.add(color);
00240
00241 return m * m;
00242 }
00243
00244 void RTRender::_render(Shader& shader,
00245 FrameBuffer& fb,
00246 Camera& camera,
00247 Scene& scene)
00248 {
00249 unsigned resX = fb.getWidth();
00250 unsigned resY = fb.getHeight();
00251 Color3f* pixelColors;
00252 unsigned pcIndex = 0;
00253 unsigned pcX = 0;
00254 unsigned pcY = resY - 1;
00255 int raycounter = 0;
00256 Vector3 top_left, bottom_right;
00257 Vector3 down_vec, right_vec, dir, centroid, point;
00258 Vector2 step(camera.getPixelSize(resX, resY));
00259 float xPixelSize, yPixelSize;
00260 Color3f* cRow = NULL;
00261 Color3f cCol;
00262
00263 RayIntExplorer explorer(Vector3(0,0,0), Vector3(0,0,0), _pIntersector);
00264
00265 if (!_pIntersector) return;
00266
00267 camera.getProjectionPlane(down_vec, top_left, right_vec, bottom_right);
00268
00269
00270
00271
00272 down_vec.sub(top_left);
00273 right_vec.sub(top_left);
00274 down_vec.normalize();
00275 right_vec.normalize();
00276 down_vec.scale(step.y);
00277 right_vec.scale(step.x);
00278
00279 xPixelSize = right_vec.length();
00280 yPixelSize = down_vec.length();
00281
00282
00283 if (_pixelRendering == CENTROID) {
00284 top_left.add(right_vec * .5);
00285 top_left.sub(down_vec * .5);
00286 }
00287
00288 switch (_fbWriteMode) {
00289 case PER_LINE:
00290 pixelColors = new Color3f[resX * _fbWriteElements];
00291 break;
00292 case PER_PIXEL:
00293 default:
00294 pixelColors = new Color3f[_fbWriteElements];
00295 break;
00296 }
00297
00298 #ifdef ESG_STATISTICS
00299 ((Stopwatch*)Statistics::instance()->get(Statistics::OID_RENDERING_TIME)->receptor())->start();
00300 ((Stopwatch*)Statistics::instance()->get(Statistics::OID_CPU_RENDERING_TIME)->receptor())->start();
00301 #endif // ESG_STATISTICS
00302
00303 for (int i = (int) resY - 1; i >= 0; i--) {
00304 centroid.set(top_left);
00305
00306 for (int j = 0; j < (int) resX; j++) {
00307 if (_pStopFlag != NULL && *_pStopFlag) return;
00308
00309 pixelColors[pcIndex].set(0,0,0);
00310
00311
00312 switch (_pixelRendering) {
00313 case CENTROID:
00314 raycounter += _render_pixel_centroid(explorer,
00315 *(scene.root()),
00316 shader,
00317 camera,
00318 centroid,
00319 i, j,
00320 resX, resY,
00321 pixelColors[pcIndex]);
00322 break;
00323 case CORNERS:
00324 if (cRow == NULL) cRow = new Color3f [resX + 1];
00325 raycounter += _render_pixel_corners(explorer, *(scene.root()),
00326 shader, camera, centroid,
00327 right_vec, down_vec,
00328 i, j,
00329 resX, resY,
00330 cRow, cCol,
00331 pixelColors[pcIndex]);
00332 if (j == (int)(resX - 1)) cRow[j+1].set(cCol);
00333 break;
00334 case RANDOM:
00335 raycounter += _render_pixel_centroid(explorer,
00336 *(scene.root()),
00337 shader,
00338 camera,
00339 centroid,
00340 i, j,
00341 resX, resY,
00342 pixelColors[pcIndex]);
00343 #if 0
00344 raycounter += _render_pixel_randomly(explorer, *(scene.root()),
00345 shader, camera, centroid,
00346 right_vec, down_vec,
00347 xPixelSize, yPixelSize,
00348 pixelColors[pcIndex]);
00349 #endif
00350 break;
00351 case STRATIFIED_SAMPLING:
00352 raycounter += _render_pixel_stratified(explorer,
00353 *(scene.root()), shader,
00354 camera, centroid,
00355 right_vec, down_vec,
00356 xPixelSize, yPixelSize,
00357 pixelColors[pcIndex]);
00358 break;
00359 case CENTROID_AND_CORNERS:
00360
00361 break;
00362 }
00363
00364
00365
00366
00367 if (_fbWriteMode == PER_PIXEL && _fbWriteElements <= (pcIndex+1)) {
00368 fb.setColor(camera, pcX, pcY, pixelColors[pcIndex]);
00369
00370
00371 pcIndex = 0;
00372 pcX = (j + 1) % resX;
00373 pcY = (pcX) ? i : i - 1;
00374 } else {
00375 pcIndex++;
00376 }
00377
00378 centroid.add(right_vec);
00379 }
00380
00381 if (_fbWriteMode == PER_LINE) {
00382 if (_fbWriteElements <= (pcY - i + 1)) {
00383 fb.setColors(camera, pcX, pcY, pixelColors, resX * (pcY-i+1));
00384
00385 pcIndex = 0;
00386 pcX = 0;
00387 pcY = i - 1;
00388 } else {
00389 pcIndex++;
00390 }
00391 }
00392
00393 top_left.add(down_vec);
00394 }
00395
00396
00397 #ifdef ESG_STATISTICS
00398 ((Stopwatch*)Statistics::instance()->get(Statistics::OID_RENDERING_TIME)->receptor())->stop();
00399 ((Stopwatch*)Statistics::instance()->get(Statistics::OID_CPU_RENDERING_TIME)->receptor())->stop();
00400 ((Counter*)Statistics::instance()->get(Statistics::OID_PRIMARY_RAYS)->receptor())->set(raycounter);
00401 #endif // ESG_STATISTICS
00402
00403
00404 if (cRow) delete [] cRow;
00405 delete [] pixelColors;
00406 }
00407
00408
00409
00410
00411
00412