-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscene.cpp
More file actions
148 lines (127 loc) · 4.53 KB
/
Copy pathscene.cpp
File metadata and controls
148 lines (127 loc) · 4.53 KB
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
// This is a personal academic project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: https://pvs-studio.com
#include "template.h"
#define PCG_LITTLE_ENDIAN 1 // MSVC/Windows default
#define PCG_FORCE_EMULATED_128BIT_MATH 1
#define __attribute__(x)
#include <pcg_random.hpp>
#define OGT_VOX_IMPLEMENTATION
#include "ogt_vox.h"
#include "scene.h"
#include "MaterialManager.h"
#include "Noise.h"
#include "Sphere.h"
#include "GameGUI.h"
void Scene::Set( const uint x, const uint y, const uint z, const Voxel v )
{
grid[x + y * WORLDSIZE + z * WORLDSIZE2] = v;
}
float3 Scene::SampleAllLights(const Ray& ray, const bool ignoreTransparent, const Context& context) const
{
const std::vector<Light>& lights = GetCurrentLevelR()->m_lights;
const Settings::LightSampler sampler = GetSettingsR().m_lightSampler;
const size_t totalNum = lights.size();
float3 resultColor = float3(0.0f);
const float3 normal = ray.GetNormal();
const float3 point = ray.IntersectionPoint();
for (size_t lightIndex = 0; lightIndex < totalNum; lightIndex++)
{
const Light& light = lights[lightIndex];
const float strength = light.GetImpact(point, normal);
if (strength < sampler.m_lightImpactThreshold)
{
continue;
}
if (!light.IsVisible(this, ray, ignoreTransparent, context))
{
continue;
}
float3 impact = light.m_color * strength;
resultColor += impact;
}
return resultColor;
}
float3 Scene::SampleStochasticLights(const Ray& ray, const bool ignoreTransparent, const Context& context) const
{
// get ray details
const float3 normal = ray.GetNormal();
const float3 point = ray.IntersectionPoint();
// get all lights
const std::vector<Light>& lights = GetCurrentLevelR()->m_lights;
const size_t totalNum = lights.size(); // max possible amount of lights in the level
// extract settings
const Settings::LightSampler sampler = GetSettingsR().m_lightSampler;
const float DETAIL_DISTANCE = GetSettingsR().m_detailDistanceFalloff;
const float falloff = (DETAIL_DISTANCE - ray.m_length) / DETAIL_DISTANCE;
float density = sampler.m_stochasticSamplingDensity.Get();
density *= clamp(falloff, 0.f, 1.f);
density = smoothstep(0.1f, 0.9f, density);
// find lights to sample
const size_t samplesNum = clamp(static_cast<size_t>(static_cast<float>(totalNum) * density), static_cast<size_t>(1), totalNum); // calculate number of lights to be sampled with selected density
// find index of the first light to sample, and then sample the following ones
const size_t start = static_cast<size_t>(RandomFloat() * static_cast<float>(totalNum));
const size_t MAX_ATTEMPTS = min(static_cast<size_t>(sampler.m_maxTotalAttempts.Get()), totalNum);
// init loop values
int validAttempts = 0;
int impactfulAttempts = 0;
size_t attempt = 0;
float3 resultLight = 0;
for (; attempt < MAX_ATTEMPTS; ++attempt)
{
const size_t lightIndex = (start + attempt) % totalNum;
const Light& light = lights[lightIndex];
const float strength = light.GetImpact(point, normal);
if (strength < sampler.m_lightImpactThreshold)
{
continue; // light is too weak to affect this point
}
validAttempts++;
if (validAttempts > samplesNum)
{
break; // got enough samples
}
if (!light.IsVisible(this, ray, ignoreTransparent, context))
{
continue; // light is occluded
}
const float3 impact = light.m_color * strength;
resultLight += impact;
impactfulAttempts++;
}
if (impactfulAttempts > 0)
{
resultLight = (resultLight / (float)attempt) * (float)(totalNum);
}
const float sppweight = sampler.m_historyLightAccumulationWeight.Get() / context.m_spp;
const float historyLen = length(context.m_light);
float3 historyColor = context.m_light;
if (historyLen > 0.01f)
{
historyColor = length(resultLight) * (historyColor / historyLen);
}
resultLight = lerp(resultLight, historyColor, sppweight);
return resultLight;
}
float3 Scene::SampleLights(const Ray& ray, bool ignoreTransparent, const Context& context)
{
if (GetSettingsRW().m_lightSampler.m_useStochasticLightSampling)
{
return SampleStochasticLights(ray, ignoreTransparent, context);
}
else
{
return SampleAllLights(ray, ignoreTransparent, context);
}
}
Voxel Tmpl8::Scene::GetVoxelAt(size_t x, size_t y, size_t z) const
{
return grid[x + y * WORLDSIZE + z * WORLDSIZE2];
}
bool Tmpl8::Scene::IsValidVoxel(size_t x, size_t y, size_t z) const
{
return (x >= 0 && x < WORLDSIZE) && (y >= 0 && y < WORLDSIZE) && (z >= 0 && z < WORLDSIZE);
}
void Tmpl8::Scene::SetVoxelAt(size_t x, size_t y, size_t z, Voxel voxel)
{
grid[x + y * WORLDSIZE + z * WORLDSIZE2] = voxel;
}