Skip to content

Commit

Permalink
Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
jan-van-bergen committed Jul 23, 2021
1 parent a70b1e9 commit 95bd03b
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 160 deletions.
2 changes: 2 additions & 0 deletions Pathtracer.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@
<ClCompile Include="Src\Input.cpp" />
<ClCompile Include="Src\Main.cpp" />
<ClCompile Include="Src\Math\AABB.cpp" />
<ClCompile Include="Src\Math\Mipmap.cpp" />
<ClCompile Include="Src\Pathtracer\Camera.cpp" />
<ClCompile Include="Src\Pathtracer\Mesh.cpp" />
<ClCompile Include="Src\Pathtracer\Pathtracer.cpp" />
Expand Down Expand Up @@ -265,6 +266,7 @@
<ClInclude Include="Src\Math\AABB.h" />
<ClInclude Include="Src\Math\Math.h" />
<ClInclude Include="Src\Math\Matrix4.h" />
<ClInclude Include="Src\Math\Mipmap.h" />
<ClInclude Include="Src\Math\Quaternion.h" />
<ClInclude Include="Src\Math\Vector2.h" />
<ClInclude Include="Src\Math\Vector3.h" />
Expand Down
6 changes: 6 additions & 0 deletions Pathtracer.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@
<ClCompile Include="Src\Util\ThreadPool.cpp">
<Filter>Util</Filter>
</ClCompile>
<ClCompile Include="Src\Math\Mipmap.cpp">
<Filter>Math</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="CUDA">
Expand Down Expand Up @@ -295,5 +298,8 @@
<ClInclude Include="Src\Util\ThreadPool.h">
<Filter>Util</Filter>
</ClInclude>
<ClInclude Include="Src\Math\Mipmap.h">
<Filter>Math</Filter>
</ClInclude>
</ItemGroup>
</Project>
162 changes: 3 additions & 159 deletions Src/Assets/TextureLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,163 +5,7 @@
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image/stb_image.h>

#include "Math/Math.h"
#include "Math/Vector4.h"

/*
Mipmap filter code based on http://number-none.com/product/Mipmapping,%20Part%201/index.html and https://github.com/castano/nvidia-texture-tools
*/

struct FilterBox {
static constexpr float width = 0.5f;

static float eval(float x) {
if (fabsf(x) <= width) {
return 1.0f;
} else {
return 0.0f;
}
}
};

struct FilterLanczos {
static constexpr float width = 3.0f;

static float eval(float x) {
if (fabsf(x) < width) {
return Math::sincf(PI * x) * Math::sincf(PI * x / width);
} else {
return 0.0f;
}
}
};

struct FilterKaiser {
static constexpr float width = 7.0f;
static constexpr float alpha = 4.0f;
static constexpr float stretch = 1.0f;

static float eval(float x) {
float t = x / width;
float t2 = t * t;

if (t2 < 1.0f) {
return Math::sincf(PI * x * stretch) * Math::bessel_0(alpha * sqrtf(1.0f - t2)) / Math::bessel_0(alpha);
} else {
return 0.0f;
}
}
};

#if MIPMAP_DOWNSAMPLE_FILTER == MIPMAP_DOWNSAMPLE_FILTER_BOX
typedef FilterBox Filter;
#elif MIPMAP_DOWNSAMPLE_FILTER == MIPMAP_DOWNSAMPLE_FILTER_LANCZOS
typedef FilterLanczos Filter;
#elif MIPMAP_DOWNSAMPLE_FILTER == MIPMAP_DOWNSAMPLE_FILTER_KAISER
typedef FilterKaiser Filter;
#endif

static float filter_sample_box(float x, float scale) {
constexpr int SAMPLE_COUNT = 32;
constexpr float SAMPLE_COUNT_INV = 1.0f / float(SAMPLE_COUNT);

float sample = 0.5f;
float sum = 0.0f;

for (int i = 0; i < SAMPLE_COUNT; i++, sample += 1.0f) {
float p = (x + sample * SAMPLE_COUNT_INV) * scale;

sum += Filter::eval(p);
}

return sum * SAMPLE_COUNT_INV;
}

