-
Notifications
You must be signed in to change notification settings - Fork 0
/
glight.cpp
132 lines (122 loc) · 3.7 KB
/
glight.cpp
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include "glight.h"
#include "gscene.h"
#include "gutils.h"
#include "gtriangle.h"
using namespace GMath;
GLight::GLight(GLightType lightType, GFColor lColor)
:GGameObject(GGameObject::GGameObjectType::kLight),lightType(lightType),lightColor(lColor)
{
owner = this;
}
GFColor GLight::Le(const GScene &scene, const GSurfaceInteraction &isect, const vec3 &w)
{
return GColor::blackF;
}
GFColor GLight::Sample_Li(const GScene &scene, const GSurfaceInteraction &isect, vec3 &wi, float& pdf)
{
return GColor::blackF;
}
GFColor GDirectionalLight::Sample_Li(const GScene& scene, const GSurfaceInteraction &isect, vec3 &wi, float& pdf)
{
wi = -forward();
pdf = 1;
vec3 pOutside = isect.p + wi * GUtils::worldSize;
vec3 rayDir = pOutside - isect.p;
interval ray_t(0.001, rayDir.length()*0.999);
GRay shadowRay(isect.p, rayDir.normalize());
GSurfaceInteraction newIsect;
newIsect.time = isect.time;
if(!scene.intersect(shadowRay, ray_t, newIsect))
{
return lightColor;
}
return GColor::blackF;
}
GFColor GPointLight::Sample_Li(const GScene& scene, const GSurfaceInteraction &isect, vec3 &wi, float& pdf)
{
vec3 rayDir = (vec3)_position - isect.p;
interval ray_t(0.001, rayDir.length()*0.999);
wi = rayDir;
wi.normalize();
pdf = 1;
GRay shadowRay(isect.p, wi);
GSurfaceInteraction newIsect;
newIsect.time = isect.time;
if(!scene.intersect(shadowRay, ray_t, newIsect))
{
return lightColor / rayDir.length2();
}
return GColor::blackF;
}
GFColor GSkyLight::Le(const GRay &ray)
{
vec3 normalizedDir = ray.dir;
normalizedDir.normalize();
auto t = dot(normalizedDir, vec3::up);
GFColor ret = GColor::blackF;
GFColor sky = vec4f(0.5,0.7,1.0,1.0);
GFColor ground = vec4f(0.68,0.5,0.15,1.0);
GFColor dark = vec4f(0.3, 0.3, 0.2, 1.0);
if(t>=0)
{
ret = GColor::Lerp(sky, ground, t);
}
else
{
ret = GColor::Lerp(dark, ground, -t);
}
return ret;
}
GFColor GDiffuseAreaLight::Le(const GScene& scene, const GSurfaceInteraction &isect, const vec3& w)
{
return (twoSided || dot(isect.normal, w)>0) ? lightColor : GColor::blackF;
}
GFColor GDiffuseAreaLight::Sample_Li(const GScene &scene, const GSurfaceInteraction &isect, vec3 &wi, float &pdf)
{
const GGameObject& self = *this;
GSurfaceInteraction intr = shape->Sample(isect, pdf);
vec3 rayDir = intr.p - isect.p;
if(pdf==0 || rayDir.length2()==0)
{
pdf = 0;
return GColor::blackF;
}
interval ray_t(0.001, rayDir.length()*0.999);
wi = rayDir.normalize();
GRay shadowRay(isect.p, wi); // shadowRay from object to light, wi = (lightPos - objPos).normalize
GSurfaceInteraction newIsect;
newIsect.time = isect.time;
if(!scene.intersect(shadowRay, ray_t, newIsect) || newIsect.light==this)
{
newIsect = intr;
return Le(scene, newIsect, -wi);
}
pdf = 0;
return GColor::blackF;
}
bool GSphereLight::intersect(const GRay &ray, GMath::interval ray_t, GSurfaceInteraction &isect)
{
auto sphere = std::dynamic_pointer_cast<GSphere>(shape);
sphere->center = _position;
if(sphere->intersect(ray, ray_t, isect))
{
isect.model = nullptr;
isect.material = material.get();
isect.material->UpdateShadingNormal(isect);
isect.light = this;
return true;
}
return false;
}
bool GMeshLight::intersect(const GRay &ray, interval ray_t, GSurfaceInteraction &isect)
{
if(shape->intersect(ray, ray_t, isect))
{
isect.model = nullptr;
isect.material = material.get();
isect.material->UpdateShadingNormal(isect);
isect.light = this;
return true;
}
return false;
}