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 + -
显示快捷键?