static void downsample(int width_src, int height_src, int width_dst, int height_dst, const Vector4 texture_src[], Vector4 texture_dst[], Vector4 temp[]) {
float scale_x = float(width_dst) / float(width_src);
float scale_y = float(height_dst) / float(height_src);

assert(scale_x < 1.0f && scale_y < 1.0f);

float inv_scale_x = 1.0f / scale_x;
float inv_scale_y = 1.0f / scale_y;

float filter_width_x = Filter::width * inv_scale_x;
float filter_width_y = Filter::width * inv_scale_y;

int window_size_x = int(ceilf(filter_width_x * 2.0f)) + 1;
int window_size_y = int(ceilf(filter_width_y * 2.0f)) + 1;

float * kernels = new float[window_size_x + window_size_y];
float * kernel_x = kernels;
float * kernel_y = kernels + window_size_x;

memset(kernel_x, 0, window_size_x * sizeof(float));
memset(kernel_y, 0, window_size_y * sizeof(float));

float sum_x = 0.0f;
float sum_y = 0.0f;

// Fill horizontal kernel
for (int x = 0; x < window_size_x; x++) {
float sample = filter_sample_box(x - window_size_x / 2, scale_x);

kernel_x[x] = sample;
sum_x += sample;
}

// Fill vertical kernel
for (int y = 0; y < window_size_y; y++) {
float sample = filter_sample_box(y - window_size_y / 2, scale_y);

kernel_y[y] = sample;
sum_y += sample;
}

// Normalize kernels
for (int x = 0; x < window_size_x; x++) kernel_x[x] /= sum_x;
for (int y = 0; y < window_size_y; y++) kernel_y[y] /= sum_y;

// Apply horizontal kernel
for (int y = 0; y < height_src; y++) {
for (int x = 0; x < width_dst; x++) {
float center = (float(x) + 0.5f) * inv_scale_x;

int left = int(floorf(center - filter_width_x));

Vector4 sum = Vector4(0.0f);

for (int i = 0; i < window_size_x; i++) {
int index = Math::clamp(left + i, 0, width_src - 1) + y * width_src;

sum += kernel_x[i] * texture_src[index];
}

temp[x * height_src + y] = sum;
}
}

// Apply vertical kernel
for (int x = 0; x < width_dst; x++) {
for (int y = 0; y < height_dst; y++) {
float center = (float(y) + 0.5f) * inv_scale_y;

int top = int(floorf(center - filter_width_y));

Vector4 sum = Vector4(0.0f);

for (int i = 0; i < window_size_y; i++) {
int index = x * height_src + Math::clamp(top + i, 0, height_src - 1);

sum += kernel_y[i] * temp[index];
}

texture_dst[x + y * width_dst] = sum;
}
}

delete [] kernels;
}
#include "Math/Mipmap.h"

