Improved transfer function business

This commit is contained in:
Martin Opat 2025-01-09 12:17:30 +01:00
parent d978630f26
commit fc2488c578
1 changed files with 32 additions and 6 deletions

View File

@ -10,6 +10,7 @@
#include <iostream> #include <iostream>
#include "objs/sphere.h" #include "objs/sphere.h"
// TODO: Probbably move this transfer function business into a different file
// Samples the voxel nearest to the given coordinates. TODO: Can be re-used in other places so move // Samples the voxel nearest to the given coordinates. TODO: Can be re-used in other places so move
__device__ float sampleVolumeNearest(float* volumeData, const int volW, const int volH, const int volD, int vx, int vy, int vz) { __device__ float sampleVolumeNearest(float* volumeData, const int volW, const int volH, const int volD, int vx, int vy, int vz) {
if (vx < 0) vx = 0; if (vx < 0) vx = 0;
@ -44,6 +45,32 @@ __device__ float sampleVolumeTrilinear(float* volumeData, const int volW, const
return c0 * (1.0f - dz) + c1 * dz; return c0 * (1.0f - dz) + c1 * dz;
} }
// Function to map a temperature to an RGB color
__device__ Color3 temperatureToRGB(float temperature) {
// atm, the scalar field is normalized
const float minTemp = 0.0f; // coldest == deep blue
const float maxTemp = 1.0f; // hottest temperature == deep red
temperature = clamp(temperature, minTemp, maxTemp);
float t = normalize(temperature, minTemp, maxTemp);
float r, g, b;
if (t < 0.5f) { // From blue to green
t *= 2.0f; // Scale to [0, 1]
r = interpolate(0.0f, 0.0f, t);
g = interpolate(0.0f, 1.0f, t);
b = interpolate(1.0f, 0.0f, t);
} else { // From green to red
t = (t - 0.5f) * 2.0f; // Scale to [0, 1]
r = interpolate(0.0f, 1.0f, t);
g = interpolate(1.0f, 0.0f, t);
b = interpolate(0.0f, 0.0f, t);
}
return Color3::init(r, g, b);
}
// Transfer function // Transfer function
__device__ float4 transferFunction(float density, Vec3 grad, Point3 pos, Vec3 rayDir) { __device__ float4 transferFunction(float density, Vec3 grad, Point3 pos, Vec3 rayDir) {
@ -52,7 +79,8 @@ __device__ float4 transferFunction(float density, Vec3 grad, Point3 pos, Vec3 ra
float alphaSample = density * 0.1f; float alphaSample = density * 0.1f;
// result.w = 1.0f - expf(-density * 0.1f); // result.w = 1.0f - expf(-density * 0.1f);
Color3 baseColor = Color3::init(density, 0.1f*density, 1.f - density); // TODO: Implement a proper transfer function // Color3 baseColor = Color3::init(density, 0.1f*density, 1.f - density); // TODO: Implement a proper transfer function
Color3 baseColor = temperatureToRGB(density);
Vec3 normal = -grad.normalize(); Vec3 normal = -grad.normalize();
@ -80,6 +108,7 @@ __device__ float4 transferFunction(float density, Vec3 grad, Point3 pos, Vec3 ra
} }
// TODO: instead of IMAGEWIDTH and IMAGEHEIGHT this should reflect the windowSize; // TODO: instead of IMAGEWIDTH and IMAGEHEIGHT this should reflect the windowSize;
__global__ void raycastKernel(float* volumeData, FrameBuffer framebuffer) { __global__ void raycastKernel(float* volumeData, FrameBuffer framebuffer) {
int px = blockIdx.x * blockDim.x + threadIdx.x; int px = blockIdx.x * blockDim.x + threadIdx.x;
@ -149,16 +178,13 @@ __global__ void raycastKernel(float* volumeData, FrameBuffer framebuffer) {
Point3 pos = d_cameraPos + rayDir * tCurrent; Point3 pos = d_cameraPos + rayDir * tCurrent;
// Convert to volume indices // Convert to volume indices
// float fx = pos.x * (VOLUME_WIDTH - 1);
// float fy = pos.y * (VOLUME_HEIGHT - 1);
// float fz = pos.z * (VOLUME_DEPTH - 1);
int ix = (int)roundf(pos.x); int ix = (int)roundf(pos.x);
int iy = (int)roundf(pos.y); int iy = (int)roundf(pos.y);
int iz = (int)roundf(pos.z); int iz = (int)roundf(pos.z);
// Sample (pick appropriate method based on volume size) // Sample (pick appropriate method based on volume size)
float density = sampleVolumeNearest(volumeData, VOLUME_WIDTH, VOLUME_HEIGHT, VOLUME_DEPTH, ix, iy, iz); // float density = sampleVolumeNearest(volumeData, VOLUME_WIDTH, VOLUME_HEIGHT, VOLUME_DEPTH, ix, iy, iz);
// float density = sampleVolumeTrilinear(volumeData, VOLUME_WIDTH, VOLUME_HEIGHT, VOLUME_DEPTH, pos.x, pos.y, pos.z); float density = sampleVolumeTrilinear(volumeData, VOLUME_WIDTH, VOLUME_HEIGHT, VOLUME_DEPTH, pos.x, pos.y, pos.z);
// If density ~ 0, skip shading // If density ~ 0, skip shading
if (density > minAllowedDensity) { if (density > minAllowedDensity) {