raytracer.cpp

来自「Ray tracing on PS3, using the accelerati」· C++ 代码 · 共 399 行 · 第 1/2 页

CPP
399
字号
/* Copyright (c) 2007 Massachusetts Institute of Technology * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *//** * raytracer.cpp - Implementation for routines of the RayTracer class * @author Brian Sweatt * * The CLIPPING_T, LIGHT_CLIPPING, and CLIPPING_WEIGHT parameters can be tweaked in this file... * These are the maximum intersection time that will recurse for reflection and refraction, the  * minimum lighting contribution before a shadow is assumed, and the minimum recursion weight, respectively. *  * Altering these parameters by decreasing CLIPPING_T, increasing LIGHT_CLIPPING, or increasing CLIPPING_WEIGHT * may increase performance, but will decrease rendering quality. Alter at your own rendering risk. */extern "C" {#include <reflect_vec3_v.h>#include <dot_product3_v.h>#include <dot_product3.h>#include <normalize3_v.h>#include <spu_mfcio.h>  // #include <simdmath.h>#include <simdmath/recipf4.h>#include <simdmath/sqrtf4.h>}#include "raytracer.h"#include "light.h"#include "material.h"#include "common.h"#define CLIPPING_T 1000.0f// Warning: setting light clipping could lead to ugly artifacts if set too high....#define LIGHT_CLIPPING 0.0f#define CLIPPING_WEIGHT 0.0fRayTracer :: RayTracer(ObjectSet *Objects, int Bounces, bool Shadows, int NumLights, vector float Amb):   objects(Objects),   bounces(Bounces),   shadows(Shadows),   num_lights(NumLights),  ambient_light(Amb) {}int RayTracer :: getBounces() const {  return bounces;}// Returns the mask for which directions are valid.... Invalid directions are filled in with ZEROvector unsigned int RayTracer::transmit_vec3_v(vector float &dx, vector float &dy, vector float &dz,					       const vector float nx, const vector float ny, const vector float nz,					       const vector float ix, const vector float iy, const vector float iz, 					       vector float index_i, vector float index_t) const {  vector float Ix, Iy, Iz;  vector float nr = _recipf4_fast(index_t);  const vector unsigned int sign_bit = spu_splats((unsigned int)0x80000000);  Ix = (vector float) spu_xor((vector unsigned int) ix, sign_bit);  Iy = (vector float) spu_xor((vector unsigned int) iy, sign_bit);  Iz = (vector float) spu_xor((vector unsigned int) iz, sign_bit);  nr = spu_mul(nr, index_i);  vector float nDotI = _dot_product3_v(nx, ny, nz, Ix, Iy, Iz);  vector float one_v = spu_splats(1.0f);  vector float sqrtTerm = spu_nmsub(nDotI, nDotI, one_v);  sqrtTerm = spu_nmsub(spu_mul(nr, nr), sqrtTerm, one_v);  vector float zero_v = spu_splats(0.0f);  vector unsigned int valid = spu_cmpgt(sqrtTerm, zero_v);  vector float rx, ry, rz;  vector float rfactor;  sqrtTerm = _sqrtf4(sqrtTerm);  rx = spu_mul(nr, Ix);  ry = spu_mul(nr, Iy);  rz = spu_mul(nr, Iz);  rfactor = spu_msub(nr, nDotI, sqrtTerm);  rx = spu_msub(rfactor, nx, rx);  ry = spu_msub(rfactor, ny, ry);  rz = spu_msub(rfactor, nz, rz);  _normalize3_v(&rx, &ry, &rz, rx, ry, rz);  dx = spu_sel(zero_v, rx, valid);  dy = spu_sel(zero_v, ry, valid);  dz = spu_sel(zero_v, rz, valid);    return valid;}RGBPacket RayTracer :: tracePacket(const RayPacket r, HitPacket &hit, float tmin, int bounces, vector float refIndex) const {  RGBPacket color;  vector float old_t = hit.t;  vector float zero_v = spu_splats(0.0f);  vector float one_v = spu_splats(1.0f);  vector float half = spu_splats(0.5f);  vector float max_v = spu_splats(MAX_FLOAT);  /*  vector float rx0 = r.x0;  vector float ry0 = r.y0;  vector float rz0 = r.z0;  vector float rdx = r.dx;  vector float rdy = r.dy;  vector float rdz = r.dz;  vector float hit_t = hit.t;  vector float hit_nx = hit.nx;  vector float hit_ny = hit.ny;  vector float hit_nz = hit.nz;  */  color.r = color.g = color.b = zero_v;    //printf("TracePacket: %i %i  %i\n", objects->num_spheres, objects->num_triangles, bounces);  bool sAlloc = (bool) objects->spheres;  bool tAlloc = (bool) objects->triangles;  // DMA transfers have been started on the   // Loop over all the objects in the scene, one primitive-type at a time  mfc_write_tag_mask(1 << DMA_TAG_TRIANGLES);  mfc_read_tag_status_all();  //printf("TracePacket... finished DMAing triangles\n");  for (int j = 0; tAlloc && (j < objects->num_triangles); j++) {    (*(objects->triangles+j)).intersectPacket(r, hit, tmin);  }  mfc_write_tag_mask(1 << DMA_TAG_SPHERES);  mfc_read_tag_status_all();  for (int j = 0; sAlloc && (j < objects->num_spheres); j++) {    (*(objects->spheres+j)).intersectPacket(r, hit, tmin);  }  vector unsigned int changed = spu_cmpgt(old_t, hit.t);  vector float x = spu_madd(r.dx, hit.t, r.x0);  vector float y = spu_madd(r.dy, hit.t, r.y0);  vector float z = spu_madd(r.dz, hit.t, r.z0);    mfc_write_tag_mask(1 << DMA_TAG_LIGHTS);  mfc_read_tag_status_all();  // After finding the closest intersection, shade it for every light in the scene  for (int i = 0; i < objects->num_lights; i++) {    vector float dirToLightx, dirToLighty, dirToLightz, distanceToLight;    RGBPacket light_color;    RGBPacket curr;    light_color.r = zero_v; light_color.g = zero_v; light_color.b = zero_v;    curr.r = zero_v; curr.g = zero_v; curr.b = zero_v;    RayPacket sray;    HitPacket shit;    sray.x0 = x; sray.y0 = y; sray.z0 = z;        light_getIllumination(*(objects->lights+i), light_color, dirToLightx, dirToLighty, dirToLightz, 			  distanceToLight, x, y, z);#if(SHADING)#if(SHADOWS)    // The following is code to see if the contribution from a light is significant enough to make     // a noticeable impact on the scene... This is adjusted using the LIGHT_CLIPPING constant    // The branch resulting from the if statement isn't costly in most cases, where this will     // cut out alot of work intersecting primitives to check for shadows        vector float lightclip = spu_splats((float)LIGHT_CLIPPING);    vector unsigned int magltclip = spu_cmpgt(lightclip, light_color.r);    magltclip = spu_and(magltclip, spu_cmpgt(lightclip, light_color.g));    magltclip = spu_and(magltclip, spu_cmpgt(lightclip, light_color.b));    magltclip = spu_gather(magltclip);        if (spu_extract(magltclip, 0) == 15)      continue;    shit.t = distanceToLight;    shit.nx = shit.ny = shit.nz = zero_v;    // Assuming dirToLight is normalized...    sray.dx = dirToLightx; sray.dy = dirToLighty; sray.dz = dirToLightz;#endif //SHADOWS    mfc_write_tag_mask(1 << DMA_TAG_MATERIALS);    mfc_read_tag_status_all();        materialShade(objects->materials, curr, r, hit, 		  dirToLightx, dirToLighty, dirToLightz, 		  light_color.r, light_color.g, light_color.b,		  changed);#if(SHADOWS)        // Check all primitives for light occlusion    for (int j = 0; sAlloc && (j < objects->num_spheres); j++) {      (*(objects->spheres+j)).intersectPacket(sray, shit, 0.01f);    }    vector unsigned int occluded = spu_cmpgt(distanceToLight, shit.t);    int count  = spu_extract(spu_gather(occluded), 0);    //for (int j = 0; (count < 15) && (objects->cylinders) && (j < objects->num_cylinders); j++) {    //  objects->cylinders[j].intersectPacket(sray, shit, 0.0001f);    //}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?