implemented some more controls
This commit is contained in:
parent
dc0175f88a
commit
9c7dd45858
|
|
@ -28,9 +28,9 @@ const ColorStop h_stopsBluePurleRed[] = {
|
|||
|
||||
__device__ Point3 d_cameraPos;
|
||||
__device__ Vec3 d_cameraDir;
|
||||
__device__ Vec3 d_cameraUp;
|
||||
__device__ Point3 d_lightPos;
|
||||
__device__ Color3 d_backgroundColor;
|
||||
__device__ Vec3 d_cameraUp;
|
||||
|
||||
Vec3 h_cameraUp = Vec3::init(0.0, 1.0, 0.0).normalize();
|
||||
|
||||
|
|
@ -45,3 +45,9 @@ void copyConstantsToDevice() {
|
|||
// ----------------------- Camera and Light -----------------------
|
||||
cudaMemcpyToSymbol(d_cameraUp, &h_cameraUp, sizeof(Vec3));
|
||||
}
|
||||
|
||||
|
||||
// ----------------------- TransferFunction -----------------------
|
||||
__device__ float d_opacityK;
|
||||
__device__ float d_sigmoidOne;
|
||||
__device__ float d_sigmoidTwo;
|
||||
|
|
|
|||
12
src/consts.h
12
src/consts.h
|
|
@ -11,9 +11,8 @@ const int VOLUME_WIDTH = 97; // lon
|
|||
const int VOLUME_HEIGHT = 71; // lat
|
||||
const int VOLUME_DEPTH = 42; // lev
|
||||
|
||||
// TODO: replace with window->w and window->h
|
||||
const int IMAGE_WIDTH = 800;
|
||||
const int IMAGE_HEIGHT = 600;
|
||||
const int INITIAL_WINDOW_WIDTH = 1200;
|
||||
const int INITIAL_WINDOW_HEIGHT = 900;
|
||||
|
||||
const double epsilon = 1e-10f;
|
||||
const double infty = 1e15f; // This value is used to represent missing values in data
|
||||
|
|
@ -52,12 +51,19 @@ extern __device__ Point3 d_lightPos;
|
|||
// Background color
|
||||
extern __device__ Color3 d_backgroundColor;
|
||||
|
||||
|
||||
// --------------------------- Transfer Function Constants ---------------------------
|
||||
struct ColorStop {
|
||||
float pos; // in [0,1]
|
||||
Color3 color;
|
||||
};
|
||||
|
||||
// factor for the opacity function
|
||||
extern __device__ float d_opacityK;
|
||||
// sigmoid function variables
|
||||
extern __device__ float d_sigmoidOne;
|
||||
extern __device__ float d_sigmoidTwo;
|
||||
|
||||
const int lenStopsPythonLike = 5;
|
||||
const int lenStopsGrayscale = 2;
|
||||
const int lenStopsBluePurpleRed = 3;
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ Widget::Widget(GLFWwindow* window) {
|
|||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL3_Init();
|
||||
|
||||
// this->cameraPos = Point3::init(50.0f, -50.0f, -75.0f); // Camera for partially trimmed data set
|
||||
this->cameraPos = Point3::init(300.0f, 200.0f, -700.0f); // Camera for full data set
|
||||
//
|
||||
this->cameraPos = Point3::init(50.0f, -50.0f, -75.0f); // Camera for partially trimmed data set
|
||||
// this->cameraPos = Point3::init(300.0f, 200.0f, -700.0f); // Camera for full data set
|
||||
|
||||
Vec3 h_center = Vec3::init((float)VOLUME_WIDTH/2.0f, (float)VOLUME_HEIGHT/2.0f, (float)VOLUME_DEPTH/2.0f);
|
||||
this->cameraDir = (h_center - this->cameraPos).normalize();
|
||||
|
||||
|
|
@ -25,8 +25,13 @@ Widget::Widget(GLFWwindow* window) {
|
|||
this->fps = (char*)malloc(512*sizeof(char));
|
||||
this->paused = true;
|
||||
this->renderOnce = false;
|
||||
|
||||
this->opacityK = 0;
|
||||
this->sigmoidOne = 0.5f;
|
||||
this->sigmoidTwo = -250.0f;
|
||||
};
|
||||
|
||||
// TODO: can be marginally improvement by only copying changed values to device - however we're dealing with individual floats here so i dont think the benefit would be all that obvious.
|
||||
void Widget::tick(double fps) {
|
||||
if (this->renderOnce) {
|
||||
this->renderOnce = false;
|
||||
|
|
@ -40,16 +45,22 @@ void Widget::tick(double fps) {
|
|||
// input widgets
|
||||
float min = -1, max = 1;
|
||||
|
||||
ImGui::Begin("Transfer Function Controls");
|
||||
ImGui::DragInt("k (log [1e-10, 1])", &this->opacityK, 1, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp);
|
||||
ImGui::DragFloat("sigmoidOne", &this->sigmoidOne, 0.01f, 0.0f, 1.0f, "%.2f");
|
||||
ImGui::InputFloat("sigmoidTwo", &this->sigmoidTwo, 10.0f, 100.0f, "%.0f");
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Light Controls");
|
||||
ImGui::DragScalar("X coordinate", ImGuiDataType_Double, &this->lightPos.x, 0.005f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("Y coordinate", ImGuiDataType_Double, &this->lightPos.y, 0.005f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("Z coordinate", ImGuiDataType_Double, &this->lightPos.z, 0.005f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("X coordinate", ImGuiDataType_Double, &this->lightPos.x, 0.5f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("Y coordinate", ImGuiDataType_Double, &this->lightPos.z, 0.5f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("Z coordinate", ImGuiDataType_Double, &this->lightPos.y, 0.5f, &min, &max, "%.3f");
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Miscellaneous");
|
||||
if (ImGui::Button(this->paused ? "Unpause" : "Pause")) this->paused = !this->paused;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("render Once")) {
|
||||
if (ImGui::Button("Render once")) {
|
||||
this->paused = !this->paused;
|
||||
this->renderOnce = true;
|
||||
}
|
||||
|
|
@ -58,12 +69,12 @@ void Widget::tick(double fps) {
|
|||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Camera Controls");
|
||||
ImGui::DragScalar("X position", ImGuiDataType_Double, &this->cameraPos.x, 0.005f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("Y position", ImGuiDataType_Double, &this->cameraPos.y, 0.005f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("Z position", ImGuiDataType_Double, &this->cameraPos.z, 0.005f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("X position", ImGuiDataType_Double, &this->cameraPos.x, 0.5f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("Y position", ImGuiDataType_Double, &this->cameraPos.z, 0.5f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("Z position", ImGuiDataType_Double, &this->cameraPos.y, 0.5f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("X direction", ImGuiDataType_Double, &this->cameraDir.x, 0.005f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("Y direction", ImGuiDataType_Double, &this->cameraDir.y, 0.005f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("Z direction", ImGuiDataType_Double, &this->cameraDir.z, 0.005f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("Y direction", ImGuiDataType_Double, &this->cameraDir.z, 0.005f, &min, &max, "%.3f");
|
||||
ImGui::DragScalar("Z direction", ImGuiDataType_Double, &this->cameraDir.y, 0.005f, &min, &max, "%.3f");
|
||||
ImGui::End();
|
||||
|
||||
copyToDevice();
|
||||
|
|
@ -79,6 +90,13 @@ void Widget::copyToDevice() {
|
|||
cudaMemcpyToSymbol(&d_cameraDir, &this->cameraDir, sizeof(Vec3));
|
||||
cudaMemcpyToSymbol(&d_lightPos, &this->lightPos, sizeof(Point3));
|
||||
cudaMemcpyToSymbol(&d_backgroundColor, &this->bgColor, sizeof(Color3));
|
||||
|
||||
// cudaMemcpyToSymbol(&d_opacityK, &this->opacityK, sizeof(float));
|
||||
this->opacityKReal = std::pow(10.0f, (-10 + 0.1 * this->opacityK));
|
||||
cudaMemcpyToSymbol(&d_opacityK, &this->opacityKReal, sizeof(float));
|
||||
|
||||
cudaMemcpyToSymbol(&d_sigmoidOne, &this->sigmoidOne, sizeof(float));
|
||||
cudaMemcpyToSymbol(&d_sigmoidTwo, &this->sigmoidTwo, sizeof(float));
|
||||
}
|
||||
|
||||
Widget::~Widget() {
|
||||
|
|
|
|||
|
|
@ -12,12 +12,17 @@ public:
|
|||
Point3 cameraDir;
|
||||
Vec3 cameraPos;
|
||||
Point3 lightPos;
|
||||
Color3 bgColor;
|
||||
Color3 bgColor; // TODO: widget
|
||||
|
||||
bool paused;
|
||||
bool renderOnce;
|
||||
char* fps;
|
||||
|
||||
int opacityK;
|
||||
float opacityKReal;
|
||||
float sigmoidOne;
|
||||
float sigmoidTwo;
|
||||
|
||||
ImGuiIO io;
|
||||
|
||||
void tick(double fps);
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@
|
|||
#include <curand_kernel.h>
|
||||
|
||||
// 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, const int width, const int height) {
|
||||
int px = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
int py = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
if (px >= IMAGE_WIDTH || py >= IMAGE_HEIGHT) return;
|
||||
if (px >= width || py >= height) return;
|
||||
|
||||
float accumR = 0.0f;
|
||||
float accumG = 0.0f;
|
||||
|
|
@ -24,15 +24,15 @@ __global__ void raycastKernel(float* volumeData, FrameBuffer framebuffer) {
|
|||
|
||||
// Initialize random state for ray scattering
|
||||
curandState randState;
|
||||
curand_init(1234, px + py * IMAGE_WIDTH, 0, &randState);
|
||||
curand_init(1234, px + py * width, 0, &randState);
|
||||
|
||||
// Multiple samples per pixel
|
||||
for (int s = 0; s < SAMPLES_PER_PIXEL; s++) {
|
||||
// Map to [-1, 1]
|
||||
float jitterU = (curand_uniform(&randState) - 0.5f) / IMAGE_WIDTH;
|
||||
float jitterV = (curand_uniform(&randState) - 0.5f) / IMAGE_HEIGHT;
|
||||
float u = ((px + 0.5f + jitterU) / IMAGE_WIDTH ) * 2.0f - 1.0f;
|
||||
float v = ((py + 0.5f + jitterV) / IMAGE_HEIGHT) * 2.0f - 1.0f;
|
||||
float jitterU = (curand_uniform(&randState) - 0.5f) / width;
|
||||
float jitterV = (curand_uniform(&randState) - 0.5f) / height;
|
||||
float u = ((px + 0.5f + jitterU) / width ) * 2.0f - 1.0f;
|
||||
float v = ((py + 0.5f + jitterV) / height) * 2.0f - 1.0f;
|
||||
|
||||
float tanHalfFov = tanf(fov * 0.5f);
|
||||
u *= tanHalfFov;
|
||||
|
|
@ -167,7 +167,7 @@ void Raycaster::render() {
|
|||
|
||||
// TODO: pass camera info at some point
|
||||
// frame buffer is implicitly copied to the device each frame
|
||||
raycastKernel<<<threadSize, blockSize>>> (this->data, *this->fb);
|
||||
raycastKernel<<<threadSize, blockSize>>> (this->data, *this->fb, this->w, this->h);
|
||||
|
||||
check_cuda_errors(cudaGetLastError());
|
||||
check_cuda_errors(cudaDeviceSynchronize());
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
#include "transferFunction.h"
|
||||
#include "consts.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
// Samples the voxel nearest to the given coordinates.
|
||||
|
|
@ -53,13 +56,12 @@ __device__ float sampleVolumeTrilinear(float* volumeData, const int volW, const
|
|||
|
||||
__device__ float opacityFromGradient(const Vec3 &grad) {
|
||||
float gradMag = grad.length();
|
||||
float k = 1e-6f; // tweak (the smaller the value, the less opacity) // TODO: Add a slider for this
|
||||
float alpha = 1.0f - expf(-k * gradMag);
|
||||
float alpha = 1.0f - expf(-d_opacityK * gradMag);
|
||||
return alpha;
|
||||
}
|
||||
|
||||
__device__ float opacitySigmoid(float val) {
|
||||
return 1.0f / (1.0f + expf(-250.f * (val - 0.5f))); // TODO: Parametrize and add sliders
|
||||
return 1.0f / (1.0f + expf(d_sigmoidTwo * (val - d_sigmoidOne)));
|
||||
}
|
||||
|
||||
__device__ Color3 colorMap(float normalizedValues, const ColorStop stops[], int N) {
|
||||
|
|
@ -96,6 +98,7 @@ __device__ float4 transferFunction(float density, const Vec3& grad, const Point3
|
|||
// TODO: Add a way to pick stops here
|
||||
Color3 baseColor = colorMap(normDensity, d_stopsPythonLike, lenStopsPythonLike);
|
||||
|
||||
// TODO: This is a Gui select element
|
||||
// TODO: Add a way to pick different function for alpha
|
||||
float alpha = opacityFromGradient(grad);
|
||||
// alpha = 0.1f;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
static float* d_volume = nullptr;
|
||||
|
||||
// FIXME: segfaults on window resize - the raycasting function should work with window->w and window-h instead of constants.
|
||||
// FIXME: segfaults on window resize - the problem is _not_ in the raycasting function
|
||||
|
||||
// TODO: general
|
||||
// * very similarly - actual code for loading new data as the simulation progresses - right now its effectively a static image loader * pause button once that dataloading is implemented
|
||||
|
|
@ -116,7 +116,7 @@ int main() {
|
|||
|
||||
copyConstantsToDevice();
|
||||
// Create the GUI
|
||||
Window window(IMAGE_WIDTH, IMAGE_HEIGHT);
|
||||
Window window(INITIAL_WINDOW_WIDTH, INITIAL_WINDOW_HEIGHT);
|
||||
int out = window.init(d_volume);
|
||||
|
||||
// memory management
|
||||
|
|
|
|||
Loading…
Reference in New Issue