diff --git a/core/bsdf/lambert.h b/core/bsdf/lambert.h index 6941168..a778737 100644 --- a/core/bsdf/lambert.h +++ b/core/bsdf/lambert.h @@ -20,7 +20,7 @@ __inline__ __device__ float lambert_brdf_f(const glm::vec3& wi, const glm::vec3& __inline__ __device__ void lambert_brdf_sample_f(const glm::vec3& wo, const glm::vec3& normal, glm::vec3* wi, float* pdf, curandState& rng) { *wi = cosine_weightd_sample_hemisphere(rng, normal); - *pdf = glm::dot(*wi, normal) / float(M_PI); + *pdf = fabsf(glm::dot(*wi, normal)) / float(M_PI); } #endif //SUNVOLUMERENDER_LAMBERT_H diff --git a/core/bsdf/microfacet.h b/core/bsdf/microfacet.h index ac621ed..c16baa4 100644 --- a/core/bsdf/microfacet.h +++ b/core/bsdf/microfacet.h @@ -56,7 +56,7 @@ __inline__ __device__ float microfacet_brdf_f(const glm::vec3& wi, const glm::ve //else auto wh = glm::normalize(wi + wo); - auto fresnelTerm = schlick_fresnel(1.f, ior, fmaxf(0.f, glm::dot(wh, wo))); + auto fresnelTerm = schlick_fresnel(1.f, ior, fabsf(glm::dot(wh, wo))); auto geometryTerm = geometry_cook_torrance(wi, wo, normal, wh); #ifdef DISTRIBUTION_BECKMANN auto D = beckmann_distribution(normal, wh, alpha); @@ -104,9 +104,9 @@ __inline__ __device__ void microfacet_brdf_sample_f(const glm::vec3& wo, const g *wi = glm::reflect(-wo, wh); #ifdef DISTRIBUTION_BECKMANN - *pdf = beckmann_distribution(normal, wh, alpha) / (4.f * glm::dot(wo, wh)); + *pdf = beckmann_distribution(normal, wh, alpha) / (4.f * fabsf(glm::dot(wo, wh))); #else - *pdf = GGX_distribution(normal, wh, alpha) / (4.f * glm::dot(wo, wh)); + *pdf = GGX_distribution(normal, wh, alpha) / (4.f * fabsf(glm::dot(wo, wh))); #endif } diff --git a/core/cuda_volume.h b/core/cuda_volume.h index 226c699..d0b6cf5 100644 --- a/core/cuda_volume.h +++ b/core/cuda_volume.h @@ -23,6 +23,17 @@ class cudaVolume this->tex = tex; } + __host__ __device__ void SetClipPlane(const glm::vec2& x_clip, const glm::vec2& y_clip, const glm::vec2& z_clip) + { + this->x_clip = x_clip; + this->y_clip = y_clip; + this->z_clip = z_clip; + } + + __host__ __device__ void SetXClipPlane(const glm::vec2& clip) {x_clip = clip;} + __host__ __device__ void SetYClipPlane(const glm::vec2& clip) {y_clip = clip;} + __host__ __device__ void SetZClipPlane(const glm::vec2& clip) {z_clip = clip;} + __device__ float operator ()(const glm::vec3& pointInWorld) const { return GetIntensity(pointInWorld); @@ -35,7 +46,7 @@ class cudaVolume __device__ bool Intersect(const cudaRay& ray, float* tNear, float* tFar) const { - return bbox.Intersect(ray, tNear, tFar); + return bbox.Intersect(ray, tNear, tFar, x_clip, y_clip, z_clip); } __device__ glm::vec3 Gradient_CentralDiff(const glm::vec3& pointInWorld) const @@ -92,6 +103,9 @@ class cudaVolume cudaTextureObject_t tex; glm::vec3 spacing; glm::vec3 invSpacing; + glm::vec2 x_clip; + glm::vec2 y_clip; + glm::vec2 z_clip; }; struct VolumeSample diff --git a/core/geometry/cuda_bbox.h b/core/geometry/cuda_bbox.h index 31a329d..9810f72 100644 --- a/core/geometry/cuda_bbox.h +++ b/core/geometry/cuda_bbox.h @@ -30,11 +30,16 @@ class cudaBBox invSize = 1.f / (vmax - vmin); } - __device__ bool Intersect(const cudaRay& ray, float* tNear, float* tFar) const + __device__ bool Intersect(const cudaRay& ray, float* tNear, float* tFar, const glm::vec2& x_clip, const glm::vec2& y_clip, const glm::vec2& z_clip) const { auto invDir = 1.f / ray.dir; - auto tbot = invDir * (vmin - ray.orig); - auto ttop = invDir * (vmax - ray.orig); + + // compute visible box range after clip + auto clip_vmin = vmin * glm::vec3(-x_clip[0], -y_clip[0], -z_clip[0]); + auto clip_vmax = vmax * glm::vec3(x_clip[1], y_clip[1], z_clip[1]); + + auto tbot = invDir * (clip_vmin - ray.orig); + auto ttop = invDir * (clip_vmax - ray.orig); auto tmin = glm::min(tbot, ttop); auto tmax = glm::max(tbot, ttop); diff --git a/gui/canvas.cpp b/gui/canvas.cpp index 310ab0e..bdea8ca 100644 --- a/gui/canvas.cpp +++ b/gui/canvas.cpp @@ -25,6 +25,7 @@ void Canvas::LoadVolume(std::string filename) { volumeReader.Read(filename); volumeReader.CreateDeviceVolume(&deviceVolume); + deviceVolume.SetClipPlane(glm::vec2(-1.f, 1.f), glm::vec2(-1.f, 1.f), glm::vec2(-1.f, 1.f)); setup_volume(deviceVolume); ZoomToExtent(); diff --git a/gui/canvas.h b/gui/canvas.h index 4b2560c..6b57129 100644 --- a/gui/canvas.h +++ b/gui/canvas.h @@ -136,6 +136,28 @@ class Canvas : public QGLWidget UpdateCamera(); } + // clip plane + void SetXClipPlane(double min, double max) + { + deviceVolume.SetXClipPlane(glm::vec2(float(min), float(max))); + setup_volume(deviceVolume); + ReStartRender(); + } + + void SetYClipPlane(double min, double max) + { + deviceVolume.SetYClipPlane(glm::vec2(float(min), float(max))); + setup_volume(deviceVolume); + ReStartRender(); + } + + void SetZClipPlane(double min, double max) + { + deviceVolume.SetZClipPlane(glm::vec2(float(min), float(max))); + setup_volume(deviceVolume); + ReStartRender(); + } + protected: //opengl void initializeGL(); diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index dda8f92..47f7c10 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -21,6 +21,7 @@ MainWindow::MainWindow(QWidget *parent) : ConfigureLight(); ConfigureCamera(); ConfigureRenderMode(); + ConfigureClipPlane(); // initialize transferfunction on device canvas->SetTransferFunction(this->tf->GetCompositeTFTextureObject(), 0.5f); @@ -133,6 +134,13 @@ void MainWindow::ConfigureCamera() connect(ui->SliderWidget_apeture, SIGNAL(valueChanged(double)), this, SLOT(onCameraApetureChanged(double))); } +void MainWindow::ConfigureClipPlane() +{ + connect(ui->DoubleRangeSlider_XClip, SIGNAL(positionsChanged(double, double)), this, SLOT(onXClipChanged(double, double))); + connect(ui->DoubleRangeSlider_YClip, SIGNAL(positionsChanged(double, double)), this, SLOT(onYClipChanged(double, double))); + connect(ui->DoubleRangeSlider_ZClip, SIGNAL(positionsChanged(double, double)), this, SLOT(onZClipChanged(double, double))); +} + void MainWindow::onFileOpen() { QString fileName = ""; @@ -442,3 +450,18 @@ void MainWindow::onRenderModeChanged() break; } } + +void MainWindow::onXClipChanged(double min, double max) +{ + canvas->SetXClipPlane(min, max); +} + +void MainWindow::onYClipChanged(double min, double max) +{ + canvas->SetYClipPlane(min, max); +} + +void MainWindow::onZClipChanged(double min, double max) +{ + canvas->SetZClipPlane(min, max); +} diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 68c51ed..6c7db77 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -38,6 +38,7 @@ class MainWindow : public QMainWindow void ConfigureLight(); void ConfigureCamera(); void ConfigureRenderMode(); + void ConfigureClipPlane(); private slots: void onTransferFunctionChanged(); @@ -68,6 +69,10 @@ private slots: void onRenderModeChanged(); + void onXClipChanged(double min, double max); + void onYClipChanged(double min, double max); + void onZClipChanged(double min, double max); + private: Ui::MainWindow *ui; diff --git a/gui/mainwindow.ui b/gui/mainwindow.ui index 1ad0f85..0611148 100644 --- a/gui/mainwindow.ui +++ b/gui/mainwindow.ui @@ -266,7 +266,7 @@ 0 - -139 + 0 363 689 @@ -714,6 +714,136 @@ + + + + :/icons/cut_scissor_scissors_32px_4093_easyicon.net.png:/icons/cut_scissor_scissors_32px_4093_easyicon.net.png + + + Clip Plane + + + + + + true + + + + + 0 + 0 + 378 + 550 + + + + + + + Clip range + + + + + + -1.000000000000000 + + + 1.000000000000000 + + + 0.001000000000000 + + + -1.000000000000000 + + + Qt::Horizontal + + + + + + + X + + + + + + + -1.000000000000000 + + + 1.000000000000000 + + + 0.001000000000000 + + + -1.000000000000000 + + + Qt::Horizontal + + + + + + + -1.000000000000000 + + + 1.000000000000000 + + + 0.001000000000000 + + + -1.000000000000000 + + + Qt::Horizontal + + + + + + + Y + + + + + + + Z + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + @@ -750,6 +880,11 @@ QPushButton
ctkColorPickerButton.h
+ + ctkDoubleRangeSlider + QWidget +
ctkDoubleRangeSlider.h
+
ctkPathLineEdit QWidget diff --git a/pathtracer.cu b/pathtracer.cu index 39978fb..c4481e7 100644 --- a/pathtracer.cu +++ b/pathtracer.cu @@ -135,7 +135,7 @@ __inline__ __device__ glm::vec3 sample_bsdf(const VolumeSample& vs, glm::vec3* w if(st == SHANDING_TYPE_ISOTROPIC) { hg_phase_sample_f(PHASE_FUNC_G, vs.wo, wi, pdf, rng); - return glm::vec3(vs.color_opacity); + return glm::vec3(vs.color_opacity) * hg_phase_f(vs.wo, *wi); } else if(st == SHANDING_TYPE_BRDF) { @@ -230,7 +230,7 @@ __global__ void kernel_pathtracer(const RenderParams renderParams, uint32_t hash if(t < 0.f) { - L += T * envLight.GetEnvRadiance(ray.dir); + //L += T * envLight.GetEnvRadiance(ray.dir); break; } @@ -256,7 +256,12 @@ __global__ void kernel_pathtracer(const RenderParams renderParams, uint32_t hash auto f = sample_bsdf(vs, &wi, &pdf, rng, st); float cosTerm = fabsf(glm::dot(glm::normalize(vs.gradient), wi)); if(fmaxf(f.x, fmaxf(f.y, f.z)) > 0.f && pdf > 0.f) - T *= f * cosTerm / pdf; + { + if(st == SHANDING_TYPE_ISOTROPIC) + T *= f / pdf; + else + T *= f * cosTerm / pdf; + } ray.orig = vs.ptInWorld; ray.dir = wi; diff --git a/resources/cut_scissor_scissors_32px_4093_easyicon.net.png b/resources/cut_scissor_scissors_32px_4093_easyicon.net.png new file mode 100644 index 0000000..ec0e454 Binary files /dev/null and b/resources/cut_scissor_scissors_32px_4093_easyicon.net.png differ diff --git a/resources/images.qrc b/resources/images.qrc index 3638676..8577d1a 100644 --- a/resources/images.qrc +++ b/resources/images.qrc @@ -1,5 +1,6 @@ + cut_scissor_scissors_32px_4093_easyicon.net.png Color_picker_64px_1100527_easyicon.net.png light_bulb_64px_1076410_easyicon.net.png photo_camera_77.241379310345px_1201192_easyicon.net.png