Moved transfer function functions to their own file
This commit is contained in:
parent
417913af2b
commit
1711bcf756
|
|
@ -1,5 +1,31 @@
|
||||||
#include "consts.h"
|
#include "consts.h"
|
||||||
|
|
||||||
|
// ----------------------- Colour mapping -----------------------
|
||||||
|
__constant__ ColorStop d_stopsPythonLike[5];
|
||||||
|
__constant__ ColorStop d_stopsGrayscale[2];
|
||||||
|
__constant__ ColorStop d_stopsBluePurleRed[3];
|
||||||
|
|
||||||
|
const ColorStop h_stopsPythonLike[] = {
|
||||||
|
{ 0.0f, Color3::init(0.2298057f, 0.29871797f, 0.75368315f) }, // Dark Blue
|
||||||
|
{ 0.25f, Color3::init(0.23437708f, 0.30554173f, 0.75967953f) }, // Mid Blue
|
||||||
|
{ 0.5f, Color3::init(0.27582712f, 0.36671692f, 0.81255294f) }, // White
|
||||||
|
{ 0.75f, Color3::init(0.79606387f, 0.84869321f, 0.93347147f) }, // Light Orange
|
||||||
|
{ 1.0f, Color3::init(0.70567316f, 0.01555616f, 0.15023281f) } // Red
|
||||||
|
};
|
||||||
|
|
||||||
|
const ColorStop h_stopsGrayscale[] = {
|
||||||
|
{ 0.0f, Color3::init(0.0f, 0.0f, 0.0f) }, // No colour
|
||||||
|
{ 1.0f, Color3::init(1.0f, 1.0f, 1.0f) } // White
|
||||||
|
};
|
||||||
|
|
||||||
|
const ColorStop h_stopsBluePurleRed[] = {
|
||||||
|
{ 0.0f, Color3::init(0.0f, 0.0f, 1.0f) }, // deep blue
|
||||||
|
{ 0.5f, Color3::init(0.5f, 0.0f, 0.5f) }, // purple
|
||||||
|
{ 1.0f, Color3::init(1.0f, 0.0f, 0.0f) } // deep red
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------- Camera and Light -----------------------
|
||||||
|
|
||||||
__device__ Point3 d_cameraPos;
|
__device__ Point3 d_cameraPos;
|
||||||
__device__ Vec3 d_cameraDir;
|
__device__ Vec3 d_cameraDir;
|
||||||
__device__ Vec3 d_cameraUp;
|
__device__ Vec3 d_cameraUp;
|
||||||
|
|
@ -12,7 +38,16 @@ Vec3 h_cameraDir = (center - h_cameraPos).normalize();
|
||||||
Vec3 h_cameraUp = Vec3::init(0.0, 0.0, 1.0).normalize();
|
Vec3 h_cameraUp = Vec3::init(0.0, 0.0, 1.0).normalize();
|
||||||
Point3 h_lightPos = Point3::init(1.5, 2.0, -1.0);
|
Point3 h_lightPos = Point3::init(1.5, 2.0, -1.0);
|
||||||
|
|
||||||
|
|
||||||
|
// Copy the above values to the device
|
||||||
void copyConstantsToDevice() {
|
void copyConstantsToDevice() {
|
||||||
|
// ----------------------- Colour mapping -----------------------
|
||||||
|
cudaMemcpyToSymbol(d_stopsPythonLike, h_stopsPythonLike, sizeof(h_stopsPythonLike));
|
||||||
|
cudaMemcpyToSymbol(d_stopsGrayscale, h_stopsGrayscale, sizeof(h_stopsGrayscale));
|
||||||
|
cudaMemcpyToSymbol(d_stopsBluePurleRed, h_stopsBluePurleRed, sizeof(h_stopsBluePurleRed));
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------- Camera and Light -----------------------
|
||||||
cudaMemcpyToSymbol(d_cameraPos, &h_cameraPos, sizeof(Point3));
|
cudaMemcpyToSymbol(d_cameraPos, &h_cameraPos, sizeof(Point3));
|
||||||
cudaMemcpyToSymbol(d_cameraDir, &h_cameraDir, sizeof(Vec3));
|
cudaMemcpyToSymbol(d_cameraDir, &h_cameraDir, sizeof(Vec3));
|
||||||
cudaMemcpyToSymbol(d_cameraUp, &h_cameraUp, sizeof(Vec3));
|
cudaMemcpyToSymbol(d_cameraUp, &h_cameraUp, sizeof(Vec3));
|
||||||
|
|
|
||||||
14
src/consts.h
14
src/consts.h
|
|
@ -48,6 +48,20 @@ extern __device__ Vec3 d_cameraDir;
|
||||||
extern __device__ Vec3 d_cameraUp;
|
extern __device__ Vec3 d_cameraUp;
|
||||||
extern __device__ Point3 d_lightPos;
|
extern __device__ Point3 d_lightPos;
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------- Transfer Function Constants ---------------------------
|
||||||
|
struct ColorStop {
|
||||||
|
float pos; // in [0,1]
|
||||||
|
Color3 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
const int lenStopsPythonLike = 5;
|
||||||
|
const int lenStopsGrayscale = 2;
|
||||||
|
const int lenStopsBluePurpleRed = 3;
|
||||||
|
extern __constant__ ColorStop d_stopsPythonLike[5];
|
||||||
|
extern __constant__ ColorStop d_stopsGrayscale[2];
|
||||||
|
extern __constant__ ColorStop d_stopsBluePurleRed[3];
|
||||||
|
|
||||||
// --------------------------- Functions for handling external constants ---------------------------
|
// --------------------------- Functions for handling external constants ---------------------------
|
||||||
void copyConstantsToDevice();
|
void copyConstantsToDevice();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,214 +5,12 @@
|
||||||
|
|
||||||
#include "linalg/linalg.h"
|
#include "linalg/linalg.h"
|
||||||
#include "consts.h"
|
#include "consts.h"
|
||||||
|
#include "transferFunction.h"
|
||||||
#include "cuda_error.h"
|
#include "cuda_error.h"
|
||||||
#include "shading.h"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "objs/sphere.h"
|
|
||||||
#include <curand_kernel.h>
|
#include <curand_kernel.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
|
|
||||||
__device__ float sampleVolumeNearest(float* volumeData, const int volW, const int volH, const int volD, int vx, int vy, int vz) {
|
|
||||||
// x <-> height, y <-> width, z <-> depth <--- So far this is the best one
|
|
||||||
if (vx < 0) vx = 0;
|
|
||||||
if (vy < 0) vy = 0;
|
|
||||||
if (vz < 0) vz = 0;
|
|
||||||
if (vx >= volH) vx = volH - 1;
|
|
||||||
if (vy >= volW) vy = volW - 1;
|
|
||||||
if (vz >= volD) vz = volD - 1;
|
|
||||||
|
|
||||||
int idx = vz * volW * volH + vx * volW + vy;
|
|
||||||
return volumeData[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
// tri-linear interpolation - ready if necessary (but no visible improvement for full volume)
|
|
||||||
__device__ float sampleVolumeTrilinear(float* volumeData, const int volW, const int volH, const int volD, float fx, float fy, float fz) {
|
|
||||||
int ix = (int)floorf(fx);
|
|
||||||
int iy = (int)floorf(fy);
|
|
||||||
int iz = (int)floorf(fz);
|
|
||||||
|
|
||||||
// Clamp indices to valid range
|
|
||||||
int ix1 = min(ix + 1, volW - 1);
|
|
||||||
int iy1 = min(iy + 1, volH - 1);
|
|
||||||
int iz1 = min(iz + 1, volD - 1);
|
|
||||||
ix = max(ix, 0);
|
|
||||||
iy = max(iy, 0);
|
|
||||||
iz = max(iz, 0);
|
|
||||||
|
|
||||||
// Compute weights
|
|
||||||
float dx = fx - ix;
|
|
||||||
float dy = fy - iy;
|
|
||||||
float dz = fz - iz;
|
|
||||||
|
|
||||||
// Sample values
|
|
||||||
float c00 = sampleVolumeNearest(volumeData, volW, volH, volD, ix, iy, iz) * (1.0f - dx) +
|
|
||||||
sampleVolumeNearest(volumeData, volW, volH, volD, ix1, iy, iz) * dx;
|
|
||||||
float c10 = sampleVolumeNearest(volumeData, volW, volH, volD, ix, iy1, iz) * (1.0f - dx) +
|
|
||||||
sampleVolumeNearest(volumeData, volW, volH, volD, ix1, iy1, iz) * dx;
|
|
||||||
float c01 = sampleVolumeNearest(volumeData, volW, volH, volD, ix, iy, iz1) * (1.0f - dx) +
|
|
||||||
sampleVolumeNearest(volumeData, volW, volH, volD, ix1, iy, iz1) * dx;
|
|
||||||
float c11 = sampleVolumeNearest(volumeData, volW, volH, volD, ix, iy1, iz1) * (1.0f - dx) +
|
|
||||||
sampleVolumeNearest(volumeData, volW, volH, volD, ix1, iy1, iz1) * dx;
|
|
||||||
|
|
||||||
float c0 = c00 * (1.0f - dy) + c10 * dy;
|
|
||||||
float c1 = c01 * (1.0f - dy) + c11 * dy;
|
|
||||||
|
|
||||||
return c0 * (1.0f - dz) + c1 * dz;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__device__ float opacityFromGradient(const Vec3 &grad) {
|
|
||||||
float gradMag = grad.length(); // magnitude
|
|
||||||
float k = 1e-4f; // tweak (the smaller the value, the less opacity) // TODO: What should be the value of this?
|
|
||||||
float alpha = 1.0f - expf(-k * gradMag);
|
|
||||||
return alpha;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ColorStop
|
|
||||||
{
|
|
||||||
float pos; // in [0,1]
|
|
||||||
Color3 color; // R,G,B in [0,1]
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: Rename probably
|
|
||||||
__device__ Color3 colorMapViridis(float normalizedT) {
|
|
||||||
// Here we redefine the color stops to go from deep blue (0.0) to purple (0.5) to deep red (1.0)
|
|
||||||
ColorStop tempStops[] = {
|
|
||||||
{ 0.0f, Color3::init(0.0f, 0.0f, 1.0f) }, // deep blue
|
|
||||||
{ 0.5f, Color3::init(0.5f, 0.0f, 0.5f) }, // purple
|
|
||||||
{ 1.0f, Color3::init(1.0f, 0.0f, 0.0f) } // deep red
|
|
||||||
};
|
|
||||||
|
|
||||||
// Clamp to [0,1]
|
|
||||||
if (normalizedT < 0.0f) normalizedT = 0.0f;
|
|
||||||
if (normalizedT > 1.0f) normalizedT = 1.0f;
|
|
||||||
|
|
||||||
// We have 3 stops => 2 intervals
|
|
||||||
const int N = 3;
|
|
||||||
for (int i = 0; i < N - 1; ++i)
|
|
||||||
{
|
|
||||||
float start = tempStops[i].pos;
|
|
||||||
float end = tempStops[i + 1].pos;
|
|
||||||
|
|
||||||
if (normalizedT >= start && normalizedT <= end)
|
|
||||||
{
|
|
||||||
float localT = (normalizedT - start) / (end - start);
|
|
||||||
return interpolate(tempStops[i].color, tempStops[i + 1].color, localT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Fallback if something goes out of [0,1] or numerical issues
|
|
||||||
return tempStops[N - 1].color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Monochromatic colormap for speed
|
|
||||||
__device__ Color3 colorMapMonochrome(float normalizedSpeed) {
|
|
||||||
// Define the color stops: black (0.0) to white (1.0)
|
|
||||||
ColorStop speedStops[] = {
|
|
||||||
{ 0.0f, Color3::init(0.0f, 0.0f, 0.0f) }, // No colour
|
|
||||||
{ 1.0f, Color3::init(1.0f, 1.0f, 1.0f) } // White
|
|
||||||
};
|
|
||||||
|
|
||||||
// Clamp to [0,1]
|
|
||||||
if (normalizedSpeed < 0.0f) normalizedSpeed = 0.0f;
|
|
||||||
if (normalizedSpeed > 1.0f) normalizedSpeed = 1.0f;
|
|
||||||
|
|
||||||
// Single interval (N = 2 for black to white)
|
|
||||||
const int N = 2;
|
|
||||||
for (int i = 0; i < N - 1; ++i)
|
|
||||||
{
|
|
||||||
float start = speedStops[i].pos;
|
|
||||||
float end = speedStops[i + 1].pos;
|
|
||||||
|
|
||||||
if (normalizedSpeed >= start && normalizedSpeed <= end)
|
|
||||||
{
|
|
||||||
float localT = (normalizedSpeed - start) / (end - start);
|
|
||||||
return interpolate(speedStops[i].color, speedStops[i + 1].color, localT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback
|
|
||||||
return speedStops[N - 1].color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Colormap function for gradient from blue to white to red
|
|
||||||
__device__ Color3 colorMapPythonLike(float normalizedValue) {
|
|
||||||
// Define control points for the colormap (approximation of coolwarm)
|
|
||||||
ColorStop coolwarmStops[] = {
|
|
||||||
{ 0.0f, Color3::init(0.2298057f, 0.29871797f, 0.75368315f) }, // Dark Blue
|
|
||||||
{ 0.25f, Color3::init(0.23437708f, 0.30554173f, 0.75967953f) }, // Mid Blue
|
|
||||||
{ 0.5f, Color3::init(0.27582712f, 0.36671692f, 0.81255294f) }, // White
|
|
||||||
{ 0.75f, Color3::init(0.79606387f, 0.84869321f, 0.93347147f) }, // Light Orange
|
|
||||||
{ 1.0f, Color3::init(0.70567316f, 0.01555616f, 0.15023281f) } // Red
|
|
||||||
};
|
|
||||||
|
|
||||||
// Clamp the scalar value to [0, 1]
|
|
||||||
normalizedValue = fminf(fmaxf(normalizedValue, 0.0f), 1.0f);
|
|
||||||
|
|
||||||
// Interpolate between the defined color stops
|
|
||||||
const int N = 5; // Number of control points
|
|
||||||
for (int i = 0; i < N - 1; ++i) {
|
|
||||||
float start = coolwarmStops[i].pos;
|
|
||||||
float end = coolwarmStops[i + 1].pos;
|
|
||||||
|
|
||||||
if (normalizedValue >= start && normalizedValue <= end) {
|
|
||||||
float localT = (normalizedValue - start) / (end - start);
|
|
||||||
return interpolate(coolwarmStops[i].color, coolwarmStops[i + 1].color, localT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback (shouldn't reach here due to clamping)
|
|
||||||
return coolwarmStops[N - 1].color;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Transfer function
|
|
||||||
__device__ float4 transferFunction(float density, const Vec3& grad, const Point3& pos, const Vec3& rayDir) {
|
|
||||||
// Basic transfer function. TODO: Move to a separate file, and then improve
|
|
||||||
|
|
||||||
// Color3 baseColor = Color3::init(density, 0.1f*density, 1.f - density); // TODO: Implement a proper transfer function
|
|
||||||
// Color3 baseColor = temperatureToRGB(density);
|
|
||||||
|
|
||||||
float normDensity = (density - MIN_TEMP) / (MAX_TEMP - MIN_TEMP);
|
|
||||||
// float normDensity = (density - MIN_SPEED) / (MAX_SPEED - MIN_SPEED);
|
|
||||||
|
|
||||||
normDensity = clamp(normDensity, 0.0f, 1.0f);
|
|
||||||
|
|
||||||
// Color3 baseColor = colorMapViridis(normDensity);
|
|
||||||
// Color3 baseColor = colorMapMonochrome(normDensity);
|
|
||||||
Color3 baseColor = colorMapPythonLike(normDensity);
|
|
||||||
|
|
||||||
|
|
||||||
float alpha = opacityFromGradient(grad);
|
|
||||||
// alpha = 0.1f;
|
|
||||||
alpha = 1.0f / (1.0f + expf(-250.f * (normDensity - 0.5f))); // This is also quite nice, but the exponent should be parameterized
|
|
||||||
float alphaSample = density * alpha; // TODO: Decide whether to keep alpha here or not
|
|
||||||
|
|
||||||
Vec3 normal = -grad.normalize();
|
|
||||||
|
|
||||||
Vec3 lightDir = (d_lightPos - pos).normalize();
|
|
||||||
Vec3 viewDir = -rayDir.normalize();
|
|
||||||
|
|
||||||
// Apply Phong
|
|
||||||
Vec3 shadedColor = phongShading(normal, lightDir, viewDir, baseColor);
|
|
||||||
|
|
||||||
// Compose
|
|
||||||
float4 result;
|
|
||||||
result.x = shadedColor.x * alphaSample;
|
|
||||||
result.y = shadedColor.y * alphaSample;
|
|
||||||
result.z = shadedColor.z * alphaSample;
|
|
||||||
result.w = alpha; // TODO: Again, decide if alpha here is correct or not
|
|
||||||
|
|
||||||
// TODO: This is the black silhouette, technically if we are doing alpha based on gradient then it's kind of redundant (?) ... but could also be used for even sharper edges
|
|
||||||
if (grad.length() > epsilon && fabs(grad.normalize().dot(viewDir)) < 0.2f) {
|
|
||||||
result.x = 0.0f;
|
|
||||||
result.y = 0.0f;
|
|
||||||
result.z = 0.0f;
|
|
||||||
result.w = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
#include "transferFunction.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Samples the voxel nearest to the given coordinates.
|
||||||
|
__device__ float sampleVolumeNearest(float* volumeData, const int volW, const int volH, const int volD, int vx, int vy, int vz) {
|
||||||
|
// x <-> height, y <-> width, z <-> depth <--- So far this is the best one
|
||||||
|
if (vx < 0) vx = 0;
|
||||||
|
if (vy < 0) vy = 0;
|
||||||
|
if (vz < 0) vz = 0;
|
||||||
|
if (vx >= volH) vx = volH - 1;
|
||||||
|
if (vy >= volW) vy = volW - 1;
|
||||||
|
if (vz >= volD) vz = volD - 1;
|
||||||
|
|
||||||
|
int idx = vz * volW * volH + vx * volW + vy;
|
||||||
|
return volumeData[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
// tri-linear interpolation - ready if necessary (but no visible improvement for full volume)
|
||||||
|
__device__ float sampleVolumeTrilinear(float* volumeData, const int volW, const int volH, const int volD, float fx, float fy, float fz) {
|
||||||
|
int ix = (int)floorf(fx);
|
||||||
|
int iy = (int)floorf(fy);
|
||||||
|
int iz = (int)floorf(fz);
|
||||||
|
|
||||||
|
// Clamp indices to valid range
|
||||||
|
int ix1 = min(ix + 1, volW - 1);
|
||||||
|
int iy1 = min(iy + 1, volH - 1);
|
||||||
|
int iz1 = min(iz + 1, volD - 1);
|
||||||
|
ix = max(ix, 0);
|
||||||
|
iy = max(iy, 0);
|
||||||
|
iz = max(iz, 0);
|
||||||
|
|
||||||
|
// Compute weights
|
||||||
|
float dx = fx - ix;
|
||||||
|
float dy = fy - iy;
|
||||||
|
float dz = fz - iz;
|
||||||
|
|
||||||
|
// Sample values
|
||||||
|
float c00 = sampleVolumeNearest(volumeData, volW, volH, volD, ix, iy, iz) * (1.0f - dx) +
|
||||||
|
sampleVolumeNearest(volumeData, volW, volH, volD, ix1, iy, iz) * dx;
|
||||||
|
float c10 = sampleVolumeNearest(volumeData, volW, volH, volD, ix, iy1, iz) * (1.0f - dx) +
|
||||||
|
sampleVolumeNearest(volumeData, volW, volH, volD, ix1, iy1, iz) * dx;
|
||||||
|
float c01 = sampleVolumeNearest(volumeData, volW, volH, volD, ix, iy, iz1) * (1.0f - dx) +
|
||||||
|
sampleVolumeNearest(volumeData, volW, volH, volD, ix1, iy, iz1) * dx;
|
||||||
|
float c11 = sampleVolumeNearest(volumeData, volW, volH, volD, ix, iy1, iz1) * (1.0f - dx) +
|
||||||
|
sampleVolumeNearest(volumeData, volW, volH, volD, ix1, iy1, iz1) * dx;
|
||||||
|
|
||||||
|
float c0 = c00 * (1.0f - dy) + c10 * dy;
|
||||||
|
float c1 = c01 * (1.0f - dy) + c11 * dy;
|
||||||
|
|
||||||
|
return c0 * (1.0f - dz) + c1 * dz;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__device__ float opacityFromGradient(const Vec3 &grad) {
|
||||||
|
float gradMag = grad.length();
|
||||||
|
float k = 1e-4f; // tweak (the smaller the value, the less opacity) // TODO: Add a slider for this
|
||||||
|
float alpha = 1.0f - expf(-k * gradMag);
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
__device__ float opacitySigmoid(float normDensity) {
|
||||||
|
return 1.0f / (1.0f + expf(-250.f * (normDensity - 0.5f))); // TODO: Parametrize and add sliders
|
||||||
|
}
|
||||||
|
|
||||||
|
__device__ Color3 colorMap(float normalizedValues, const ColorStop stops[], int N) {
|
||||||
|
// clamp to [0,1]
|
||||||
|
normalizedValues = fminf(fmaxf(normalizedValues, 0.0f), 1.0f);
|
||||||
|
|
||||||
|
// N stops => N-1 intervals
|
||||||
|
for (int i = 0; i < N - 1; ++i) {
|
||||||
|
float start = stops[i].pos;
|
||||||
|
float end = stops[i + 1].pos;
|
||||||
|
|
||||||
|
if (normalizedValues >= start && normalizedValues <= end) {
|
||||||
|
float localT = (normalizedValues - start) / (end - start);
|
||||||
|
return interpolate(stops[i].color, stops[i + 1].color, localT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback if something goes out of [0,1] or numerical issues
|
||||||
|
return stops[N - 1].color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Transfer function
|
||||||
|
__device__ float4 transferFunction(float density, const Vec3& grad, const Point3& pos, const Vec3& rayDir) {
|
||||||
|
|
||||||
|
// --------------------------- Sample the volume ---------------------------
|
||||||
|
// TODO: Somehow pick if to use temp of speed normalization ... or pass extremas as params.
|
||||||
|
float normDensity = (density - MIN_TEMP) / (MAX_TEMP - MIN_TEMP);
|
||||||
|
// float normDensity = (density - MIN_SPEED) / (MAX_SPEED - MIN_SPEED);
|
||||||
|
|
||||||
|
normDensity = clamp(normDensity, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
// --------------------------- Map density to color ---------------------------
|
||||||
|
// TODO: Add a way to pick stops here
|
||||||
|
Color3 baseColor = colorMap(normDensity, d_stopsPythonLike, lenStopsPythonLike);
|
||||||
|
|
||||||
|
|
||||||
|
float alpha = opacityFromGradient(grad);
|
||||||
|
// alpha = 0.1f;
|
||||||
|
alpha = opacitySigmoid(normDensity);
|
||||||
|
float alphaSample = density * alpha; // TODO: Decide whether to keep alpha here or not
|
||||||
|
|
||||||
|
// --------------------------- Shading ---------------------------
|
||||||
|
// Apply Phong
|
||||||
|
Vec3 normal = -grad.normalize();
|
||||||
|
Vec3 lightDir = (d_lightPos - pos).normalize();
|
||||||
|
Vec3 viewDir = -rayDir.normalize();
|
||||||
|
Vec3 shadedColor = phongShading(normal, lightDir, viewDir, baseColor);
|
||||||
|
|
||||||
|
// Compose
|
||||||
|
float4 result;
|
||||||
|
result.x = shadedColor.x * alphaSample;
|
||||||
|
result.y = shadedColor.y * alphaSample;
|
||||||
|
result.z = shadedColor.z * alphaSample;
|
||||||
|
result.w = alpha; // TODO: Again, decide if alpha here is correct or not
|
||||||
|
|
||||||
|
// --------------------------- Silhouettes ---------------------------
|
||||||
|
// TODO: This is the black silhouette, technically if we are doing alpha based on gradient then it's kind of redundant (?) ... but could also be used for even more pronounced edges
|
||||||
|
if (grad.length() > epsilon && fabs(grad.normalize().dot(viewDir)) < 0.2f) {
|
||||||
|
result.x = 0.0f;
|
||||||
|
result.y = 0.0f;
|
||||||
|
result.z = 0.0f;
|
||||||
|
result.w = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef TRANSFER_FUNCTION_H
|
||||||
|
#define TRANSFER_FUNCTION_H
|
||||||
|
|
||||||
|
#include "linalg/linalg.h"
|
||||||
|
#include "consts.h"
|
||||||
|
#include "shading.h"
|
||||||
|
|
||||||
|
// --------------------------- Color mapping ---------------------------
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------- Volume sampling ---------------------------
|
||||||
|
__device__ float sampleVolumeNearest(float* volumeData, const int volW, const int volH, const int volD, int vx, int vy, int vz);
|
||||||
|
__device__ float sampleVolumeTrilinear(float* volumeData, const int volW, const int volH, const int volD, float fx, float fy, float fz);
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------- Transfer function ---------------------------
|
||||||
|
__device__ float4 transferFunction(float density, const Vec3& grad, const Point3& pos, const Vec3& rayDir);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // TRANSFER_FUNCTION_H
|
||||||
Loading…
Reference in New Issue