Adding simple test for RT

This commit is contained in:
IlyaShurupov 2023-10-18 19:05:51 +03:00
parent 2e0d0e0050
commit 7af12ee1a0
8 changed files with 402 additions and 217 deletions

View file

@ -6,13 +6,10 @@
namespace tp { namespace tp {
template< typename tType, ualni tSizeX, ualni tSizeY > template <typename tType, ualni tSizeX, ualni tSizeY>
using ConstSizeBuffer2D = ConstSizeBuffer<ConstSizeBuffer<tType, tSizeX>, tSizeY>; using ConstSizeBuffer2D = ConstSizeBuffer<ConstSizeBuffer<tType, tSizeX>, tSizeY>;
template < template <typename tType, class tAllocator = DefaultAllocator>
typename tType,
class tAllocator = DefaultAllocator
>
class Buffer2D { class Buffer2D {
public: public:
typedef ualni Index; typedef ualni Index;
@ -22,40 +19,39 @@ namespace tp {
private: private:
tAllocator mAlloc; tAllocator mAlloc;
tType* mBuff = nullptr; tType* mBuff = nullptr;
Index2D mSize = { 0, 0 }; Index2D mSize = {0, 0};
void deleteBuffer() { void deleteBuffer() {
if (!mBuff) return; if (!mBuff) {
for (ualni i = 0; i < mSize.x * mSize.y; i++) mBuff[i].~tType(); return;
}
for (ualni i = 0; i < mSize.x * mSize.y; i++) {
mBuff[i].~tType();
}
mAlloc.deallocate(mBuff); mAlloc.deallocate(mBuff);
} }
void allocateBuffer(Index2D size) { void allocateBuffer(Index2D size) {
deleteBuffer(); deleteBuffer();
mBuff = (tType*) mAlloc.allocate(sizeof(tType) * size.x * size.y); mBuff = (tType*) mAlloc.allocate(sizeof(tType) * size.x * size.y);
for (ualni i = 0; i < mSize.x * mSize.y; i++) new (mBuff + i) tType(); for (ualni i = 0; i < mSize.x * mSize.y; i++) {
new (mBuff + i) tType();
}
} }
public: public:
Buffer2D() = default; Buffer2D() = default;
~Buffer2D() { ~Buffer2D() {
deleteBuffer(); deleteBuffer();
mSize = { 0, 0 }; mSize = {0, 0};
} }
explicit Buffer2D(Index2D aSize) { explicit Buffer2D(Index2D aSize) { reserve(aSize); }
reserve(aSize);
}
[[nodiscard]] Index2D size() const { [[nodiscard]] Index2D size() const { return {mSize.x, mSize.y}; }
return { mSize.x, mSize.y };
}
tType* getBuff() const { tType* getBuff() const { return mBuff; }
return mBuff;
}
inline tType& get(const Index2D& at) { inline tType& get(const Index2D& at) {
DEBUG_ASSERT(mBuff && at.x < mSize.x && at.y < mSize.y && at.x >= 0 && at.y >= 0) DEBUG_ASSERT(mBuff && at.x < mSize.x && at.y < mSize.y && at.x >= 0 && at.y >= 0)
@ -87,8 +83,23 @@ namespace tp {
} }
} }
bool operator==(const Buffer2D& in) const {
if (&in == this) {
return true;
}
if (in.size() != size()) {
return false;
}
for (auto i = 0; i < mSize.x * mSize.y; i++) {
if (mBuff[i] != in.mBuff[i]) {
return false;
}
}
return true;
}
public: public:
template<class tArchiver> template <class tArchiver>
void archiveWrite(tArchiver& ar) const { void archiveWrite(tArchiver& ar) const {
ar << mSize; ar << mSize;
for (auto i = 0; i < mSize.x; i++) { for (auto i = 0; i < mSize.x; i++) {
@ -98,7 +109,7 @@ namespace tp {
} }
} }
template<class tArchiver> template <class tArchiver>
void archiveRead(tArchiver& ar) { void archiveRead(tArchiver& ar) {
decltype(mSize) size; decltype(mSize) size;
deleteBuffer(); deleteBuffer();

View file

@ -37,8 +37,11 @@ namespace tp {
class RGBA { class RGBA {
public: public:
RGBA() : r(0), g(0), b(0), a(0) {} RGBA() : r(0), g(0), b(0), a(0) {}
RGBA(flt4 val) : rgbs(val), a(val) {} RGBA(flt4 val) : rgbs(val), a(val) {}
RGBA(const RGB& RGBs, flt4 val) : rgbs(RGBs), a(val) {} RGBA(const RGB& RGBs, flt4 val) : rgbs(RGBs), a(val) {}
RGBA(flt4 pr, flt4 pg, flt4 pb, flt4 pa) : rgbs(pr, pg, pb), a(pa) {} RGBA(flt4 pr, flt4 pg, flt4 pb, flt4 pa) : rgbs(pr, pg, pb), a(pa) {}
public: public:
@ -49,26 +52,29 @@ namespace tp {
} }
RGBA operator-(const RGBA& in) const { RGBA operator-(const RGBA& in) const {
auto const nr = tp::clamp(r - in.r, 0.f, 1.f); const auto nr = tp::clamp(r - in.r, 0.f, 1.f);
auto const ng = tp::clamp(g - in.g, 0.f, 1.f); const auto ng = tp::clamp(g - in.g, 0.f, 1.f);
auto const nb = tp::clamp(b - in.b, 0.f, 1.f); const auto nb = tp::clamp(b - in.b, 0.f, 1.f);
auto const na = tp::clamp(a - in.a, 0.f, 1.f); const auto na = tp::clamp(a - in.a, 0.f, 1.f);
return { nr, ng, nb, na }; return {nr, ng, nb, na};
} }
RGBA operator+(const RGBA& in) const { RGBA operator+(const RGBA& in) const {
auto const nr = tp::clamp(r + in.r, 0.f, 1.f); const auto nr = tp::clamp(r + in.r, 0.f, 1.f);
auto const ng = tp::clamp(g + in.g, 0.f, 1.f); const auto ng = tp::clamp(g + in.g, 0.f, 1.f);
auto const nb = tp::clamp(b + in.b, 0.f, 1.f); const auto nb = tp::clamp(b + in.b, 0.f, 1.f);
auto const na = tp::clamp(a + in.a, 0.f, 1.f); const auto na = tp::clamp(a + in.a, 0.f, 1.f);
return { nr, ng, nb, na }; return {nr, ng, nb, na};
} }
bool operator==(const RGBA& in) const { return r == in.r && g == in.g && b == in.b && a == in.a; }
public: public:
flt4 a; flt4 a;
union { union {
RGB rgbs; RGB rgbs;
struct { struct {
flt4 r; flt4 r;
flt4 g; flt4 g;

View file

@ -26,6 +26,9 @@ file(COPY "applications/rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
enable_testing() enable_testing()
file(GLOB TEST_SOURCES "./tests/*.cpp" "./tests/*/*.cpp") file(GLOB TEST_SOURCES "./tests/*.cpp" "./tests/*/*.cpp")
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES}) add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
target_include_directories(${PROJECT_NAME}Tests PUBLIC ./applications/)
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils) target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils)
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests) add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)

View file

@ -24,6 +24,7 @@ bool loadMeshes(tp::Scene& scene, const tp::String& objetsPath) {
auto object = &scene.mObjects.last(); auto object = &scene.mObjects.last();
for (auto& vertex : curMesh.Vertices) { 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.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}); object->mTopology.Normals.append(Vec3F {vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z});
} }
@ -32,6 +33,7 @@ bool loadMeshes(tp::Scene& scene, const tp::String& objetsPath) {
int idx1 = (int) curMesh.Indices[j]; int idx1 = (int) curMesh.Indices[j];
int idx2 = (int) curMesh.Indices[j + 1]; int idx2 = (int) curMesh.Indices[j + 1];
int idx3 = (int) curMesh.Indices[j + 2]; int idx3 = (int) curMesh.Indices[j + 2];
// printf("{ %i, %i, %i },\n", idx1, idx2, idx3);
object->mTopology.Indexes.append(Vec3I {idx1, idx2, idx3}); object->mTopology.Indexes.append(Vec3I {idx1, idx2, idx3});
} }

View file

@ -2,14 +2,14 @@
Meshes = "meshes.obj" Meshes = "meshes.obj"
Camera = { Camera = {
pos = { 4, 4, 4 }, pos = { 3, 3, 3 },
size_x = 400, size_x = 10,
size_y = 600, size_y = 10,
} }
Lights = { Lights = {
{ {
pos = { 4, 3, 3 }, pos = { 4, 2, 3 },
intensity = 4 intensity = 5
} }
} }

View file

@ -171,6 +171,9 @@ void RayTracer::render(const Scene& scene, RayTracer::RenderBuffer& buff, const
buff.set({i, j}, 0.f); buff.set({i, j}, 0.f);
} }
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; mProgress.percentage = (halnf) currIter / (halnf) maxIterations;
currIter++; currIter++;
} }

View file

@ -1,3 +1,125 @@
int main(int argc, char* argv[]) { return 1; } // #include "NewPlacement.hpp"
#include "RayTracer.hpp"
#include "Testing.hpp"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
using namespace tp;
void writeImage(const RayTracer::RenderBuffer& output) {
// Save the data to a PNG file
struct urgb {
uint1 r, g, b, a;
};
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);
}
}
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;
}
void testRT() {
using namespace tp;
Scene scene;
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.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.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.mCache.Source = &object.mTopology;
object.mCache.updateCache();
RayTracer::RenderSettings settings = {
0,
0,
{10, 10},
};
RayTracer::RenderBuffer output;
output.reserve(RayTracer::RenderBuffer::Index2D(settings.size.x, settings.size.y));
RayTracer rt;
rt.render(scene, output, settings);
TEST(compareCols(output.get({6, 4}), RGBA {0.560100f, 0.560100f, 0.560100f, 1.000000f}));
TEST(compareCols(output.get({6, 5}), RGBA {0.353739f, 0.353739f, 0.353739f, 1.000000f}));
TEST(compareCols(output.get({6, 6}), RGBA {0.242577f, 0.242577f, 0.242577f, 1.000000f}));
TEST(compareCols(output.get({6, 7}), RGBA {0.176313f, 0.176313f, 0.176313f, 1.000000f}));
TEST(compareCols(output.get({6, 8}), RGBA {0.000000f, 0.000000f, 0.000000f, 0.000000f}));
if (0) {
writeImage(output);
for (auto i = 0; i < output.size().x; i++) {
for (auto j = 0; j < output.size().y; j++) {
auto tmp = output.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);
if (!TestModule.initialize()) {
return 1;
}
testRT();
TestModule.deinitialize();
}

View file

@ -3,7 +3,7 @@
#include "Module.hpp" #include "Module.hpp"
#define PTR_OFFSET(first, offset) (*((&first) + offset)) #define PTR_OFFSET(first, offset) (*((&first) + offset))
#define MEMBER_OFFSET(s, m) (alni(&(((s*)0)->m))) #define MEMBER_OFFSET(s, m) (alni(&(((s*) 0)->m)))
namespace tp { namespace tp {
@ -26,19 +26,45 @@ namespace tp {
class Pair { class Pair {
public: public:
Pair() = default; Pair() = default;
Pair(T1 t1, T2 t2) : head(t1), tail(t2) {}
union { T1 t1; T1 head; T1 x; }; template <typename U1, typename U2>
union { T2 t2; T2 tail; T2 y; }; Pair(U1 t1, U2 t2) : head(static_cast<T1>(t1)),
tail(static_cast<T2>(t2)) {}
union {
T1 t1;
T1 head;
T1 x;
};
union {
T2 t2;
T2 tail;
T2 y;
};
bool operator==(const Pair& in) const { return in.t1 == t1 && in.t2 == t2; }
bool operator!=(const Pair& in) const { return !this->operator==(in); }
}; };
template <typename Type = alni> template <typename Type = alni>
class Bits { class Bits {
Type mFlags = 0; Type mFlags = 0;
public: public:
Bits() = default; Bits() = default;
explicit Bits(Type val) { mFlags = val; } explicit Bits(Type val) { mFlags = val; }
explicit Bits(bool val) { for (int bit = 0; bit < sizeof(Type); bit++) { set(bit, val); } }
explicit Bits(bool val) {
for (int bit = 0; bit < sizeof(Type); bit++) {
set(bit, val);
}
}
bool get(int1 idx) { return mFlags & (1l << idx); } bool get(int1 idx) { return mFlags & (1l << idx); }
void set(int1 idx, bool val) { void set(int1 idx, bool val) {
if (val) { if (val) {
mFlags |= (1l << idx); mFlags |= (1l << idx);
@ -48,19 +74,25 @@ namespace tp {
} }
}; };
template <typename tType = ualni>
template<typename tType = ualni>
class Range { class Range {
public: public:
class Iterator { class Iterator {
public: public:
tType mIndex; tType mIndex;
explicit Iterator(tType pStartIndex) : mIndex(pStartIndex) {} explicit Iterator(tType pStartIndex) : mIndex(pStartIndex) {}
tType index() const { return mIndex; } tType index() const { return mIndex; }
inline void operator++() { mIndex++; } inline void operator++() { mIndex++; }
inline operator tType() const { return mIndex; } inline operator tType() const { return mIndex; }
inline bool operator==(Iterator pIndex) { return mIndex == pIndex.mIndex; } inline bool operator==(Iterator pIndex) { return mIndex == pIndex.mIndex; }
inline bool operator!=(Iterator pIndex) { return mIndex != pIndex.mIndex; } inline bool operator!=(Iterator pIndex) { return mIndex != pIndex.mIndex; }
inline const Iterator& operator*() { return *this; } inline const Iterator& operator*() { return *this; }
}; };
@ -68,15 +100,21 @@ namespace tp {
tType mEnd = 0; tType mEnd = 0;
Range() = default; Range() = default;
explicit Range(tType pEndIndex) : mBegin(0), mEnd(pEndIndex) {} explicit Range(tType pEndIndex) : mBegin(0), mEnd(pEndIndex) {}
Range(tType pStartIndex, tType pEndIndex) : mBegin(pStartIndex), mEnd(pEndIndex) {} Range(tType pStartIndex, tType pEndIndex) : mBegin(pStartIndex), mEnd(pEndIndex) {}
bool valid() { return mBegin < mEnd; } bool valid() { return mBegin < mEnd; }
tType idxBegin() const { return mBegin; } tType idxBegin() const { return mBegin; }
tType idxEnd() const { return mEnd; } tType idxEnd() const { return mEnd; }
tType idxDiff() const { return mEnd - mBegin; } tType idxDiff() const { return mEnd - mBegin; }
Iterator begin() { return Iterator(mBegin); } Iterator begin() { return Iterator(mBegin); }
Iterator end() { return Iterator(mEnd); } Iterator end() { return Iterator(mEnd); }
}; };
} }