-
Notifications
You must be signed in to change notification settings - Fork 0
/
SpecularMaterial.cc
91 lines (77 loc) · 2.73 KB
/
SpecularMaterial.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "Background.h"
#include "HitRecord.h"
#include "Light.h"
#include "Math.h"
#include "Point.h"
#include "Primitive.h"
#include "Ray.h"
#include "RenderContext.h"
#include "Scene.h"
#include "SpecularMaterial.h"
#include "Vector.h"
#include <cfloat>
using namespace std;
SpecularMaterial::SpecularMaterial(const Color& color, Animation<Color> highlight, Animation<float> Kd, Animation<float> Ka, Animation<float> Kr, Animation<int> exp)
:color(color), highlight(highlight), Kd(Kd), Ka(Ka), Kr(Kr), exp(exp)
{
}
SpecularMaterial::~SpecularMaterial()
{
}
void SpecularMaterial::preprocess(int maxTime)
{
highlight.preprocess(maxTime);
Kd.preprocess(maxTime);
Ka.preprocess(maxTime);
Kr.preprocess(maxTime);
exp.preprocess(maxTime);
}
void SpecularMaterial::shade(Color& result, const RenderContext& context,
const Ray& ray, const HitRecord& hit, const Color& atten, int depth) const
{
double time = context.time();
const Scene* scene = context.getScene();
const vector<Light*>& lights = scene->getLights();
Point hitpos = ray.origin()+ray.direction()*hit.minT();
Vector normal;
hit.getPrimitive()->normal(normal, context, hitpos, ray, hit);
double costheta = Dot(normal, ray.direction());
if(costheta > 0)
normal = -normal;
const Object* world = scene->getObject();
Color light = scene->getAmbient()*Ka(time);
Color specular(0,0,0);
Light*const* begin = &lights[0];
Light*const* end = &lights[0]+lights.size();
while(begin != end){
Color light_color;
Vector light_direction;
double dist = (*begin++)->getLight(light_color, light_direction, context, hitpos);
double cosphi = Dot(normal, light_direction);
if(cosphi > 0){
// Cast shadow rays...
HitRecord shadowhit(dist);
Ray shadowray(hitpos, light_direction);
world->intersect(shadowhit, context, shadowray);
if(!shadowhit.getPrimitive()) // No shadows...
{
Vector h = light_direction - ray.direction(); //halfway vector
h.normalize();
light += light_color*(Kd(time)*cosphi);
double s = pow( Dot(normal, h), exp(time)); //Specular fraction
specular += light_color*s;
}
}
}
result = specular*highlight(time) + light*color;
if(depth < context.getScene()->getMaxRayDepth() && Kr(time) > 0.)
{
double reflet = 2. * Dot(ray.direction(), normal);
Vector rDir = ray.direction() - reflet * normal;
rDir.normalize();
Ray reflection(hitpos, rDir);
Color rcolor;
scene->traceRay(rcolor, context, reflection, atten, depth+1);
result += rcolor * Kr(time);
}
}