Vector getNormal(ItemPtr item, Ray ray, Vector point) { switch(item->type) { case SPHERE: case LIGHT: if(length2(ray.from-item->center)<item->radius * item->radius) { //inside! return fast_normalize(item->center-point); } return fast_normalize(point-item->center); case CHECKER: return item->normal; default: return ZERO; } }
Viewport setupViewport(int x, int y, int w, int h, int animation) { Viewport viewport; Vector forward = fast_normalize(lookAt-(camera+X*animation/40.f)); real distanceToViewport = cot(hFov/2)/2 * w; viewport.hVector = getRight(forward); viewport.vVector = getUp(forward, viewport.hVector)*-1; viewport.ray.from = camera+X*animation/40.f; viewport.ray.ray = forward*distanceToViewport+viewport.hVector*(-w/2+x)+viewport.vVector*(-h/2+y); return viewport; }
Vector getPixelAntialiased(Viewport viewport, Stack * stack, ulong * seed) { Vector totalColor = ZERO; Ray ray = viewport.ray; for(int i=0;i<PIXEL_RUNS;i++) { Vector hError = viewport.hVector*(random(seed)-.5f); Vector vError = viewport.vVector*(random(seed)-.5f); ray.ray = fast_normalize(viewport.ray.ray+(i==0?0:hError+vError)); Vector color = getPixelWithReflection(ray, stack, seed); totalColor += color; } totalColor = totalColor*(1.f/PIXEL_RUNS); return totalColor; }
Distance3f distance_line3(const float3 p, const float3 a, const float3 b) { const float3 bma = b-a; const float3 bma_u = fast_normalize(bma); const float ab = fast_length(bma); const float3 pma = p - a; const float dotf = dot(pma, bma_u); if (dotf < 0) { Distance3f d = { fast_length(pma), a }; return d; } else if (dotf > ab) { Distance3f d = { fast_length(pma), b }; return d; } else { const float dist = fast_length(cross(pma, bma_u)); const float3 pi = a + (bma_u * dotf); Distance3f d = { dist, pi }; return d; } }
Vector getPixel(Ray ray, Stack * stack, real magnitude, real refractiveIndex, int depth, ulong *seed) { ItemPtr item = getClosestItem(ray); if(item==NULL) { return ZERO; } Vector point = getIntersectPoint(item, ray) + ray.from; int specularRoughness = getSpecularRoughness(item, point); Vector normal = getNormal(item, ray, point); Vector diffuseColor = ZERO; Vector specularColor = ZERO; Ray reflection; reflection.ray = reflect(ray.ray, normal); reflection.from = point+(reflection.ray*.001f); if(length2(getDiffuse(item, point))>0 || length2(getSpecular(item, point))>0) { for(int i=0;i<lightNumber;i++) { ItemPtr light = &lights[i]; Vector lightVector = light->center-point; Vector lightPixel = fast_normalize(lightVector); real diffuseFactor = dot(normal, lightPixel); real specularFactor = dot(reflection.ray, lightPixel); if(diffuseFactor>0 || specularFactor>0) { int hitLight=0; Ray movedLightRay; movedLightRay.from=reflection.from; Vector right = getRight(lightPixel); Vector up = getUp(lightPixel, right); for(int i=0;i<SHADOW_RUNS;i++) { //TODO: this can be much faster methinks real r = random(seed)*2-1; real u = random(seed)*sqrt(1-r*r); movedLightRay.ray = fast_normalize(lightVector+right*r*light->radius+up*u*light->radius); ItemPtr closestItem = getClosestItem(movedLightRay); if(closestItem!=NULL && closestItem->type==LIGHT) { hitLight++; } } if(hitLight > 0) { real lightValue = ((real)hitLight) / SHADOW_RUNS; if(diffuseFactor>0) { diffuseFactor *= lightValue; diffuseColor = diffuseColor+light->light*diffuseFactor; } if(specularFactor>0) { specularFactor = lightValue * pow(specularFactor, specularRoughness); specularColor = specularColor+light->light*specularFactor; } } } } } Vector color = (diffuseColor*getDiffuse(item, point)+specularColor*getSpecular(item, point)) * magnitude; if(depth > 0) { Ray refraction; if(getRefraction(item, point)) { refraction.ray = refract(ray.ray, normal, item, refractiveIndex); refraction.from = point+(refraction.ray*.001f); if(length2(refraction.ray)>0) { push(stack, depth-1, refraction, magnitude, getRefraction(item, point)); } } if(getReflection(item, point) > 0) { push(stack, depth-1, reflection, magnitude * getReflection(item, point), refractiveIndex); } } return color; }
Vector getRight(Vector forward) { Vector right = cross(Y, forward); return length2(right)==0 ? X : fast_normalize(right); }