-
Notifications
You must be signed in to change notification settings - Fork 3
/
lambient_occlusion.h
148 lines (114 loc) · 2.89 KB
/
lambient_occlusion.h
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#pragma once
#include "lraybank.h"
namespace LM {
class AmbientOcclusion : public RayBank
{
public:
protected:
struct AOSample
{
Vector2 uv;
uint32_t tri_id;
Vector3 pos;
Vector3 normal;
};
enum {MAX_COMPLEX_AO_TEXEL_SAMPLES = 16};
void ProcessAO();
void ProcessAO_LineMT(uint32_t y_offset, int y_section_start);
void ProcessAO_Texel(int tx, int ty, int qmc_variation);
float CalculateAO(int tx, int ty, int qmc_variation, const MiniList &ml);
float CalculateAO_Complex(int tx, int ty, int qmc_variation, const MiniList &ml);
private:
int AO_FindSamplePoints(int tx, int ty, const MiniList &ml, AOSample samples[MAX_COMPLEX_AO_TEXEL_SAMPLES]);
void AO_RandomTexelSample(Vector2 &st, int tx, int ty, int n) const
{
if (n)
{
st.x = Math::randf() + tx;
st.y = Math::randf() + ty;
}
else
{
// fix first to centre of texel
st.x = 0.5f + tx;
st.y = 0.5f + ty;
}
// has to be ranged 0 to 1
st.x /= m_iWidth;
st.y /= m_iHeight;
}
bool AO_FindTexelTriangle(const MiniList &ml, const Vector2 &st, uint32_t &tri_inside, Vector3 &bary) const
{
// barycentric coords.
const UVTri * pUVTri;
for (uint32_t i=0; i<ml.num; i++)
{
tri_inside = m_TriIDs[ml.first + i];
pUVTri = &m_Scene.m_UVTris[tri_inside];
// within?
pUVTri->FindBarycentricCoords(st, bary);
if (BarycentricInside(bary))
{
return true;
}
}
// not inside any triangles
return false;
}
void AO_RandomQMCDirection(Vector3 &dir, const Vector3 &ptNormal, int n, int qmc_variation) const
{
Vector3 push = ptNormal * m_Settings_SurfaceBias; //0.005f;
m_QMC.QMCRandomUnitDir(dir, n, qmc_variation);
// clip?
float dot = dir.dot(ptNormal);
if (dot < 0.0f)
dir = -dir;
// prevent parallel lines
dir += push;
// collision detect
dir.normalize();
}
void AO_RandomQMCRay(Ray &r, const Vector3 &ptNormal, int n, int qmc_variation) const
{
Vector3 push = ptNormal * m_Settings_SurfaceBias; // 0.005f;
// push ray origin
r.o += push;
// RandomUnitDir(r.d);
m_QMC.QMCRandomUnitDir(r.d, n, qmc_variation);
// clip?
float dot = r.d.dot(ptNormal);
if (dot < 0.0f)
{
// make dot always positive for calculations as to the weight given to this hit
//dot = -dot;
r.d = -r.d;
}
// prevent parallel lines
r.d += push;
// r.d = ptNormal;
// collision detect
r.d.normalize();
}
void AO_FindSamplesRandomRay(Ray &r, const Vector3 &ptNormal) const
{
//Vector3 push = ptNormal * m_Settings_AO_ReverseBias; //0.005f;
Vector3 push = ptNormal * m_Settings_SurfaceBias; //0.005f;
// push ray origin
r.o -= push;
RandomUnitDir(r.d);
// clip?
float dot = r.d.dot(ptNormal);
if (dot < 0.0f)
{
// make dot always positive for calculations as to the weight given to this hit
//dot = -dot;
r.d = -r.d;
}
// prevent parallel lines
r.d += push;
// r.d = ptNormal;
// collision detect
r.d.normalize();
}
};
} // namespace