Primitive sampling
This commit is contained in:
parent
368ae81251
commit
77db3f4ab5
9 changed files with 242 additions and 80 deletions
|
|
@ -35,6 +35,10 @@ bool TrigCache::castRay(const Ray& ray) const {
|
||||||
static halnf a, f, u, v;
|
static halnf a, f, u, v;
|
||||||
static halnf t;
|
static halnf t;
|
||||||
|
|
||||||
|
if (ray.dir.dot(mNormal) > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
h = ray.dir.cross(mEdgeP1P3);
|
h = ray.dir.cross(mEdgeP1P3);
|
||||||
a = mEdgeP1P2.dot(h);
|
a = mEdgeP1P2.dot(h);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ void renderCommand(const String& scenePath) {
|
||||||
|
|
||||||
auto start = get_time();
|
auto start = get_time();
|
||||||
|
|
||||||
rayt.render(scene, output);
|
rayt.render(scene, output, settings);
|
||||||
|
|
||||||
auto end = get_time();
|
auto end = get_time();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,26 +46,68 @@ bool loadMeshes(tp::Scene& scene, const tp::String& objetsPath) {
|
||||||
return scene.mObjects.size();
|
return scene.mObjects.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getVector(lua_State* L, const char* name, tp::Vec3F& out, const char* parent) {
|
// Function to read a Lua table representing RenderSettings
|
||||||
lua_getglobal(L, name);
|
int readRenderSettings(lua_State* L, tp::RayTracer::RenderSettings& settings) {
|
||||||
|
lua_getglobal(L, "RenderSettings");
|
||||||
if (lua_istable(L, -1)) {
|
if (!lua_istable(L, -1)) {
|
||||||
lua_pushstring(L, "x");
|
printf("RenderSettings is not a table.\n");
|
||||||
lua_gettable(L, -2);
|
return 0; // Error
|
||||||
|
|
||||||
if (lua_isnumber(L, -1)) {
|
|
||||||
out.x = lua_tonumber(L, -1);
|
|
||||||
} else {
|
|
||||||
printf("Component of vector '%s' is not found in %s\n\n", name, parent);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
printf("Vector '%s' is not found in %s\n\n", name, parent);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read depth field
|
||||||
|
lua_getfield(L, -1, "depth");
|
||||||
|
if (lua_isnumber(L, -1)) {
|
||||||
|
settings.depth = (int) lua_tonumber(L, -1);
|
||||||
|
} else {
|
||||||
|
printf("RenderSettings 'depth' field is missing or not a number.\n");
|
||||||
|
lua_pop(L, 1); // Pop the 'depth' field
|
||||||
|
return 0; // Error
|
||||||
|
}
|
||||||
|
lua_pop(L, 1); // Pop the 'depth' field
|
||||||
|
|
||||||
|
// Read spray field
|
||||||
|
lua_getfield(L, -1, "spray");
|
||||||
|
if (lua_isnumber(L, -1)) {
|
||||||
|
settings.spray = (int) lua_tonumber(L, -1);
|
||||||
|
} else {
|
||||||
|
printf("RenderSettings 'spray' field is missing or not a number.\n");
|
||||||
|
lua_pop(L, 1); // Pop the 'spray' field
|
||||||
|
return 0; // Error
|
||||||
|
}
|
||||||
|
lua_pop(L, 1); // Pop the 'spray' field
|
||||||
|
|
||||||
|
return 1; // Success
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to read a Lua table representing a light
|
||||||
|
int readLight(lua_State* L, tp::PointLight* light) {
|
||||||
|
lua_getfield(L, -1, "pos"); // Get the "pos" field from the light table
|
||||||
|
if (!lua_istable(L, -1)) {
|
||||||
|
printf("Light is missing the 'pos' table.\n");
|
||||||
|
return 0; // Error
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
lua_rawgeti(L, -1, i + 1); // Index is 1-based in Lua
|
||||||
|
if (!lua_isnumber(L, -1)) {
|
||||||
|
printf("Light 'pos' field is not a number at index %d.\n", i);
|
||||||
|
lua_pop(L, 2); // Pop both the number and the 'pos' table
|
||||||
|
return 0; // Error
|
||||||
|
}
|
||||||
|
light->pos[i] = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1); // Pop the number
|
||||||
|
}
|
||||||
|
lua_pop(L, 1); // Pop the 'pos' table
|
||||||
|
|
||||||
|
lua_getfield(L, -1, "intensity"); // Get the "intensity" field from the light table
|
||||||
|
if (!lua_isnumber(L, -1)) {
|
||||||
|
printf("Light is missing the 'intensity' field or it's not a number.\n");
|
||||||
|
lua_pop(L, 1); // Pop the 'intensity' field
|
||||||
|
return 0; // Error
|
||||||
|
}
|
||||||
|
light->intensity = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1); // Pop the 'intensity' field
|
||||||
|
|
||||||
|
return 1; // Success
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadScene(tp::Scene& scene, const tp::String& scenePath, tp::RayTracer::RenderSettings& settings) {
|
void loadScene(tp::Scene& scene, const tp::String& scenePath, tp::RayTracer::RenderSettings& settings) {
|
||||||
|
|
@ -154,5 +196,38 @@ void loadScene(tp::Scene& scene, const tp::String& scenePath, tp::RayTracer::Ren
|
||||||
scene.mCamera.setFar(100);
|
scene.mCamera.setFar(100);
|
||||||
scene.mCamera.setRatio((tp::halnf) size_y / (tp::halnf) size_x);
|
scene.mCamera.setRatio((tp::halnf) size_y / (tp::halnf) size_x);
|
||||||
|
|
||||||
|
// ---------- LIGHTS
|
||||||
|
{
|
||||||
|
lua_getglobal(L, "Lights");
|
||||||
|
if (!lua_istable(L, -1)) {
|
||||||
|
printf("Lights is not a table.\n");
|
||||||
|
lua_close(L);
|
||||||
|
return; // Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read and process each light in the "Lights" table
|
||||||
|
int numLights = lua_rawlen(L, -1); // Get the number of lights in the table
|
||||||
|
for (int i = 1; i <= numLights; i++) {
|
||||||
|
lua_rawgeti(L, -1, i); // Get the i-th element (light) from the table
|
||||||
|
if (lua_istable(L, -1)) {
|
||||||
|
tp::PointLight light;
|
||||||
|
if (!readLight(L, &light)) {
|
||||||
|
printf("Cant read lights data\n");
|
||||||
|
lua_close(L);
|
||||||
|
return; // Error
|
||||||
|
}
|
||||||
|
scene.mLights.append(light);
|
||||||
|
}
|
||||||
|
lua_pop(L, 1); // Pop the i-th light table
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------- settings --------------
|
||||||
|
if (!readRenderSettings(L, settings)) {
|
||||||
|
printf("Cant Read Render Settings");
|
||||||
|
lua_close(L);
|
||||||
|
return; // Error
|
||||||
|
}
|
||||||
|
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,3 +6,10 @@ Camera = {
|
||||||
size_x = 400,
|
size_x = 400,
|
||||||
size_y = 600,
|
size_y = 600,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lights = {
|
||||||
|
{
|
||||||
|
pos = { 4, 3, 3 },
|
||||||
|
intensity = 4
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
|
@ -11,31 +11,31 @@ v -1.039076 -1.039076 -1.285234
|
||||||
v 1.039076 -1.039076 1.792917
|
v 1.039076 -1.039076 1.792917
|
||||||
v 1.039076 -1.039076 -1.285234
|
v 1.039076 -1.039076 -1.285234
|
||||||
vt 0.625000 0.500000
|
vt 0.625000 0.500000
|
||||||
vt 0.875000 0.500000
|
|
||||||
vt 0.875000 0.750000
|
|
||||||
vt 0.625000 0.750000
|
vt 0.625000 0.750000
|
||||||
|
vt 0.875000 0.750000
|
||||||
|
vt 0.875000 0.500000
|
||||||
vt 0.375000 0.750000
|
vt 0.375000 0.750000
|
||||||
vt 0.625000 1.000000
|
|
||||||
vt 0.375000 1.000000
|
vt 0.375000 1.000000
|
||||||
|
vt 0.625000 1.000000
|
||||||
vt 0.375000 0.000000
|
vt 0.375000 0.000000
|
||||||
vt 0.625000 0.000000
|
|
||||||
vt 0.625000 0.250000
|
|
||||||
vt 0.375000 0.250000
|
vt 0.375000 0.250000
|
||||||
|
vt 0.625000 0.250000
|
||||||
|
vt 0.625000 0.000000
|
||||||
vt 0.125000 0.500000
|
vt 0.125000 0.500000
|
||||||
vt 0.375000 0.500000
|
|
||||||
vt 0.125000 0.750000
|
vt 0.125000 0.750000
|
||||||
vn 0.0000 0.0000 1.0000
|
vt 0.375000 0.500000
|
||||||
vn 1.0000 0.0000 0.0000
|
|
||||||
vn 0.0000 -1.0000 0.0000
|
|
||||||
vn 0.0000 0.0000 -1.0000
|
vn 0.0000 0.0000 -1.0000
|
||||||
vn -1.0000 0.0000 0.0000
|
vn -1.0000 0.0000 0.0000
|
||||||
|
vn 0.0000 1.0000 0.0000
|
||||||
|
vn 0.0000 0.0000 1.0000
|
||||||
|
vn 1.0000 0.0000 0.0000
|
||||||
usemtl Material
|
usemtl Material
|
||||||
s off
|
s off
|
||||||
f 1/1/1 5/2/1 7/3/1 3/4/1
|
f 1/1/1 3/2/1 7/3/1 5/4/1
|
||||||
f 4/5/2 3/4/2 7/6/2 8/7/2
|
f 4/5/2 8/6/2 7/7/2 3/2/2
|
||||||
f 8/8/3 7/9/3 5/10/3 6/11/3
|
f 8/8/3 6/9/3 5/10/3 7/11/3
|
||||||
f 6/12/4 2/13/4 4/5/4 8/14/4
|
f 6/12/4 8/13/4 4/5/4 2/14/4
|
||||||
f 6/11/5 5/10/5 1/1/5 2/13/5
|
f 6/9/5 2/14/5 1/1/5 5/10/5
|
||||||
o Cube.001
|
o Cube.001
|
||||||
v 0.411013 -0.208216 -1.264212
|
v 0.411013 -0.208216 -1.264212
|
||||||
v 0.411013 -0.208216 -0.612621
|
v 0.411013 -0.208216 -0.612621
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,22 @@ Meshes = "meshes.obj"
|
||||||
|
|
||||||
Camera = {
|
Camera = {
|
||||||
pos = { 0.5, 4.5, 0.2 },
|
pos = { 0.5, 4.5, 0.2 },
|
||||||
size_x = 500,
|
size_x = 600,
|
||||||
size_y = 700,
|
size_y = 800,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lights = {
|
||||||
|
{
|
||||||
|
pos = { -0.5, 3.5, 1 },
|
||||||
|
intensity = 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos = { 0, 0, 1 },
|
||||||
|
intensity = 0.5
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderSettings = {
|
||||||
|
depth = 1,
|
||||||
|
spray = 10,
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,38 @@
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (1) {
|
||||||
|
const auto& points = castData.obj->mCache.TransformedPoints;
|
||||||
|
const auto& normals = castData.obj->mCache.TransformedNormals;
|
||||||
|
const auto trig = castData.trig;
|
||||||
|
|
||||||
|
const auto& n1 = normals[trig->mP1];
|
||||||
|
const auto& n2 = normals[trig->mP2];
|
||||||
|
const auto& n3 = normals[trig->mP3];
|
||||||
|
|
||||||
|
auto v0 = points[trig->mP1];
|
||||||
|
auto v1 = points[trig->mP2];
|
||||||
|
auto v2 = points[trig->mP3];
|
||||||
|
|
||||||
|
// Calculate barycentric coordinates
|
||||||
|
Vec3F barycentric;
|
||||||
|
|
||||||
|
// Calculate the area of the triangle
|
||||||
|
auto areaABC = (halnf) (v1 - v0).cross(v2 - v0).length();
|
||||||
|
auto areaPBC = (halnf) (v1 - castData.hitPos).cross(v2 - castData.hitPos).length();
|
||||||
|
auto areaPCA = (halnf) (v2 - castData.hitPos).cross(v0 - castData.hitPos).length();
|
||||||
|
|
||||||
|
// Calculate the barycentric coordinates
|
||||||
|
barycentric.x = areaPBC / areaABC;
|
||||||
|
barycentric.y = areaPCA / areaABC;
|
||||||
|
barycentric.z = 1.0f - barycentric.x - barycentric.y;
|
||||||
|
|
||||||
|
// Interpolate the normal using barycentric coordinates
|
||||||
|
normal = n1 * barycentric.x + n2 * barycentric.y + n3 * barycentric.z;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
using namespace tp;
|
using namespace tp;
|
||||||
|
|
||||||
ModuleManifest* sDependencies[] = {&gModuleMath, &gModuleCommandLine, &gModuleConnection, nullptr};
|
ModuleManifest* sDependencies[] = {&gModuleMath, &gModuleCommandLine, &gModuleConnection, nullptr};
|
||||||
|
|
@ -28,7 +60,7 @@ void RayTracer::castRay(const Ray& ray, RayCastData& out, alnf far) {
|
||||||
|
|
||||||
auto dist = (trig->getHitPos() - ray.pos).length2();
|
auto dist = (trig->getHitPos() - ray.pos).length2();
|
||||||
|
|
||||||
if (far > dist) {
|
if (far > dist && dist > EPSILON) {
|
||||||
out.trig = &trig.data();
|
out.trig = &trig.data();
|
||||||
out.hitPos = trig->getHitPos();
|
out.hitPos = trig->getHitPos();
|
||||||
out.obj = &obj.data();
|
out.obj = &obj.data();
|
||||||
|
|
@ -41,9 +73,58 @@ void RayTracer::castRay(const Ray& ray, RayCastData& out, alnf far) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RayTracer::render(const Scene& scene, RayTracer::RenderBuffer& buff) {
|
void RayTracer::cycle(const RayCastData& castData, LightData& out, uhalni depth) {
|
||||||
|
if (depth) {
|
||||||
|
depth--;
|
||||||
|
|
||||||
|
Vec3F normal = castData.trig->getNormal();
|
||||||
|
normal.normalize();
|
||||||
|
|
||||||
|
const auto delta1 = castData.trig->mEdgeP1P2.unitV();
|
||||||
|
const auto delta2 = normal.cross(delta1);
|
||||||
|
|
||||||
|
for (auto idx : Range(mSettings.spray)) {
|
||||||
|
RayCastData materialCastData;
|
||||||
|
LightData lightData;
|
||||||
|
|
||||||
|
auto d1 = ((halnf) randomFloat() - 0.5f) * 2;
|
||||||
|
auto d2 = ((halnf) randomFloat() - 0.5f) * 2;
|
||||||
|
|
||||||
|
auto sprayNormal = (normal + delta1 * d1 + delta2 * d2).normalize();
|
||||||
|
|
||||||
|
castRay({sprayNormal, castData.hitPos}, materialCastData, mScene->mCamera.getFar());
|
||||||
|
if (materialCastData.hit) {
|
||||||
|
cycle(materialCastData, lightData, depth);
|
||||||
|
out.intensity += lightData.intensity * 0.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cast for light
|
||||||
|
for (auto light : mScene->mLights) {
|
||||||
|
RayCastData lightCastData;
|
||||||
|
auto dir = light->pos - castData.hitPos;
|
||||||
|
auto length = (halnf) dir.length();
|
||||||
|
|
||||||
|
Ray lightRay = {dir.unitV(), castData.hitPos};
|
||||||
|
|
||||||
|
if (lightRay.dir.dot(castData.trig->mNormal) < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
castRay(lightRay, lightCastData, length);
|
||||||
|
|
||||||
|
if (lightCastData.hit) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.intensity += light->intensity / (length * length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RayTracer::render(const Scene& scene, RayTracer::RenderBuffer& buff, const RenderSettings& settings) {
|
||||||
mScene = &scene;
|
mScene = &scene;
|
||||||
mBuff = &buff;
|
mBuff = &buff;
|
||||||
|
mSettings = settings;
|
||||||
|
|
||||||
auto pos = mScene->mCamera.getPos();
|
auto pos = mScene->mCamera.getPos();
|
||||||
auto fov = mScene->mCamera.getFOV();
|
auto fov = mScene->mCamera.getFOV();
|
||||||
|
|
@ -71,54 +152,20 @@ void RayTracer::render(const Scene& scene, RayTracer::RenderBuffer& buff) {
|
||||||
for (RayTracer::RenderBuffer::Index i = 0; i < buff.size().x; i++) {
|
for (RayTracer::RenderBuffer::Index i = 0; i < buff.size().x; i++) {
|
||||||
for (RayTracer::RenderBuffer::Index j = 0; j < buff.size().y; j++) {
|
for (RayTracer::RenderBuffer::Index j = 0; j < buff.size().y; j++) {
|
||||||
iterPoint = planeLeftTop + ((deltaX * (halnf) i) + (deltaY * (halnf) j));
|
iterPoint = planeLeftTop + ((deltaX * (halnf) i) + (deltaY * (halnf) j));
|
||||||
|
|
||||||
ray.dir = (iterPoint - pos).unitV();
|
ray.dir = (iterPoint - pos).unitV();
|
||||||
|
|
||||||
castRay(ray, castData, mScene->mCamera.getFar());
|
castRay(ray, castData, mScene->mCamera.getFar());
|
||||||
|
|
||||||
if (castData.hit) {
|
if (castData.hit) {
|
||||||
Vec3F normal = castData.trig->getNormal();
|
LightData lightData;
|
||||||
|
cycle(castData, lightData, mSettings.depth);
|
||||||
|
|
||||||
if (1) {
|
lightData.intensity = clamp(lightData.intensity, 0.f, 1.f);
|
||||||
const auto& points = castData.obj->mCache.TransformedPoints;
|
RGBA col = {lightData.intensity, lightData.intensity, lightData.intensity, 1.f};
|
||||||
const auto& normals = castData.obj->mCache.TransformedNormals;
|
|
||||||
const auto trig = castData.trig;
|
|
||||||
|
|
||||||
const auto& n1 = normals[trig->mP1];
|
|
||||||
const auto& n2 = normals[trig->mP2];
|
|
||||||
const auto& n3 = normals[trig->mP3];
|
|
||||||
|
|
||||||
auto v0 = points[trig->mP1];
|
|
||||||
auto v1 = points[trig->mP2];
|
|
||||||
auto v2 = points[trig->mP3];
|
|
||||||
|
|
||||||
// Calculate barycentric coordinates
|
|
||||||
Vec3F barycentric;
|
|
||||||
|
|
||||||
// Calculate the area of the triangle
|
|
||||||
auto areaABC = (halnf) (v1 - v0).cross(v2 - v0).length();
|
|
||||||
auto areaPBC = (halnf) (v1 - castData.hitPos).cross(v2 - castData.hitPos).length();
|
|
||||||
auto areaPCA = (halnf) (v2 - castData.hitPos).cross(v0 - castData.hitPos).length();
|
|
||||||
|
|
||||||
// Calculate the barycentric coordinates
|
|
||||||
barycentric.x = areaPBC / areaABC;
|
|
||||||
barycentric.y = areaPCA / areaABC;
|
|
||||||
barycentric.z = 1.0f - barycentric.x - barycentric.y;
|
|
||||||
|
|
||||||
// Interpolate the normal using barycentric coordinates
|
|
||||||
normal = n1 * barycentric.x + n2 * barycentric.y + n3 * barycentric.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
normal.normalize();
|
|
||||||
|
|
||||||
RGBA col = {normal.x * 0.5f + 0.5f, normal.y * 0.5f + 0.5f, normal.z * 0.5f + 0.5f, 1.f};
|
|
||||||
buff.set({i, j}, col);
|
buff.set({i, j}, col);
|
||||||
|
|
||||||
// auto depth = 1 - clamp((halnf) (castData.hitPos - ray.pos).length(), 0.f, mScene->mCamera.getFar()) / mScene->mCamera.getFar();
|
|
||||||
// buff.set({i, j}, {depth, depth, depth, 1.f});
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
buff.set({i, j}, RGBA(0.f, 0.f, 0.f, 0.f));
|
buff.set({i, j}, 0.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,19 @@ namespace tp {
|
||||||
TopologyCache mCache;
|
TopologyCache mCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PointLight {
|
||||||
|
Vec3F pos;
|
||||||
|
halnf fallOut = 1.f;
|
||||||
|
halnf intensity = 1.f;
|
||||||
|
};
|
||||||
|
|
||||||
class Scene {
|
class Scene {
|
||||||
public:
|
public:
|
||||||
Scene() = default;
|
Scene() = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Buffer<Object> mObjects;
|
Buffer<Object> mObjects;
|
||||||
|
Buffer<PointLight> mLights;
|
||||||
Camera mCamera;
|
Camera mCamera;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -35,14 +42,14 @@ namespace tp {
|
||||||
typedef Buffer2D<RGBA> RenderBuffer;
|
typedef Buffer2D<RGBA> RenderBuffer;
|
||||||
|
|
||||||
struct RenderSettings {
|
struct RenderSettings {
|
||||||
alni samplesiPerPixel = 1;
|
uhalni depth = 2;
|
||||||
alni rayBounces = 1;
|
uhalni spray = 1;
|
||||||
Vec2I size;
|
Vec2I size;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RayTracer() = default;
|
RayTracer() = default;
|
||||||
void render(const Scene& scene, RenderBuffer& buff);
|
void render(const Scene& scene, RenderBuffer& buff, const RenderSettings& settings);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct RayCastData {
|
struct RayCastData {
|
||||||
|
|
@ -52,7 +59,13 @@ namespace tp {
|
||||||
bool hit = false;
|
bool hit = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LightData {
|
||||||
|
halnf intensity = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
void castRay(const Ray& ray, RayCastData& out, alnf far);
|
void castRay(const Ray& ray, RayCastData& out, alnf far);
|
||||||
|
void cycle(const RayCastData& ray, LightData& out, uhalni depth);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RenderSettings mSettings;
|
RenderSettings mSettings;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue