Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ misc/file2c/file2cpp

# Editor and OS things
imgui.ini
.polyscope.ini
.DS_Store
.vscode
*.swp
Expand Down
1 change: 0 additions & 1 deletion include/polyscope/camera_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ class CameraView : public QuantityStructure<CameraView> {
// Rendering helpers used by quantities
void setCameraViewUniforms(render::ShaderProgram& p);
std::vector<std::string> addCameraViewRules(std::vector<std::string> initRules, bool withCameraView = true);
std::string getShaderNameForRenderMode();

// Get info related to how the frame is drawn (billboard center vector, center-to-top vector, center-to-right vector)
std::tuple<glm::vec3, glm::vec3, glm::vec3> getFrameBillboardGeometry();
Expand Down
18 changes: 18 additions & 0 deletions include/polyscope/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#include <cstdint>
#include <string>

#include "polyscope/scaled_value.h"
#include "polyscope/types.h"


namespace polyscope {

Expand Down Expand Up @@ -36,5 +39,20 @@ extern float lastRightSideFreeY;
extern float leftWindowsWidth;
extern float rightWindowsWidth;

// Cached versions of lazy properties used for updates
namespace lazy {
extern TransparencyMode transparencyMode;
extern ProjectionMode projectionMode;
extern int transparencyRenderPasses;
extern int ssaaFactor;
extern float uiScale;
extern bool groundPlaneEnabled;
extern GroundPlaneMode groundPlaneMode;
extern ScaledValue<float> groundPlaneHeightFactor;
extern int shadowBlurIters;
extern float shadowDarkness;
} // namespace lazy


} // namespace internal
} // namespace polyscope
2 changes: 2 additions & 0 deletions include/polyscope/render/opengl/shaders/rules.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ extern const ShaderReplacementRule PROJ_AND_INV_PROJ_MAT;
extern const ShaderReplacementRule COMPUTE_SHADE_NORMAL_FROM_POSITION;
extern const ShaderReplacementRule PREMULTIPLY_LIT_COLOR;
extern const ShaderReplacementRule CULL_POS_FROM_VIEW;
extern const ShaderReplacementRule BUILD_RAY_FOR_FRAGMENT_PERSPECTIVE;
extern const ShaderReplacementRule BUILD_RAY_FOR_FRAGMENT_ORTHOGRAPHIC;