bool TextureLoader::load_dds(const char * filename, Texture & texture) {
FILE * file; fopen_s(&file, filename, "rb");
Expand Down Expand Up @@ -313,10 +157,10 @@ bool TextureLoader::load_stb(const char * filename, Texture & texture) {
while (true) {
#if MIPMAP_DOWNSAMPLE_FILTER == MIPMAP_DOWNSAMPLE_FILTER_BOX
// Box filter can downsample the previous Mip level
downsample(level_width * 2, level_height * 2, level_width, level_height, data_rgba + offset_prev, data_rgba + offset, temp);
Mipmap::downsample(level_width * 2, level_height * 2, level_width, level_height, data_rgba + offset_prev, data_rgba + offset, temp);
#else
// Other filters downsample the original Texture for better quality
downsample(texture.width, texture.height, level_width, level_height, data_rgba, data_rgba + offset, temp);
Mipmap::downsample(texture.width, texture.height, level_width, level_height, data_rgba, data_rgba + offset, temp);
#endif

mip_offsets[level++] = offset * sizeof(Vector4);
Expand Down
105 changes: 105 additions & 0 deletions Src/Math/Mipmap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "Mipmap.h"

#include <string.h>

static float filter_sample_box(float x, float scale) {
constexpr int SAMPLE_COUNT = 32;
constexpr float SAMPLE_COUNT_INV = 1.0f / float(SAMPLE_COUNT);

float sample = 0.5f;
float sum = 0.0f;

for (int i = 0; i < SAMPLE_COUNT; i++, sample += 1.0f) {
float p = (x + sample * SAMPLE_COUNT_INV) * scale;

sum += Mipmap::Filter::eval(p);
}

return sum * SAMPLE_COUNT_INV;
}

void Mipmap::downsample(int width_src, int height_src, int width_dst, int height_dst, const Vector4 texture_src[], Vector4 texture_dst[], Vector4 temp[]) {
float scale_x = float(width_dst) / float(width_src);
float scale_y = float(height_dst) / float(height_src);

assert(scale_x < 1.0f && scale_y < 1.0f);

float inv_scale_x = 1.0f / scale_x;
float inv_scale_y = 1.0f / scale_y;

float filter_width_x = Mipmap::Filter::width * inv_scale_x;
float filter_width_y = Mipmap::Filter::width * inv_scale_y;

int window_size_x = int(ceilf(filter_width_x * 2.0f)) + 1;
int window_size_y = int(ceilf(filter_width_y * 2.0f)) + 1;

float * kernels = new float[window_size_x + window_size_y];
float * kernel_x = kernels;
float * kernel_y = kernels + window_size_x;

memset(kernel_x, 0, window_size_x * sizeof(float));
memset(kernel_y, 0, window_size_y * sizeof(float));

float sum_x = 0.0f;
float sum_y = 0.0f;

// Fill horizontal kernel
for (int x = 0; x < window_size_x; x++) {
float sample = filter_sample_box(x - window_size_x / 2, scale_x);

kernel_x[x] = sample;
sum_x += sample;
}

// Fill vertical kernel
for (int y = 0; y < window_size_y; y++) {
float sample = filter_sample_box(y - window_size_y / 2, scale_y);

kernel_y[y] = sample;
sum_y += sample;
}

// Normalize kernels
for (int x = 0; x < window_size_x; x++) kernel_x[x] /= sum_x;
for (int y = 0; y < window_size_y; y++) kernel_y[y] /= sum_y;

// Apply horizontal kernel
for (int y = 0; y < height_src; y++) {
for (int x = 0; x < width_dst; x++) {
float center = (float(x) + 0.5f) * inv_scale_x;

int left = int(floorf(center - filter_width_x));

Vector4 sum = Vector4(0.0f);

for (int i = 0; i < window_size_x; i++) {
int index = Math::clamp(left + i, 0, width_src - 1) + y * width_src;

sum += kernel_x[i] * texture_src[index];
}

temp[x * height_src + y] = sum;
}
}

// Apply vertical kernel
for (int x = 0; x < width_dst; x++) {
for (int y = 0; y < height_dst; y++) {
float center = (float(y) + 0.5f) * inv_scale_y;

int top = int(floorf(center - filter_width_y));

Vector4 sum = Vector4(0.0f);

for (int i = 0; i < window_size_y; i++) {
int index = x * height_src + Math::clamp(top + i, 0, height_src - 1);

sum += kernel_y[i] * temp[index];
}

texture_dst[x + y * width_dst] = sum;
}
}

delete [] kernels;
}
60 changes: 60 additions & 0 deletions Src/Math/Mipmap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#pragma once
#include "Math.h"
#include "Vector4.h"

namespace Mipmap {
/*
Mipmap filter code based on http://number-none.com/product/Mipmapping,%20Part%201/index.html and https://github.com/castano/nvidia-texture-tools
*/

struct FilterBox {
static constexpr float width = 0.5f;

static float eval(float x) {
if (fabsf(x) <= width) {
return 1.0f;
} else {
return 0.0f;
}
}
};

struct FilterLanczos {
static constexpr float width = 3.0f;

static float eval(float x) {
if (fabsf(x) < width) {
return Math::sincf(PI * x) * Math::sincf(PI * x / width);
} else {
return 0.0f;
}
}
};

struct FilterKaiser {
static constexpr float width = 7.0f;
static constexpr float alpha = 4.0f;
static constexpr float stretch = 1.0f;

static float eval(float x) {
float t = x / width;
float t2 = t * t;

if (t2 < 1.0f) {
return Math::sincf(PI * x * stretch) * Math::bessel_0(alpha * sqrtf(1.0f - t2)) / Math::bessel_0(alpha);
} else {
return 0.0f;
}
}
};

#if MIPMAP_DOWNSAMPLE_FILTER == MIPMAP_DOWNSAMPLE_FILTER_BOX
typedef FilterBox Filter;
#elif MIPMAP_DOWNSAMPLE_FILTER == MIPMAP_DOWNSAMPLE_FILTER_LANCZOS
typedef FilterLanczos Filter;
#elif MIPMAP_DOWNSAMPLE_FILTER == MIPMAP_DOWNSAMPLE_FILTER_KAISER
typedef FilterKaiser Filter;
#endif

void downsample(int width_src, int height_src, int width_dst, int height_dst, const Vector4 texture_src[], Vector4 texture_dst[], Vector4 temp[]);
}
2 changes: 1 addition & 1 deletion Src/Pathtracer/Pathtracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ void Pathtracer::cuda_init(unsigned frame_buffer_handle, int screen_width, int s

for (int i = 0; i < mesh_data.bvh.index_count; i++) {
int index = mesh_data.bvh.indices[i];
Triangle & triangle = mesh_data.triangles[index];
const Triangle & triangle = mesh_data.triangles[index];

aggregated_triangles[mesh_data_triangle_offsets[m] + i].position_0 = triangle.position_0;
aggregated_triangles[mesh_data_triangle_offsets[m] + i].position_edge_1 = triangle.position_1 - triangle.position_0;
Expand Down

0 comments on commit 95bd03b

Please sign in to comment.