Vec3f find_color(Ray ray,Hit hit,Group* group,Camera* camera) { int num_lights = sceneParser->getNumLights(); Vec3f cambient = sceneParser->getAmbientLight(); if (group->intersect(ray, hit, camera->getTMin()))//撞到了 { Vec3f cobject = hit.getMaterial()->getDiffuseColor(); Vec3f canswer = cambient * cobject; Vec3f clight; Vec3f light_dir; Vec3f normal_dir = hit.getNormal(); float distolight; for (int i = 0; i < num_lights; i++) { Light *light = sceneParser->getLight(i); //light_dir : the direction to the light // 该方法用于获得指向光的方向,光的颜色,和到达光的距离 light->getIllumination(hit.getIntersectionPoint(), light_dir, clight, distolight); //cpixel = cambient * cobject + SUMi [ clamped(Li . N) * clighti * cobject ] //返回局部光 canswer = canswer + hit.getMaterial()->Shade(ray, hit, light_dir, clight)*cobject; canswer.Clamp(); } return canswer; } else return sceneParser->getBackgroundColor(); }
Vec3f RayTracer::traceRay(Ray &ray, float tmin, int bounces, float weight, float indexOfRefraction, Hit &hit) const { //printf("当前已有光线:\n"); //RayTree::Print(); Vec3f canswer; if (bounces > max_bounces) return Vec3f(0.0f, 0.0f, 0.0f); Camera *camera = sceneParser->getCamera(); Group *group = sceneParser->getGroup(); int num_lights = sceneParser->getNumLights(); Vec3f cambient = sceneParser->getAmbientLight(); //原来最后是这里出了问题,一旦碰到有转换的物体,那么hit带出来的值是 //转换后的视线看到的值,而非本来视线看到的值 //所以解决方案是:距离不变,根据距离重新计算焦点 if (group->intersect(ray, hit, tmin))//撞到了 { if (is_view_ray) { RayTree::SetMainSegment(ray, 0, hit.getT()); is_view_ray = false; } Vec3f cobject = hit.getMaterial()->getDiffuseColor(); Vec3f hitPoint = hit.getIntersectionPoint(); //环境光部分 canswer = cambient * cobject; Vec3f clight;//光的颜色 Vec3f light_dir;//指向光的方向 Vec3f normal_dir = hit.getNormal();//交点法线向量 float distolight;//距离光源的距离 for (int i = 0; i < num_lights; i++) { Light *light = sceneParser->getLight(i); //light_dir : the direction to the light // 该方法用于获得指向光的方向,光的颜色,和到达光的距离 // 第一个参数传递的是焦点信息 light->getIllumination(hitPoint, light_dir, clight, distolight); Ray ray2(hitPoint, light_dir); Vec3f init_normal(0, 0, 0); Hit hit2(distolight, NULL, init_normal); //阴影检测 if (shadow) { if (group->intersect(ray2, hit2, tmin)){ RayTree::AddShadowSegment(ray2, 0, hit2.getT()); continue; } RayTree::AddShadowSegment(ray2, 0, hit2.getT()); } //cpixel = cambient * cobject + SUMi [ clamped(Li . N) * clighti * cobject ] //返回局部光 canswer = canswer + hit.getMaterial()->Shade(ray, hit, light_dir, clight); } //printf("当前已有光线:\n"); //RayTree::Print(); //反射光 Material *material = hit.getMaterial(); Vec3f rc = material->getReflectiveColor(); if (rc.r() > 0 && rc.g() > 0 && rc.b() > 0) { Vec3f mirrorDir; Vec3f incoming = ray.getDirection(); mirrorDir = mirrorDirection(normal_dir, incoming); // The ray weight is simply multiplied by the magnitude of the reflected color Ray ray3(hitPoint, mirrorDir); Vec3f init_normal(0, 0, 0); Hit hit3(distolight, NULL, init_normal); //忘记乘以本身的反射光系数%………… canswer += traceRay(ray3, tmin, bounces + 1, weight*rc.Length(), indexOfRefraction, hit3)*rc; if (bounces + 1 < max_bounces) RayTree::AddReflectedSegment(ray3, 0, hit3.getT()); } //printf("当前已有光线:\n"); //RayTree::Print(); //从这里开始还都存在问题!!!!! //折射光 Vec3f transmitted; Vec3f tc = material->getTransparentColor(); float index = material->getIndexOfRefraction(); if (tc.r() > 0 && tc.g() > 0 && tc.b() > 0) { Vec3f init_normal(0, 0, 0); Hit hit4(distolight, NULL, init_normal); //在判断折射光的存在之后,要考虑光线的位置:物体内还是物体外 //这里根据normal和incoming的点积来判断 Vec3f incoming = ray.getDirection(); float judge = normal_dir.Dot3(incoming); if (judge < 0)//光线在外 { if (transmittedDirection(normal_dir, incoming, 1, index, transmitted)) { Ray ray4(hitPoint, transmitted); canswer += traceRay(ray4, tmin, bounces+1, weight*rc.Length(), index, hit4)*tc; RayTree::AddTransmittedSegment(ray4, 0, hit4.getT()); } } else//光线在内 { normal_dir.Negate(); if (transmittedDirection(normal_dir, incoming, index, 1, transmitted)) { Ray ray4(hitPoint, transmitted); canswer += traceRay(ray4, tmin, bounces+1, weight*rc.Length(), 1, hit4)*tc; RayTree::AddTransmittedSegment(ray4, 0, hit4.getT()); } } } //printf("当前已有光线:\n"); //RayTree::Print(); } else canswer = sceneParser->getBackgroundColor(); canswer.Clamp(); return canswer; }
//没用 weight Vec3f RayTracer::traceRay(Ray &ray, float tmin, int bounces, float indexOfRefraction, Hit &hit, Grid *grid) const { if(bounces >= max_bounces) return Vec3f(0,0,0); RayTracingStats::IncrementNumNonShadowRays(); //Group *group = s->getGroup(); //group->intersect(ray,hit,tmin); 这里是没用grid的代码 grid->intersect(ray,hit,tmin); if(hit.getMaterial()==NULL) return s->getBackgroundColor(); else { RayTracingStats::IncrementNumShadowRays(); Vec3f col(0,0,0); Vec3f hitPoint = hit.getIntersectionPoint(); Vec3f tempAmb; Vec3f::MultRow(tempAmb,s->getAmbientLight(),hit.getMaterial()->getDiffuse(hitPoint)); //Kd La col += tempAmb; int lightNumber = s->getNumLights(); Light *light; for(int i=0; i<lightNumber; i++) { light = s->getLight(i); Vec3f lightColor; Vec3f dirToLight; //Vec3f interPoint = hit.getIntersectionPoint(); float distanceToLight; light->getIllumination(hitPoint,dirToLight,lightColor,distanceToLight); if(!castShadowRayGrid(hitPoint-ray.getDirection()*EPSILON,dirToLight,distanceToLight,grid)) { Vec3f tempShade = hit.getMaterial()->Shade(ray,hit,dirToLight,lightColor); //diffuse specular col += tempShade; } } if(hit.getMaterial()->isReflect(hitPoint)) { Ray rayReflect(mirrorDirection(hit.getNormal(),ray.getDirection()),hitPoint); Vec3f tempRefl; Hit hit2(1000,NULL,Vec3f(1,1,1)); Vec3f::MultRow(tempRefl,hit.getMaterial()->getReflect(hitPoint),traceRay(rayReflect,tmin,bounces+1,indexOfRefraction,hit2,grid)); //weight,indexOfRefrection col += tempRefl; } if(hit.getMaterial()->isTransparent(hitPoint)) { bool notTotalReflective; Vec3f transmittedDir; if(ray.getDirection().Dot3(hit.getNormal())>0) //ray is inside the object { notTotalReflective = transmittedDirection(hit.getNormal()*(-1.0f),ray.getDirection(),hit.getMaterial()->getIndexOfRefrac(hitPoint),indexOfRefraction,transmittedDir); } else //outside { notTotalReflective = transmittedDirection(hit.getNormal(),ray.getDirection(),indexOfRefraction,hit.getMaterial()->getIndexOfRefrac(hitPoint),transmittedDir); } if(notTotalReflective) { Ray rayTransparent(transmittedDir,hitPoint); Vec3f tempTrans; Hit hit3(10000,NULL,Vec3f(1,1,1)); Vec3f::MultRow(tempTrans,hit.getMaterial()->getTrans(hitPoint),traceRay(rayTransparent,tmin,bounces+1,indexOfRefraction,hit3,grid)); col += tempTrans; } else { Vec3f tempTotalTrans; Vec3f::MultRow(tempTotalTrans,hit.getMaterial()->getTrans(hitPoint),hit.getMaterial()->getDiffuse(hitPoint)); col += tempTotalTrans; } } return col; } }