ShaderReplacementRule generateSlicePlaneRule(std::string uniquePostfix);
ShaderReplacementRule generateVolumeGridSlicePlaneRule(std::string uniquePostfix);
Expand Down
3 changes: 2 additions & 1 deletion include/polyscope/vector_quantity.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ void VectorQuantity<QuantityT>::drawVectors() {
template <typename QuantityT>
void VectorQuantity<QuantityT>::createProgram() {

std::vector<std::string> rules = this->quantity.parent.addStructureRules({"SHADE_BASECOLOR"});
std::vector<std::string> rules =
this->quantity.parent.addStructureRules({view::getCurrentProjectionModeRaycastRule(), "SHADE_BASECOLOR"});
if (this->quantity.parent.wantsCullPosition()) {
rules.push_back("VECTOR_CULLPOS_FROM_TAIL");
}
Expand Down
3 changes: 3 additions & 0 deletions include/polyscope/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ CameraParameters getCameraParametersForCurrentView(); // contains all of this in
// (these friendly helpers to get the same info as ^^^)
glm::mat4 getCameraViewMatrix();
void setCameraViewMatrix(glm::mat4 newMat);
ProjectionMode getProjectionMode();
void setProjectionMode(ProjectionMode newMode);
glm::mat4 getCameraPerspectiveMatrix();
glm::vec3 getCameraWorldPosition();
void getCameraFrame(glm::vec3& lookDir, glm::vec3& upDir, glm::vec3& rightDir);
Expand Down Expand Up @@ -165,6 +167,7 @@ std::tuple<int, int> screenCoordsToBufferInds(glm::vec2 screenCoords);
glm::ivec2 screenCoordsToBufferIndsVec(glm::vec2 screenCoords);
glm::vec2 bufferIndsToScreenCoords(int xPos, int yPos);
glm::vec2 bufferIndsToScreenCoords(glm::ivec2 bufferInds);
std::string getCurrentProjectionModeRaycastRule();

// == Internal helpers. Should probably not be called in user code.

Expand Down
6 changes: 4 additions & 2 deletions src/camera_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,16 @@ void CameraView::drawPickDelayed() {
void CameraView::prepare() {

{
std::vector<std::string> rules = addStructureRules({"SHADE_BASECOLOR"});
std::vector<std::string> rules =
addStructureRules({view::getCurrentProjectionModeRaycastRule(), "SHADE_BASECOLOR"});
if (wantsCullPosition()) rules.push_back("SPHERE_CULLPOS_FROM_CENTER");
rules = render::engine->addMaterialRules(material, rules);
nodeProgram = render::engine->requestShader("RAYCAST_SPHERE", rules);
}

{
std::vector<std::string> rules = addStructureRules({"SHADE_BASECOLOR"});
std::vector<std::string> rules =
addStructureRules({view::getCurrentProjectionModeRaycastRule(), "SHADE_BASECOLOR"});
if (wantsCullPosition()) rules.push_back("CYLINDER_CULLPOS_FROM_MID");
rules = render::engine->addMaterialRules(material, rules);
edgeProgram = render::engine->requestShader("RAYCAST_CYLINDER", rules);
Expand Down
11 changes: 8 additions & 3 deletions src/curve_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ void CurveNetwork::drawPickDelayed() {

std::vector<std::string> CurveNetwork::addCurveNetworkNodeRules(std::vector<std::string> initRules) {
initRules = addStructureRules(initRules);

initRules.push_back(view::getCurrentProjectionModeRaycastRule());

if (nodeRadiusQuantityName != "" || edgeRadiusQuantityName != "") {
initRules.push_back("SPHERE_VARIABLE_SIZE");
Expand All @@ -233,6 +235,8 @@ std::vector<std::string> CurveNetwork::addCurveNetworkNodeRules(std::vector<std:
std::vector<std::string> CurveNetwork::addCurveNetworkEdgeRules(std::vector<std::string> initRules) {
initRules = addStructureRules(initRules);

initRules.push_back(view::getCurrentProjectionModeRaycastRule());

// use node radius to blend cylinder radius
if (nodeRadiusQuantityName != "" || edgeRadiusQuantityName != "") {
initRules.push_back("CYLINDER_VARIABLE_SIZE");
Expand Down Expand Up @@ -292,9 +296,10 @@ void CurveNetwork::preparePick() {
size_t pickStart = pick::requestPickBufferRange(this, totalPickElements);

{ // Set up node picking program
nodePickProgram =
render::engine->requestShader("RAYCAST_SPHERE", addCurveNetworkNodeRules({"SPHERE_PROPAGATE_COLOR"}),
render::ShaderReplacementDefaults::Pick);
nodePickProgram = render::engine->requestShader(
"RAYCAST_SPHERE",
addCurveNetworkNodeRules({"SPHERE_PROPAGATE_COLOR"}),
render::ShaderReplacementDefaults::Pick);

// Fill color buffer with packed point indices
std::vector<glm::vec3> pickColors;
Expand Down
16 changes: 16 additions & 0 deletions src/internal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,21 @@ float lastRightSideFreeY = 10;
float leftWindowsWidth = -1.;
float rightWindowsWidth = -1.;


namespace lazy {

TransparencyMode transparencyMode = TransparencyMode::None;
ProjectionMode projectionMode = ProjectionMode::Perspective;
int transparencyRenderPasses = 8;
int ssaaFactor = 1;
float uiScale = -1.;
bool groundPlaneEnabled = true;
GroundPlaneMode groundPlaneMode = GroundPlaneMode::TileReflection;
ScaledValue<float> groundPlaneHeightFactor = 0;
int shadowBlurIters = 2;
float shadowDarkness = .4;

} // namespace lazy

} // namespace internal
} // namespace polyscope
3 changes: 3 additions & 0 deletions src/point_cloud.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,9 @@ PointCloudPickResult PointCloud::interpretPickResult(const PickResult& rawResult
std::vector<std::string> PointCloud::addPointCloudRules(std::vector<std::string> initRules, bool withPointCloud) {
initRules = addStructureRules(initRules);
if (withPointCloud) {

initRules.push_back(view::getCurrentProjectionModeRaycastRule());

if (pointRadiusQuantityName != "") {
initRules.push_back("SPHERE_VARIABLE_SIZE");
}
Expand Down
56 changes: 25 additions & 31 deletions src/polyscope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1421,19 +1421,6 @@ void refresh() {
requestRedraw();
}

// Cached versions of lazy properties used for updates
namespace lazy {
TransparencyMode transparencyMode = TransparencyMode::None;
int transparencyRenderPasses = 8;
int ssaaFactor = 1;
float uiScale = -1.;
bool groundPlaneEnabled = true;
GroundPlaneMode groundPlaneMode = GroundPlaneMode::TileReflection;
ScaledValue<float> groundPlaneHeightFactor = 0;
int shadowBlurIters = 2;
float shadowDarkness = .4;
} // namespace lazy

void processLazyProperties() {

// Note: This function essentially represents lazy software design, and it's an ugly and error-prone part of the
Expand All @@ -1448,45 +1435,52 @@ void processLazyProperties() {
// There is a second function processLazyPropertiesOutsideOfImGui() which handles a few more that can only be set
// at limited times when an ImGui frame is not active.

// projection mode
if (internal::lazy::projectionMode != view::projectionMode) {
internal::lazy::projectionMode = view::projectionMode;
view::setProjectionMode(view::projectionMode);
}

// transparency mode
if (lazy::transparencyMode != options::transparencyMode) {
lazy::transparencyMode = options::transparencyMode;
if (internal::lazy::transparencyMode != options::transparencyMode) {
internal::lazy::transparencyMode = options::transparencyMode;
render::engine->setTransparencyMode(options::transparencyMode);
}

// transparency render passes
if (lazy::transparencyRenderPasses != options::transparencyRenderPasses) {
lazy::transparencyRenderPasses = options::transparencyRenderPasses;
if (internal::lazy::transparencyRenderPasses != options::transparencyRenderPasses) {
internal::lazy::transparencyRenderPasses = options::transparencyRenderPasses;
requestRedraw();
}

// ssaa
if (lazy::ssaaFactor != options::ssaaFactor) {
lazy::ssaaFactor = options::ssaaFactor;
if (internal::lazy::ssaaFactor != options::ssaaFactor) {
internal::lazy::ssaaFactor = options::ssaaFactor;
render::engine->setSSAAFactor(options::ssaaFactor);
}

// ground plane
if (lazy::groundPlaneEnabled != options::groundPlaneEnabled || lazy::groundPlaneMode != options::groundPlaneMode) {
lazy::groundPlaneEnabled = options::groundPlaneEnabled;
if (internal::lazy::groundPlaneEnabled != options::groundPlaneEnabled ||
internal::lazy::groundPlaneMode != options::groundPlaneMode) {
internal::lazy::groundPlaneEnabled = options::groundPlaneEnabled;
if (!options::groundPlaneEnabled) {
// if the (depecated) groundPlaneEnabled = false, set mode to None, so we only have one variable to check
options::groundPlaneMode = GroundPlaneMode::None;
}
lazy::groundPlaneMode = options::groundPlaneMode;
internal::lazy::groundPlaneMode = options::groundPlaneMode;
requestRedraw();
}
if (lazy::groundPlaneHeightFactor.asAbsolute() != options::groundPlaneHeightFactor.asAbsolute() ||
lazy::groundPlaneHeightFactor.isRelative() != options::groundPlaneHeightFactor.isRelative()) {
lazy::groundPlaneHeightFactor = options::groundPlaneHeightFactor;
if (internal::lazy::groundPlaneHeightFactor.asAbsolute() != options::groundPlaneHeightFactor.asAbsolute() ||
internal::lazy::groundPlaneHeightFactor.isRelative() != options::groundPlaneHeightFactor.isRelative()) {
internal::lazy::groundPlaneHeightFactor = options::groundPlaneHeightFactor;
requestRedraw();
}
if (lazy::shadowBlurIters != options::shadowBlurIters) {
lazy::shadowBlurIters = options::shadowBlurIters;
if (internal::lazy::shadowBlurIters != options::shadowBlurIters) {
internal::lazy::shadowBlurIters = options::shadowBlurIters;
requestRedraw();
}
if (lazy::shadowDarkness != options::shadowDarkness) {
lazy::shadowDarkness = options::shadowDarkness;
if (internal::lazy::shadowDarkness != options::shadowDarkness) {
internal::lazy::shadowDarkness = options::shadowDarkness;
requestRedraw();
}
};
Expand All @@ -1495,8 +1489,8 @@ void processLazyPropertiesOutsideOfImGui() {
// Like processLazyProperties, but this one handles properties which cannot be changed mid-ImGui frame

// uiScale
if (lazy::uiScale != options::uiScale) {
lazy::uiScale = options::uiScale;
if (internal::lazy::uiScale != options::uiScale) {
internal::lazy::uiScale = options::uiScale;
render::engine->configureImGui();
setInitialWindowWidths();
}
Expand Down
2 changes: 1 addition & 1 deletion src/render/ground_plane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ void GroundPlane::draw(bool isRedraw) {
}
case ProjectionMode::Orthographic: {
glm::vec4 lookDir = glm::vec4(0, 0, 1, 0) * viewMat;
groundPlaneProgram->setUniform("u_cameraHeight", (lookDir.y * state::lengthScale) + groundHeight);
groundPlaneProgram->setUniform("u_cameraHeight", (lookDir[iP] * state::lengthScale) + groundHeight);
break;
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/render/mock_opengl/mock_gl_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1964,6 +1964,8 @@ void MockGLEngine::populateDefaultShadersAndRules() {
registerShaderRule("PREMULTIPLY_LIT_COLOR", PREMULTIPLY_LIT_COLOR);
registerShaderRule("CULL_POS_FROM_VIEW", CULL_POS_FROM_VIEW);
registerShaderRule("PROJ_AND_INV_PROJ_MAT", PROJ_AND_INV_PROJ_MAT);
registerShaderRule("BUILD_RAY_FOR_FRAGMENT_PERSPECTIVE", BUILD_RAY_FOR_FRAGMENT_PERSPECTIVE);
registerShaderRule("BUILD_RAY_FOR_FRAGMENT_ORTHOGRAPHIC", BUILD_RAY_FOR_FRAGMENT_ORTHOGRAPHIC);

// Lighting and shading things
registerShaderRule("LIGHT_MATCAP", LIGHT_MATCAP);
Expand Down
2 changes: 2 additions & 0 deletions src/render/opengl/gl_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2500,6 +2500,8 @@ void GLEngine::populateDefaultShadersAndRules() {
registerShaderRule("PREMULTIPLY_LIT_COLOR", PREMULTIPLY_LIT_COLOR);
registerShaderRule("CULL_POS_FROM_VIEW", CULL_POS_FROM_VIEW);
registerShaderRule("PROJ_AND_INV_PROJ_MAT", PROJ_AND_INV_PROJ_MAT);
registerShaderRule("BUILD_RAY_FOR_FRAGMENT_PERSPECTIVE", BUILD_RAY_FOR_FRAGMENT_PERSPECTIVE);
registerShaderRule("BUILD_RAY_FOR_FRAGMENT_ORTHOGRAPHIC", BUILD_RAY_FOR_FRAGMENT_ORTHOGRAPHIC);

// Lighting and shading things
registerShaderRule("LIGHT_MATCAP", LIGHT_MATCAP);
Expand Down
37 changes: 37 additions & 0 deletions src/render/opengl/shaders/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,39 @@ vec3 fragmentViewPosition(vec4 viewport, vec2 depthRange, mat4 invProjMat, vec4
return eyePos.xyz / eyePos.w;
}

// Build ray start and ray direction for fragment-based raycasting.
// For perspective projection: rays originate from the camera (origin) and point towards the fragment view position.
void buildRayForFragmentPerspective(vec4 viewport, vec2 depthRange, mat4 projMat, mat4 invProjMat, vec4 fragCoord,
out vec3 rayStart, out vec3 rayDir) {
vec3 viewPos = fragmentViewPosition(viewport, depthRange, invProjMat, fragCoord);
rayStart = vec3(0.0, 0.0, 0.0);
rayDir = normalize(viewPos);
}

// Build ray start and ray direction for fragment-based raycasting.
// For orthographic projection: rays are parallel, all pointing in -Z direction in view space,
// starting from the fragment's XY position.
void buildRayForFragmentOrthographic(vec4 viewport, vec2 depthRange, mat4 projMat, mat4 invProjMat, vec4 fragCoord,
out vec3 rayStart, out vec3 rayDir) {

// Orthographic: parallel rays pointing in -Z direction
// Convert fragment screen position to NDC
vec2 ndcXY = ((2.0 * fragCoord.xy) - (2.0 * viewport.xy)) / (viewport.zw) - 1.0;

// Unproject to view space at near plane (NDC z = -1) and far plane (NDC z = 1)
// For orthographic, we just need the XY in view space
vec4 ndcNear = vec4(ndcXY, -1.0, 1.0);
vec4 viewNear = invProjMat * ndcNear;
viewNear /= viewNear.w;

vec4 ndcFar = vec4(ndcXY, 1.0, 1.0);
vec4 viewFar = invProjMat * ndcFar;
viewFar /= viewFar.w;

rayStart = viewNear.xyz;
rayDir = normalize(viewFar.xyz - viewNear.xyz);
}

float fragDepthFromView(mat4 projMat, vec2 depthRange, vec3 viewPoint) {
vec4 clipPos = projMat * vec4(viewPoint, 1.); // only actually need one element of this result, could save work
float z_ndc = clipPos.z / clipPos.w;
Expand Down Expand Up @@ -206,6 +239,10 @@ bool raySphereIntersection(vec3 rayStart, vec3 rayDir, vec3 sphereCenter, float
}
}

)"
// Split the raw string literal to avoid compiler string length limits
R"(

bool rayPlaneIntersection(vec3 rayStart, vec3 rayDir, vec3 planePos, vec3 planeDir, out float tHit, out vec3 pHit, out vec3 nHit) {

float num = dot(planePos - rayStart, planeDir);
Expand Down
6 changes: 3 additions & 3 deletions src/render/opengl/shaders/cylinder_shaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ R"(
layout(location = 0) out vec4 outputF;

float LARGE_FLOAT();
vec3 fragmentViewPosition(vec4 viewport, vec2 depthRange, mat4 invProjMat, vec4 fragCoord);
bool rayTaperedCylinderIntersection(vec3 rayStart, vec3 rayDir, vec3 cylTail, vec3 cylTip, float cylRadTail, float cylRadTip, out float tHit, out vec3 pHit, out vec3 nHit);
float fragDepthFromView(mat4 projMat, vec2 depthRange, vec3 viewPoint);

Expand All @@ -173,7 +172,8 @@ R"(
{
// Build a ray corresponding to this fragment
vec2 depthRange = vec2(gl_DepthRange.near, gl_DepthRange.far);
vec3 viewRay = fragmentViewPosition(u_viewport, depthRange, u_invProjMatrix, gl_FragCoord);
vec3 rayStart, rayDir;
${ BUILD_RAY_FOR_FRAGMENT }$


float tipRadius = u_radius;
Expand All @@ -184,7 +184,7 @@ R"(
float tHit;
vec3 pHit;
vec3 nHit;
rayTaperedCylinderIntersection(vec3(0., 0., 0), viewRay, tailView, tipView, tailRadius, tipRadius, tHit, pHit, nHit);
rayTaperedCylinderIntersection(rayStart, rayDir, tailView, tipView, tailRadius, tipRadius, tHit, pHit, nHit);
if(tHit >= LARGE_FLOAT()) {
discard;
}
Expand Down
Loading