Apply formating to all files. CLeanup
This commit is contained in:
parent
b4ae5dde77
commit
91fb72bd49
928 changed files with 14515 additions and 21479 deletions
|
|
@ -12,89 +12,89 @@
|
|||
using namespace tp;
|
||||
|
||||
void writeImage(const RayTracer::RenderBuffer& output, const char* name) {
|
||||
// Save the data to a PNG file
|
||||
struct urgb {
|
||||
uint1 r, g, b, a;
|
||||
};
|
||||
// Save the data to a PNG file
|
||||
struct urgb {
|
||||
uint1 r, g, b, a;
|
||||
};
|
||||
|
||||
Buffer2D<urgb> converted;
|
||||
converted.reserve(output.size());
|
||||
Buffer2D<urgb> converted;
|
||||
converted.reserve(output.size());
|
||||
|
||||
for (RayTracer::RenderBuffer::Index i = 0; i < output.size().x; i++) {
|
||||
for (RayTracer::RenderBuffer::Index j = 0; j < output.size().y; j++) {
|
||||
converted.get({i, j}).r = uint1(output.get({i, j}).r * 255);
|
||||
converted.get({i, j}).g = uint1(output.get({i, j}).g * 255);
|
||||
converted.get({i, j}).b = uint1(output.get({i, j}).b * 255);
|
||||
converted.get({i, j}).a = uint1(output.get({i, j}).a * 255);
|
||||
}
|
||||
}
|
||||
for (RayTracer::RenderBuffer::Index i = 0; i < output.size().x; i++) {
|
||||
for (RayTracer::RenderBuffer::Index j = 0; j < output.size().y; j++) {
|
||||
converted.get({ i, j }).r = uint1(output.get({ i, j }).r * 255);
|
||||
converted.get({ i, j }).g = uint1(output.get({ i, j }).g * 255);
|
||||
converted.get({ i, j }).b = uint1(output.get({ i, j }).b * 255);
|
||||
converted.get({ i, j }).a = uint1(output.get({ i, j }).a * 255);
|
||||
}
|
||||
}
|
||||
|
||||
if (stbi_write_png(name, converted.size().x, converted.size().y, 4, converted.getBuff(), converted.size().x * 4) != 0) {
|
||||
// Image saved successfully
|
||||
printf("Image saved successfully.\n");
|
||||
} else {
|
||||
printf("Error saving the image.\n");
|
||||
}
|
||||
if (stbi_write_png(name, converted.size().x, converted.size().y, 4, converted.getBuff(), converted.size().x * 4) != 0) {
|
||||
// Image saved successfully
|
||||
printf("Image saved successfully.\n");
|
||||
} else {
|
||||
printf("Error saving the image.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void* printStatus(void* arg) {
|
||||
auto percentage = (const halnf*) arg;
|
||||
auto old = *percentage;
|
||||
while (*percentage < 0.99f) {
|
||||
sleep(500);
|
||||
if (old != *percentage && (*percentage - old) > 0.01) {
|
||||
printf("Progress - %f\n", (*percentage) * 100);
|
||||
old = *percentage;
|
||||
}
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
auto percentage = (const halnf*) arg;
|
||||
auto old = *percentage;
|
||||
while (*percentage < 0.99f) {
|
||||
sleep(500);
|
||||
if (old != *percentage && (*percentage - old) > 0.01) {
|
||||
printf("Progress - %f\n", (*percentage) * 100);
|
||||
old = *percentage;
|
||||
}
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
void renderCommand(const String& scenePath) {
|
||||
Scene scene;
|
||||
Scene scene;
|
||||
|
||||
RayTracer::RenderSettings settings;
|
||||
RayTracer::RenderSettings settings;
|
||||
|
||||
loadScene(scene, scenePath, settings);
|
||||
loadScene(scene, scenePath, settings);
|
||||
|
||||
RayTracer::OutputBuffers output;
|
||||
RayTracer rayt;
|
||||
RayTracer::OutputBuffers output;
|
||||
RayTracer rayt;
|
||||
|
||||
pthread_t my_thread;
|
||||
int ret;
|
||||
pthread_t my_thread;
|
||||
int ret;
|
||||
|
||||
printf("\nStarting Render:\n\n");
|
||||
printf("\nStarting Render:\n\n");
|
||||
|
||||
ret = pthread_create(&my_thread, NULL, &printStatus, &rayt.mProgress.percentage);
|
||||
if (ret != 0) {
|
||||
printf("Error: pthread_create() failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
ret = pthread_create(&my_thread, NULL, &printStatus, &rayt.mProgress.percentage);
|
||||
if (ret != 0) {
|
||||
printf("Error: pthread_create() failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
auto start = get_time();
|
||||
auto start = get_time();
|
||||
|
||||
rayt.render(scene, output, settings);
|
||||
rayt.render(scene, output, settings);
|
||||
|
||||
auto end = get_time();
|
||||
auto end = get_time();
|
||||
|
||||
pthread_join(my_thread, NULL);
|
||||
pthread_join(my_thread, NULL);
|
||||
|
||||
printf("\nRender finished with average render time per sample - %i (ms)\n", end - start);
|
||||
printf("\nRender finished with average render time per sample - %i (ms)\n", end - start);
|
||||
|
||||
writeImage(output.normals, "normals.png");
|
||||
writeImage(output.color, "color.png");
|
||||
writeImage(output.depth, "depth.png");
|
||||
writeImage(output.normals, "normals.png");
|
||||
writeImage(output.color, "color.png");
|
||||
writeImage(output.depth, "depth.png");
|
||||
}
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
tp::ModuleManifest* deps[] = {&gModuleRayTracer, nullptr};
|
||||
tp::ModuleManifest module("Rayt", nullptr, nullptr, deps);
|
||||
tp::ModuleManifest* deps[] = { &gModuleRayTracer, nullptr };
|
||||
tp::ModuleManifest module("Rayt", nullptr, nullptr, deps);
|
||||
|
||||
if (module.initialize()) {
|
||||
renderCommand("scene.lua");
|
||||
if (module.initialize()) {
|
||||
renderCommand("scene.lua");
|
||||
|
||||
module.deinitialize();
|
||||
}
|
||||
module.deinitialize();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,238 +9,238 @@ extern "C" {
|
|||
#include "OBJ_Loader.h"
|
||||
|
||||
bool loadMeshes(tp::Scene& scene, const tp::String& objetsPath) {
|
||||
using namespace tp;
|
||||
using namespace tp;
|
||||
|
||||
objl::Loader Loader;
|
||||
objl::Loader Loader;
|
||||
|
||||
if (!Loader.LoadFile(objetsPath.read())) {
|
||||
std::cout << "Failed to Load File. May have failed to find it or it was not an .obj file.\n";
|
||||
return false;
|
||||
}
|
||||
if (!Loader.LoadFile(objetsPath.read())) {
|
||||
std::cout << "Failed to Load File. May have failed to find it or it was not an .obj file.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& curMesh : Loader.LoadedMeshes) {
|
||||
scene.mObjects.append(Object());
|
||||
for (auto& curMesh : Loader.LoadedMeshes) {
|
||||
scene.mObjects.append(Object());
|
||||
|
||||
auto object = &scene.mObjects.last();
|
||||
auto object = &scene.mObjects.last();
|
||||
|
||||
for (auto& vertex : curMesh.Vertices) {
|
||||
// printf("{ %f, %f, %f }, \n", vertex.Position.X, vertex.Position.Y, vertex.Position.Z);
|
||||
object->mTopology.Points.append(Vec3F {vertex.Position.X, vertex.Position.Y, vertex.Position.Z});
|
||||
object->mTopology.Normals.append(Vec3F {vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z});
|
||||
}
|
||||
for (auto& vertex : curMesh.Vertices) {
|
||||
// printf("{ %f, %f, %f }, \n", vertex.Position.X, vertex.Position.Y, vertex.Position.Z);
|
||||
object->mTopology.Points.append(Vec3F{ vertex.Position.X, vertex.Position.Y, vertex.Position.Z });
|
||||
object->mTopology.Normals.append(Vec3F{ vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z });
|
||||
}
|
||||
|
||||
for (int j = 0; j < curMesh.Indices.size(); j += 3) {
|
||||
int idx1 = (int) curMesh.Indices[j];
|
||||
int idx2 = (int) curMesh.Indices[j + 1];
|
||||
int idx3 = (int) curMesh.Indices[j + 2];
|
||||
// printf("{ %i, %i, %i },\n", idx1, idx2, idx3);
|
||||
object->mTopology.Indexes.append(Vec3I {idx1, idx2, idx3});
|
||||
}
|
||||
for (int j = 0; j < curMesh.Indices.size(); j += 3) {
|
||||
int idx1 = (int) curMesh.Indices[j];
|
||||
int idx2 = (int) curMesh.Indices[j + 1];
|
||||
int idx3 = (int) curMesh.Indices[j + 2];
|
||||
// printf("{ %i, %i, %i },\n", idx1, idx2, idx3);
|
||||
object->mTopology.Indexes.append(Vec3I{ idx1, idx2, idx3 });
|
||||
}
|
||||
|
||||
if (object->mTopology.Normals.size() != object->mTopology.Points.size()) {
|
||||
printf("Logic error loading normals\n");
|
||||
}
|
||||
if (object->mTopology.Normals.size() != object->mTopology.Points.size()) {
|
||||
printf("Logic error loading normals\n");
|
||||
}
|
||||
|
||||
object->mCache.Source = &object->mTopology;
|
||||
object->mCache.updateCache();
|
||||
}
|
||||
object->mCache.Source = &object->mTopology;
|
||||
object->mCache.updateCache();
|
||||
}
|
||||
|
||||
return scene.mObjects.size();
|
||||
return scene.mObjects.size();
|
||||
}
|
||||
|
||||
// Function to read a Lua table representing RenderSettings
|
||||
int readRenderSettings(lua_State* L, tp::RayTracer::RenderSettings& settings) {
|
||||
lua_getglobal(L, "RenderSettings");
|
||||
if (!lua_istable(L, -1)) {
|
||||
printf("RenderSettings is not a table.\n");
|
||||
return 0; // Error
|
||||
}
|
||||
lua_getglobal(L, "RenderSettings");
|
||||
if (!lua_istable(L, -1)) {
|
||||
printf("RenderSettings is not a table.\n");
|
||||
return 0; // Error
|
||||
}
|
||||
|
||||
// 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 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
|
||||
// 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
|
||||
|
||||
// Read depth field
|
||||
lua_getfield(L, -1, "multisampling");
|
||||
if (lua_isnumber(L, -1)) {
|
||||
settings.multisampling = (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 depth field
|
||||
lua_getfield(L, -1, "multisampling");
|
||||
if (lua_isnumber(L, -1)) {
|
||||
settings.multisampling = (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
|
||||
|
||||
return 1; // Success
|
||||
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, "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
|
||||
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
|
||||
return 1; // Success
|
||||
}
|
||||
|
||||
void loadScene(tp::Scene& scene, const tp::String& scenePath, tp::RayTracer::RenderSettings& settings) {
|
||||
lua_State* L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
lua_State* L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
|
||||
if (luaL_dofile(L, "script.lua") != 0) {
|
||||
lua_close(L);
|
||||
printf("Cant open scene script.\n");
|
||||
return;
|
||||
}
|
||||
if (luaL_dofile(L, "script.lua") != 0) {
|
||||
lua_close(L);
|
||||
printf("Cant open scene script.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lua_getglobal(L, "Meshes");
|
||||
lua_getglobal(L, "Meshes");
|
||||
|
||||
if (lua_isstring(L, -1)) {
|
||||
tp::String meshesPath = lua_tostring(L, -1);
|
||||
if (lua_isstring(L, -1)) {
|
||||
tp::String meshesPath = lua_tostring(L, -1);
|
||||
|
||||
if (!loadMeshes(scene, meshesPath)) {
|
||||
printf("No 'meshes' loaded - check ur .obj path and validate content of .obj .\n");
|
||||
return;
|
||||
}
|
||||
if (!loadMeshes(scene, meshesPath)) {
|
||||
printf("No 'meshes' loaded - check ur .obj path and validate content of .obj .\n");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
printf("No 'meshes' path given.\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
printf("No 'meshes' path given.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// --- camera
|
||||
// --- camera
|
||||
|
||||
// Access Camera table
|
||||
lua_getglobal(L, "Camera");
|
||||
if (!lua_istable(L, -1)) {
|
||||
printf("Camera is not a table.\n");
|
||||
lua_close(L);
|
||||
return;
|
||||
}
|
||||
// Access Camera table
|
||||
lua_getglobal(L, "Camera");
|
||||
if (!lua_istable(L, -1)) {
|
||||
printf("Camera is not a table.\n");
|
||||
lua_close(L);
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify you are inside the "Camera" table
|
||||
int cameraTableIndex = lua_gettop(L); // Get the index of the "Camera" table
|
||||
// Verify you are inside the "Camera" table
|
||||
int cameraTableIndex = lua_gettop(L); // Get the index of the "Camera" table
|
||||
|
||||
// Access the "pos" field and validate it
|
||||
lua_getfield(L, cameraTableIndex, "pos");
|
||||
if (!lua_istable(L, -1) || lua_rawlen(L, -1) != 3) {
|
||||
printf("Invalid 'pos' field in Camera table.\n");
|
||||
lua_close(L);
|
||||
return;
|
||||
}
|
||||
// Access the "pos" field and validate it
|
||||
lua_getfield(L, cameraTableIndex, "pos");
|
||||
if (!lua_istable(L, -1) || lua_rawlen(L, -1) != 3) {
|
||||
printf("Invalid 'pos' field in Camera table.\n");
|
||||
lua_close(L);
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the values from the table
|
||||
float pos[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
lua_rawgeti(L, -1, i + 1);
|
||||
if (lua_isnumber(L, -1)) {
|
||||
pos[i] = lua_tonumber(L, -1);
|
||||
} else {
|
||||
printf("Invalid 'pos' field value at index %d.\n", i + 1);
|
||||
lua_close(L);
|
||||
return;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
// Read the values from the table
|
||||
float pos[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
lua_rawgeti(L, -1, i + 1);
|
||||
if (lua_isnumber(L, -1)) {
|
||||
pos[i] = lua_tonumber(L, -1);
|
||||
} else {
|
||||
printf("Invalid 'pos' field value at index %d.\n", i + 1);
|
||||
lua_close(L);
|
||||
return;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// Access the "size_x" field and validate it
|
||||
lua_getfield(L, cameraTableIndex, "size_x");
|
||||
if (!lua_isnumber(L, -1)) {
|
||||
printf("Invalid or missing 'size_x' field in Camera table.\n");
|
||||
lua_close(L);
|
||||
return;
|
||||
}
|
||||
int size_x = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1); // Pop the 'size_x' value from the stack
|
||||
// Access the "size_x" field and validate it
|
||||
lua_getfield(L, cameraTableIndex, "size_x");
|
||||
if (!lua_isnumber(L, -1)) {
|
||||
printf("Invalid or missing 'size_x' field in Camera table.\n");
|
||||
lua_close(L);
|
||||
return;
|
||||
}
|
||||
int size_x = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1); // Pop the 'size_x' value from the stack
|
||||
|
||||
// Access the "size_y" field and validate it
|
||||
lua_getfield(L, cameraTableIndex, "size_y");
|
||||
if (!lua_isnumber(L, -1)) {
|
||||
printf("Invalid or missing 'size_y' field in Camera table.\n");
|
||||
lua_close(L);
|
||||
return;
|
||||
}
|
||||
int size_y = lua_tointeger(L, -1);
|
||||
// Access the "size_y" field and validate it
|
||||
lua_getfield(L, cameraTableIndex, "size_y");
|
||||
if (!lua_isnumber(L, -1)) {
|
||||
printf("Invalid or missing 'size_y' field in Camera table.\n");
|
||||
lua_close(L);
|
||||
return;
|
||||
}
|
||||
int size_y = lua_tointeger(L, -1);
|
||||
|
||||
settings.size = {(tp::halnf) size_x, (tp::halnf) size_y};
|
||||
settings.size = { (tp::halnf) size_x, (tp::halnf) size_y };
|
||||
|
||||
scene.mCamera.lookAtPoint({0, 0, 0}, {pos[0], pos[1], pos[2]}, {0, 0, 1});
|
||||
scene.mCamera.setFOV(3.14 / 4);
|
||||
scene.mCamera.setFar(100);
|
||||
scene.mCamera.setRatio((tp::halnf) size_y / (tp::halnf) size_x);
|
||||
scene.mCamera.lookAtPoint({ 0, 0, 0 }, { pos[0], pos[1], pos[2] }, { 0, 0, 1 });
|
||||
scene.mCamera.setFOV(3.14 / 4);
|
||||
scene.mCamera.setFar(100);
|
||||
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
|
||||
}
|
||||
// ---------- 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
|
||||
}
|
||||
}
|
||||
// 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
|
||||
}
|
||||
// ----------- settings --------------
|
||||
if (!readRenderSettings(L, settings)) {
|
||||
printf("Cant Read Render Settings");
|
||||
lua_close(L);
|
||||
return; // Error
|
||||
}
|
||||
|
||||
lua_close(L);
|
||||
lua_close(L);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,198 +44,195 @@ normal = n1 * barycentric.x + n2 * barycentric.y + n3 * barycentric.z;
|
|||
|
||||
using namespace tp;
|
||||
|
||||
ModuleManifest* sDependencies[] = {&gModuleMath, &gModuleCommandLine, &gModuleConnection, nullptr};
|
||||
ModuleManifest* sDependencies[] = { &gModuleMath, &gModuleCommandLine, &gModuleConnection, nullptr };
|
||||
|
||||
ModuleManifest tp::gModuleRayTracer = ModuleManifest("RayTracer", nullptr, nullptr, sDependencies);
|
||||
|
||||
void RayTracer::castRay(const Ray& ray, RayCastData& out, alnf far) {
|
||||
out.hit = false;
|
||||
out.hit = false;
|
||||
|
||||
far *= far;
|
||||
far *= far;
|
||||
|
||||
for (auto obj : mScene->mObjects) {
|
||||
for (auto trig : obj->mCache.TrigCaches) {
|
||||
if (trig->castRay(ray)) {
|
||||
// printf("Hit\n");
|
||||
for (auto obj : mScene->mObjects) {
|
||||
for (auto trig : obj->mCache.TrigCaches) {
|
||||
if (trig->castRay(ray)) {
|
||||
// printf("Hit\n");
|
||||
|
||||
auto dist = (trig->getHitPos() - ray.pos).length2();
|
||||
auto dist = (trig->getHitPos() - ray.pos).length2();
|
||||
|
||||
if (far > dist && dist > EPSILON) {
|
||||
out.trig = &trig.data();
|
||||
out.hitPos = trig->getHitPos();
|
||||
out.obj = &obj.data();
|
||||
out.hit = true;
|
||||
if (far > dist && dist > EPSILON) {
|
||||
out.trig = &trig.data();
|
||||
out.hitPos = trig->getHitPos();
|
||||
out.obj = &obj.data();
|
||||
out.hit = true;
|
||||
|
||||
far = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
far = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RayTracer::cycle(const RayCastData& castData, LightData& out, uhalni depth) {
|
||||
if (depth) {
|
||||
depth--;
|
||||
if (depth) {
|
||||
depth--;
|
||||
|
||||
Vec3F normal = castData.trig->getNormal();
|
||||
normal.normalize();
|
||||
Vec3F normal = castData.trig->getNormal();
|
||||
normal.normalize();
|
||||
|
||||
const auto delta1 = castData.trig->mEdgeP1P2.unitV();
|
||||
const auto delta2 = normal.cross(delta1);
|
||||
const auto delta1 = castData.trig->mEdgeP1P2.unitV();
|
||||
const auto delta2 = normal.cross(delta1);
|
||||
|
||||
for (auto idx : Range(mSettings.spray)) {
|
||||
RayCastData materialCastData;
|
||||
LightData lightData;
|
||||
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 d1 = ((halnf) randomFloat() - 0.5f) * 2;
|
||||
auto d2 = ((halnf) randomFloat() - 0.5f) * 2;
|
||||
|
||||
auto sprayNormal = (normal + delta1 * d1 + delta2 * d2).normalize();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
// 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};
|
||||
Ray lightRay = { dir.unitV(), castData.hitPos };
|
||||
|
||||
if (lightRay.dir.dot(castData.trig->mNormal) < 0) {
|
||||
continue;
|
||||
}
|
||||
castRay(lightRay, lightCastData, length);
|
||||
if (lightRay.dir.dot(castData.trig->mNormal) < 0) {
|
||||
continue;
|
||||
}
|
||||
castRay(lightRay, lightCastData, length);
|
||||
|
||||
if (lightCastData.hit) {
|
||||
continue;
|
||||
}
|
||||
if (lightCastData.hit) {
|
||||
continue;
|
||||
}
|
||||
|
||||
out.intensity += light->intensity / (length * length);
|
||||
}
|
||||
out.intensity += light->intensity / (length * length);
|
||||
}
|
||||
}
|
||||
|
||||
void RayTracer::render(const Scene& scene, OutputBuffers& out, const RenderSettings& settings) {
|
||||
out.color.reserve({settings.size.x, settings.size.y});
|
||||
out.normals.reserve({settings.size.x, settings.size.y});
|
||||
out.depth.reserve({settings.size.x, settings.size.y});
|
||||
out.color.reserve({ settings.size.x, settings.size.y });
|
||||
out.normals.reserve({ settings.size.x, settings.size.y });
|
||||
out.depth.reserve({ settings.size.x, settings.size.y });
|
||||
|
||||
mScene = &scene;
|
||||
mSettings = settings;
|
||||
mScene = &scene;
|
||||
mSettings = settings;
|
||||
|
||||
auto pos = mScene->mCamera.getPos();
|
||||
auto fov = mScene->mCamera.getFOV();
|
||||
auto height = sqrt(mScene->mCamera.getRatio());
|
||||
auto width = 1.f / height;
|
||||
auto forward = mScene->mCamera.getForward();
|
||||
auto up = mScene->mCamera.getUp();
|
||||
auto right = forward.cross(up);
|
||||
auto planeCenter = pos + (forward * halnf(width / (2.f * tan(fov / 2.f))));
|
||||
auto planeCenterOffset = (up * (halnf) height / 2.f) - (right * (halnf) width / 2.f);
|
||||
auto pos = mScene->mCamera.getPos();
|
||||
auto fov = mScene->mCamera.getFOV();
|
||||
auto height = sqrt(mScene->mCamera.getRatio());
|
||||
auto width = 1.f / height;
|
||||
auto forward = mScene->mCamera.getForward();
|
||||
auto up = mScene->mCamera.getUp();
|
||||
auto right = forward.cross(up);
|
||||
auto planeCenter = pos + (forward * halnf(width / (2.f * tan(fov / 2.f))));
|
||||
auto planeCenterOffset = (up * (halnf) height / 2.f) - (right * (halnf) width / 2.f);
|
||||
|
||||
auto planeLeftTop = planeCenter + planeCenterOffset;
|
||||
auto planeLeftTop = planeCenter + planeCenterOffset;
|
||||
|
||||
RayCastData castData;
|
||||
RayCastData castData;
|
||||
|
||||
Ray ray = {
|
||||
{0, 0, 0},
|
||||
pos
|
||||
};
|
||||
Ray ray = { { 0, 0, 0 }, pos };
|
||||
|
||||
Vec3F iterPoint = {0, 0, 0};
|
||||
Vec3F deltaX = right * halnf(width / (alnf) mSettings.size.x);
|
||||
Vec3F deltaY = up * halnf(-height / (alnf) mSettings.size.y);
|
||||
Vec3F iterPoint = { 0, 0, 0 };
|
||||
Vec3F deltaX = right * halnf(width / (alnf) mSettings.size.x);
|
||||
Vec3F deltaY = up * halnf(-height / (alnf) mSettings.size.y);
|
||||
|
||||
ualni maxIterations = mSettings.size.x * mSettings.size.y;
|
||||
ualni currIter = 0;
|
||||
ualni maxIterations = mSettings.size.x * mSettings.size.y;
|
||||
ualni currIter = 0;
|
||||
|
||||
halnf maxDepth = 0;
|
||||
halnf minDepth = mScene->mCamera.getFar() * mSettings.multisampling;
|
||||
halnf maxDepth = 0;
|
||||
halnf minDepth = mScene->mCamera.getFar() * mSettings.multisampling;
|
||||
|
||||
auto accumulateColor = [](RGBA& col, const RGBA& in) {
|
||||
col.r += in.r;
|
||||
col.g += in.g;
|
||||
col.b += in.b;
|
||||
col.a = 1;
|
||||
};
|
||||
auto accumulateColor = [](RGBA& col, const RGBA& in) {
|
||||
col.r += in.r;
|
||||
col.g += in.g;
|
||||
col.b += in.b;
|
||||
col.a = 1;
|
||||
};
|
||||
|
||||
auto divideColor = [](RGBA& col, const halnf num) {
|
||||
col.r /= num;
|
||||
col.g /= num;
|
||||
col.b /= num;
|
||||
};
|
||||
auto divideColor = [](RGBA& col, const halnf num) {
|
||||
col.r /= num;
|
||||
col.g /= num;
|
||||
col.b /= num;
|
||||
};
|
||||
|
||||
for (auto i = 0; i < mSettings.size.x; i++) {
|
||||
for (auto j = 0; j < mSettings.size.y; j++) {
|
||||
for (auto sample = 0; sample < mSettings.multisampling; sample++) {
|
||||
auto randX = randomFloat();
|
||||
auto randY = randomFloat();
|
||||
for (auto i = 0; i < mSettings.size.x; i++) {
|
||||
for (auto j = 0; j < mSettings.size.y; j++) {
|
||||
for (auto sample = 0; sample < mSettings.multisampling; sample++) {
|
||||
auto randX = randomFloat();
|
||||
auto randY = randomFloat();
|
||||
|
||||
iterPoint = planeLeftTop + ((deltaX * (halnf) (i + randX)) + (deltaY * (halnf) (j + randY)));
|
||||
ray.dir = (iterPoint - pos).unitV();
|
||||
iterPoint = planeLeftTop + ((deltaX * (halnf) (i + randX)) + (deltaY * (halnf) (j + randY)));
|
||||
ray.dir = (iterPoint - pos).unitV();
|
||||
|
||||
castRay(ray, castData, mScene->mCamera.getFar());
|
||||
castRay(ray, castData, mScene->mCamera.getFar());
|
||||
|
||||
if (castData.hit) {
|
||||
LightData lightData;
|
||||
cycle(castData, lightData, mSettings.depth);
|
||||
if (castData.hit) {
|
||||
LightData lightData;
|
||||
cycle(castData, lightData, mSettings.depth);
|
||||
|
||||
const auto normal = castData.trig->getNormal();
|
||||
const auto depth = (halnf) (castData.hitPos - ray.pos).length();
|
||||
const auto normal = castData.trig->getNormal();
|
||||
const auto depth = (halnf) (castData.hitPos - ray.pos).length();
|
||||
|
||||
lightData.intensity = clamp(lightData.intensity, 0.f, 1.f);
|
||||
RGBA col = {lightData.intensity, lightData.intensity, lightData.intensity, 1.f};
|
||||
lightData.intensity = clamp(lightData.intensity, 0.f, 1.f);
|
||||
RGBA col = { lightData.intensity, lightData.intensity, lightData.intensity, 1.f };
|
||||
|
||||
accumulateColor(out.color.get({i, j}), col);
|
||||
accumulateColor(out.normals.get({i, j}), {normal.x * 0.5f + 0.5f, normal.y * 0.5f + 0.5f, normal.z * 0.5f + 0.5f, 1.f});
|
||||
accumulateColor(out.depth.get({i, j}), {depth, depth, depth, 1.f});
|
||||
accumulateColor(out.color.get({ i, j }), col);
|
||||
accumulateColor(out.normals.get({ i, j }), { normal.x * 0.5f + 0.5f, normal.y * 0.5f + 0.5f, normal.z * 0.5f + 0.5f, 1.f });
|
||||
accumulateColor(out.depth.get({ i, j }), { depth, depth, depth, 1.f });
|
||||
|
||||
} else {
|
||||
out.color.set({i, j}, 0.f);
|
||||
out.normals.set({i, j}, 0.f);
|
||||
out.depth.set({i, j}, 0.f);
|
||||
}
|
||||
} else {
|
||||
out.color.set({ i, j }, 0.f);
|
||||
out.normals.set({ i, j }, 0.f);
|
||||
out.depth.set({ i, j }, 0.f);
|
||||
}
|
||||
|
||||
// auto tmp = buff.get({i, j});
|
||||
// printf(" %f, %f, %f, %f, ", tmp.r, tmp.g, tmp.b, tmp.a);
|
||||
}
|
||||
// auto tmp = buff.get({i, j});
|
||||
// printf(" %f, %f, %f, %f, ", tmp.r, tmp.g, tmp.b, tmp.a);
|
||||
}
|
||||
|
||||
mProgress.percentage = (halnf) currIter / (halnf) maxIterations;
|
||||
currIter++;
|
||||
}
|
||||
}
|
||||
mProgress.percentage = (halnf) currIter / (halnf) maxIterations;
|
||||
currIter++;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = 0; i < mSettings.size.x * mSettings.size.y; i++) {
|
||||
divideColor(out.color.getBuff()[i], (halnf) mSettings.multisampling);
|
||||
divideColor(out.normals.getBuff()[i], (halnf) mSettings.multisampling);
|
||||
divideColor(out.depth.getBuff()[i], (halnf) mSettings.multisampling);
|
||||
}
|
||||
for (auto i = 0; i < mSettings.size.x * mSettings.size.y; i++) {
|
||||
divideColor(out.color.getBuff()[i], (halnf) mSettings.multisampling);
|
||||
divideColor(out.normals.getBuff()[i], (halnf) mSettings.multisampling);
|
||||
divideColor(out.depth.getBuff()[i], (halnf) mSettings.multisampling);
|
||||
}
|
||||
|
||||
for (auto i = 0; i < mSettings.size.x * mSettings.size.y; i++) {
|
||||
if (!out.depth.getBuff()[i].a) {
|
||||
continue;
|
||||
}
|
||||
const auto depth = out.depth.getBuff()[i].r;
|
||||
if (maxDepth < depth) {
|
||||
maxDepth = depth;
|
||||
}
|
||||
if (minDepth > depth) {
|
||||
minDepth = depth;
|
||||
}
|
||||
}
|
||||
for (auto i = 0; i < mSettings.size.x * mSettings.size.y; i++) {
|
||||
if (!out.depth.getBuff()[i].a) {
|
||||
continue;
|
||||
}
|
||||
const auto depth = out.depth.getBuff()[i].r;
|
||||
if (maxDepth < depth) {
|
||||
maxDepth = depth;
|
||||
}
|
||||
if (minDepth > depth) {
|
||||
minDepth = depth;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = 0; i < mSettings.size.x * mSettings.size.y; i++) {
|
||||
auto& col = out.depth.getBuff()[i];
|
||||
if (col.a == 1.f) {
|
||||
col.r = (col.r - minDepth) / (maxDepth - minDepth);
|
||||
col.g = col.r;
|
||||
col.b = col.r;
|
||||
}
|
||||
}
|
||||
for (auto i = 0; i < mSettings.size.x * mSettings.size.y; i++) {
|
||||
auto& col = out.depth.getBuff()[i];
|
||||
if (col.a == 1.f) {
|
||||
col.r = (col.r - minDepth) / (maxDepth - minDepth);
|
||||
col.g = col.r;
|
||||
col.b = col.r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,77 +10,77 @@
|
|||
|
||||
namespace tp {
|
||||
|
||||
extern ModuleManifest gModuleRayTracer;
|
||||
extern ModuleManifest gModuleRayTracer;
|
||||
|
||||
class Object {
|
||||
public:
|
||||
Object() = default;
|
||||
class Object {
|
||||
public:
|
||||
Object() = default;
|
||||
|
||||
public:
|
||||
Topology mTopology;
|
||||
TopologyCache mCache;
|
||||
};
|
||||
public:
|
||||
Topology mTopology;
|
||||
TopologyCache mCache;
|
||||
};
|
||||
|
||||
struct PointLight {
|
||||
Vec3F pos;
|
||||
halnf fallOut = 1.f;
|
||||
halnf intensity = 1.f;
|
||||
};
|
||||
struct PointLight {
|
||||
Vec3F pos;
|
||||
halnf fallOut = 1.f;
|
||||
halnf intensity = 1.f;
|
||||
};
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
Scene() = default;
|
||||
class Scene {
|
||||
public:
|
||||
Scene() = default;
|
||||
|
||||
public:
|
||||
Buffer<Object> mObjects;
|
||||
Buffer<PointLight> mLights;
|
||||
Camera mCamera;
|
||||
};
|
||||
public:
|
||||
Buffer<Object> mObjects;
|
||||
Buffer<PointLight> mLights;
|
||||
Camera mCamera;
|
||||
};
|
||||
|
||||
class RayTracer {
|
||||
public:
|
||||
typedef Buffer2D<RGBA> RenderBuffer;
|
||||
class RayTracer {
|
||||
public:
|
||||
typedef Buffer2D<RGBA> RenderBuffer;
|
||||
|
||||
struct Progress {
|
||||
halnf percentage = 0.f;
|
||||
} mProgress;
|
||||
struct Progress {
|
||||
halnf percentage = 0.f;
|
||||
} mProgress;
|
||||
|
||||
struct RenderSettings {
|
||||
uhalni depth = 2;
|
||||
uhalni spray = 1;
|
||||
ualni multisampling = 1;
|
||||
Vec2I size;
|
||||
};
|
||||
struct RenderSettings {
|
||||
uhalni depth = 2;
|
||||
uhalni spray = 1;
|
||||
ualni multisampling = 1;
|
||||
Vec2I size;
|
||||
};
|
||||
|
||||
struct OutputBuffers {
|
||||
RenderBuffer normals;
|
||||
RenderBuffer color;
|
||||
RenderBuffer depth;
|
||||
// albedo, reflectance ...
|
||||
};
|
||||
struct OutputBuffers {
|
||||
RenderBuffer normals;
|
||||
RenderBuffer color;
|
||||
RenderBuffer depth;
|
||||
// albedo, reflectance ...
|
||||
};
|
||||
|
||||
public:
|
||||
RayTracer() = default;
|
||||
void render(const Scene& scene, OutputBuffers& out, const RenderSettings& settings);
|
||||
public:
|
||||
RayTracer() = default;
|
||||
void render(const Scene& scene, OutputBuffers& out, const RenderSettings& settings);
|
||||
|
||||
private:
|
||||
struct RayCastData {
|
||||
const Object* obj = nullptr;
|
||||
TrigCache* trig = nullptr;
|
||||
Vec3F hitPos = {0, 0, 0};
|
||||
bool hit = false;
|
||||
};
|
||||
private:
|
||||
struct RayCastData {
|
||||
const Object* obj = nullptr;
|
||||
TrigCache* trig = nullptr;
|
||||
Vec3F hitPos = { 0, 0, 0 };
|
||||
bool hit = false;
|
||||
};
|
||||
|
||||
struct LightData {
|
||||
halnf intensity = 0;
|
||||
};
|
||||
struct LightData {
|
||||
halnf intensity = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
void castRay(const Ray& ray, RayCastData& out, alnf far);
|
||||
void cycle(const RayCastData& ray, LightData& out, uhalni depth);
|
||||
private:
|
||||
void castRay(const Ray& ray, RayCastData& out, alnf far);
|
||||
void cycle(const RayCastData& ray, LightData& out, uhalni depth);
|
||||
|
||||
private:
|
||||
RenderSettings mSettings;
|
||||
const Scene* mScene = nullptr;
|
||||
};
|
||||
private:
|
||||
RenderSettings mSettings;
|
||||
const Scene* mScene = nullptr;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,117 +10,114 @@
|
|||
using namespace tp;
|
||||
|
||||
void writeImage(const RayTracer::RenderBuffer& output) {
|
||||
// Save the data to a PNG file
|
||||
struct urgb {
|
||||
uint1 r, g, b, a;
|
||||
};
|
||||
// Save the data to a PNG file
|
||||
struct urgb {
|
||||
uint1 r, g, b, a;
|
||||
};
|
||||
|
||||
Buffer2D<urgb> converted;
|
||||
converted.reserve(output.size());
|
||||
Buffer2D<urgb> converted;
|
||||
converted.reserve(output.size());
|
||||
|
||||
for (RayTracer::RenderBuffer::Index i = 0; i < output.size().x; i++) {
|
||||
for (RayTracer::RenderBuffer::Index j = 0; j < output.size().y; j++) {
|
||||
converted.get({i, j}).r = uint1(output.get({i, j}).r * 255);
|
||||
converted.get({i, j}).g = uint1(output.get({i, j}).g * 255);
|
||||
converted.get({i, j}).b = uint1(output.get({i, j}).b * 255);
|
||||
converted.get({i, j}).a = uint1(output.get({i, j}).a * 255);
|
||||
}
|
||||
}
|
||||
for (RayTracer::RenderBuffer::Index i = 0; i < output.size().x; i++) {
|
||||
for (RayTracer::RenderBuffer::Index j = 0; j < output.size().y; j++) {
|
||||
converted.get({ i, j }).r = uint1(output.get({ i, j }).r * 255);
|
||||
converted.get({ i, j }).g = uint1(output.get({ i, j }).g * 255);
|
||||
converted.get({ i, j }).b = uint1(output.get({ i, j }).b * 255);
|
||||
converted.get({ i, j }).a = uint1(output.get({ i, j }).a * 255);
|
||||
}
|
||||
}
|
||||
|
||||
stbi_write_png("output.png", converted.size().x, converted.size().y, 4, converted.getBuff(), converted.size().x * 4);
|
||||
stbi_write_png("output.png", converted.size().x, converted.size().y, 4, converted.getBuff(), converted.size().x * 4);
|
||||
}
|
||||
|
||||
bool compareCols(const RGBA& l, const RGBA& r) {
|
||||
auto small = 0.0001f;
|
||||
if ((l.r - r.r) > small) {
|
||||
return false;
|
||||
}
|
||||
if ((l.g - r.g) > small) {
|
||||
return false;
|
||||
}
|
||||
if ((l.b - r.b) > small) {
|
||||
return false;
|
||||
}
|
||||
if ((l.a - r.a) > small) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
auto small = 0.0001f;
|
||||
if ((l.r - r.r) > small) {
|
||||
return false;
|
||||
}
|
||||
if ((l.g - r.g) > small) {
|
||||
return false;
|
||||
}
|
||||
if ((l.b - r.b) > small) {
|
||||
return false;
|
||||
}
|
||||
if ((l.a - r.a) > small) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void testRT() {
|
||||
using namespace tp;
|
||||
using namespace tp;
|
||||
|
||||
Scene scene;
|
||||
Scene scene;
|
||||
|
||||
scene.mCamera.lookAtPoint({0, 0, 0}, {2, 2, 2}, {0, 0, 1});
|
||||
scene.mCamera.setFOV(3.14 / 4);
|
||||
scene.mCamera.lookAtPoint({ 0, 0, 0 }, { 2, 2, 2 }, { 0, 0, 1 });
|
||||
scene.mCamera.setFOV(3.14 / 4);
|
||||
|
||||
scene.mLights.append({
|
||||
{0, 0, 1.1f},
|
||||
1.f, 0.3f
|
||||
});
|
||||
scene.mLights.append({ { 0, 0, 1.1f }, 1.f, 0.3f });
|
||||
|
||||
scene.mObjects.append(Object());
|
||||
auto& object = scene.mObjects.last();
|
||||
scene.mObjects.append(Object());
|
||||
auto& object = scene.mObjects.last();
|
||||
|
||||
object.mTopology.Points = {
|
||||
{1.000000, 0.000000, 0.000000},
|
||||
{0.000000, 1.000000, 0.000000},
|
||||
{0.000000, 0.000000, 1.000000},
|
||||
};
|
||||
object.mTopology.Points = {
|
||||
{ 1.000000, 0.000000, 0.000000 },
|
||||
{ 0.000000, 1.000000, 0.000000 },
|
||||
{ 0.000000, 0.000000, 1.000000 },
|
||||
};
|
||||
|
||||
object.mTopology.Normals = {
|
||||
{1.000000, 1.000000, 1.000000},
|
||||
{1.000000, 1.000000, 1.000000},
|
||||
{1.000000, 1.000000, 1.000000},
|
||||
};
|
||||
object.mTopology.Normals = {
|
||||
{ 1.000000, 1.000000, 1.000000 },
|
||||
{ 1.000000, 1.000000, 1.000000 },
|
||||
{ 1.000000, 1.000000, 1.000000 },
|
||||
};
|
||||
|
||||
object.mTopology.Indexes = {
|
||||
{0, 1, 2},
|
||||
};
|
||||
object.mTopology.Indexes = {
|
||||
{ 0, 1, 2 },
|
||||
};
|
||||
|
||||
object.mCache.Source = &object.mTopology;
|
||||
object.mCache.updateCache();
|
||||
object.mCache.Source = &object.mTopology;
|
||||
object.mCache.updateCache();
|
||||
|
||||
RayTracer::RenderSettings settings = {
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
{10, 10},
|
||||
};
|
||||
RayTracer::RenderSettings settings = {
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
{ 10, 10 },
|
||||
};
|
||||
|
||||
RayTracer::OutputBuffers output;
|
||||
// output.reserve(RayTracer::RenderBuffer::Index2D(settings.size.x, settings.size.y));
|
||||
RayTracer::OutputBuffers output;
|
||||
// output.reserve(RayTracer::RenderBuffer::Index2D(settings.size.x, settings.size.y));
|
||||
|
||||
RayTracer rt;
|
||||
rt.render(scene, output, settings);
|
||||
RayTracer rt;
|
||||
rt.render(scene, output, settings);
|
||||
|
||||
TEST(compareCols(output.color.get({6, 4}), RGBA {0.560100f, 0.560100f, 0.560100f, 1.000000f}));
|
||||
TEST(compareCols(output.color.get({6, 5}), RGBA {0.353739f, 0.353739f, 0.353739f, 1.000000f}));
|
||||
TEST(compareCols(output.color.get({6, 6}), RGBA {0.242577f, 0.242577f, 0.242577f, 1.000000f}));
|
||||
TEST(compareCols(output.color.get({6, 7}), RGBA {0.176313f, 0.176313f, 0.176313f, 1.000000f}));
|
||||
TEST(compareCols(output.color.get({6, 8}), RGBA {0.000000f, 0.000000f, 0.000000f, 0.000000f}));
|
||||
TEST(compareCols(output.color.get({ 6, 4 }), RGBA{ 0.560100f, 0.560100f, 0.560100f, 1.000000f }));
|
||||
TEST(compareCols(output.color.get({ 6, 5 }), RGBA{ 0.353739f, 0.353739f, 0.353739f, 1.000000f }));
|
||||
TEST(compareCols(output.color.get({ 6, 6 }), RGBA{ 0.242577f, 0.242577f, 0.242577f, 1.000000f }));
|
||||
TEST(compareCols(output.color.get({ 6, 7 }), RGBA{ 0.176313f, 0.176313f, 0.176313f, 1.000000f }));
|
||||
TEST(compareCols(output.color.get({ 6, 8 }), RGBA{ 0.000000f, 0.000000f, 0.000000f, 0.000000f }));
|
||||
|
||||
if (0) {
|
||||
writeImage(output.color);
|
||||
for (auto i = 0; i < output.color.size().x; i++) {
|
||||
for (auto j = 0; j < output.color.size().y; j++) {
|
||||
auto tmp = output.color.get({i, j});
|
||||
printf("TEST(compareCols(output.get({%i, %i}), RGBA{ %ff, %ff, %ff, %ff }));\n", i, j, tmp.r, tmp.g, tmp.b, tmp.a);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (0) {
|
||||
writeImage(output.color);
|
||||
for (auto i = 0; i < output.color.size().x; i++) {
|
||||
for (auto j = 0; j < output.color.size().y; j++) {
|
||||
auto tmp = output.color.get({ i, j });
|
||||
printf("TEST(compareCols(output.get({%i, %i}), RGBA{ %ff, %ff, %ff, %ff }));\n", i, j, tmp.r, tmp.g, tmp.b, tmp.a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
tp::ModuleManifest* ModuleDependencies[] = {&tp::gModuleRayTracer, nullptr};
|
||||
tp::ModuleManifest TestModule("TokenizerTest", nullptr, nullptr, ModuleDependencies);
|
||||
tp::ModuleManifest* ModuleDependencies[] = { &tp::gModuleRayTracer, nullptr };
|
||||
tp::ModuleManifest TestModule("TokenizerTest", nullptr, nullptr, ModuleDependencies);
|
||||
|
||||
if (!TestModule.initialize()) {
|
||||
return 1;
|
||||
}
|
||||
if (!TestModule.initialize()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
testRT();
|
||||
testRT();
|
||||
|
||||
TestModule.deinitialize();
|
||||
TestModule.deinitialize();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue