Skip to content

Commit 5406520

Browse files
committed
fix orthogonal issue.
1 parent dc0c7c2 commit 5406520

5 files changed

Lines changed: 81 additions & 9 deletions

File tree

‎.polyscope.ini‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"uiScale": 1.0,
3+
"windowHeight": 1352,
4+
"windowPosX": 1283,
5+
"windowPosY": 35,
6+
"windowWidth": 2554
7+
}

‎src/render/opengl/shaders/common.cpp‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,45 @@ vec3 fragmentViewPosition(vec4 viewport, vec2 depthRange, mat4 invProjMat, vec4
179179
return eyePos.xyz / eyePos.w;
180180
}
181181
182+
// Detect if the projection matrix is orthographic.
183+
// In an orthographic projection matrix, projMat[3][3] == 1.0 and projMat[2][3] == 0.0.
184+
// In a perspective projection matrix, projMat[3][3] == 0.0 and projMat[2][3] == -1.0.
185+
bool isOrthoProjection(mat4 projMat) {
186+
return abs(projMat[3][3] - 1.0) < 0.001;
187+
}
188+
189+
// Build ray start and ray direction for fragment-based raycasting.
190+
// For perspective projection: rays originate from the camera (origin) and point towards the fragment view position.
191+
// For orthographic projection: rays are parallel, all pointing in -Z direction in view space,
192+
// starting from the fragment's XY position.
193+
void buildRayForFragment(vec4 viewport, vec2 depthRange, mat4 projMat, mat4 invProjMat, vec4 fragCoord,
194+
out vec3 rayStart, out vec3 rayDir) {
195+
196+
if (isOrthoProjection(projMat)) {
197+
// Orthographic: parallel rays pointing in -Z direction
198+
// Convert fragment screen position to NDC
199+
vec2 ndcXY = ((2.0 * fragCoord.xy) - (2.0 * viewport.xy)) / (viewport.zw) - 1.0;
200+
201+
// Unproject to view space at near plane (NDC z = -1) and far plane (NDC z = 1)
202+
// For orthographic, we just need the XY in view space
203+
vec4 ndcNear = vec4(ndcXY, -1.0, 1.0);
204+
vec4 viewNear = invProjMat * ndcNear;
205+
viewNear /= viewNear.w;
206+
207+
vec4 ndcFar = vec4(ndcXY, 1.0, 1.0);
208+
vec4 viewFar = invProjMat * ndcFar;
209+
viewFar /= viewFar.w;
210+
211+
rayStart = viewNear.xyz;
212+
rayDir = normalize(viewFar.xyz - viewNear.xyz);
213+
} else {
214+
// Perspective: rays from origin through fragment position
215+
vec3 viewPos = fragmentViewPosition(viewport, depthRange, invProjMat, fragCoord);
216+
rayStart = vec3(0.0, 0.0, 0.0);
217+
rayDir = viewPos;
218+
}
219+
}
220+
182221
float fragDepthFromView(mat4 projMat, vec2 depthRange, vec3 viewPoint) {
183222
vec4 clipPos = projMat * vec4(viewPoint, 1.); // only actually need one element of this result, could save work
184223
float z_ndc = clipPos.z / clipPos.w;
@@ -206,6 +245,10 @@ bool raySphereIntersection(vec3 rayStart, vec3 rayDir, vec3 sphereCenter, float
206245
}
207246
}
208247
248+
)"
249+
// Split the raw string literal to avoid compiler string length limits
250+
R"(
251+
209252
bool rayPlaneIntersection(vec3 rayStart, vec3 rayDir, vec3 planePos, vec3 planeDir, out float tHit, out vec3 pHit, out vec3 nHit) {
210253
211254
float num = dot(planePos - rayStart, planeDir);

‎src/render/opengl/shaders/cylinder_shaders.cpp‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ R"(
164164
165165
float LARGE_FLOAT();
166166
vec3 fragmentViewPosition(vec4 viewport, vec2 depthRange, mat4 invProjMat, vec4 fragCoord);
167+
void buildRayForFragment(vec4 viewport, vec2 depthRange, mat4 projMat, mat4 invProjMat, vec4 fragCoord, out vec3 rayStart, out vec3 rayDir);
167168
bool rayTaperedCylinderIntersection(vec3 rayStart, vec3 rayDir, vec3 cylTail, vec3 cylTip, float cylRadTail, float cylRadTip, out float tHit, out vec3 pHit, out vec3 nHit);
168169
float fragDepthFromView(mat4 projMat, vec2 depthRange, vec3 viewPoint);
169170
@@ -173,7 +174,8 @@ R"(
173174
{
174175
// Build a ray corresponding to this fragment
175176
vec2 depthRange = vec2(gl_DepthRange.near, gl_DepthRange.far);
176-
vec3 viewRay = fragmentViewPosition(u_viewport, depthRange, u_invProjMatrix, gl_FragCoord);
177+
vec3 rayStart, rayDir;
178+
buildRayForFragment(u_viewport, depthRange, u_projMatrix, u_invProjMatrix, gl_FragCoord, rayStart, rayDir);
177179
178180
179181
float tipRadius = u_radius;
@@ -184,7 +186,7 @@ R"(
184186
float tHit;
185187
vec3 pHit;
186188
vec3 nHit;
187-
rayTaperedCylinderIntersection(vec3(0., 0., 0), viewRay, tailView, tipView, tailRadius, tipRadius, tHit, pHit, nHit);
189+
rayTaperedCylinderIntersection(rayStart, rayDir, tailView, tipView, tailRadius, tipRadius, tHit, pHit, nHit);
188190
if(tHit >= LARGE_FLOAT()) {
189191
discard;
190192
}

‎src/render/opengl/shaders/sphere_shaders.cpp‎

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ R"(
7373
${ GEOM_DECLARATIONS }$
7474
7575
void buildTangentBasis(vec3 unitNormal, out vec3 basisX, out vec3 basisY);
76+
bool isOrthoProjection(mat4 projMat);
7677
7778
void main() {
7879
@@ -82,7 +83,14 @@ R"(
8283
// Construct the 4 corners of a billboard quad, facing the camera
8384
// Quad is shifted pointRadius toward the camera, otherwise it doesn't actually necessarily
8485
// cover the full sphere due to perspective.
85-
vec3 dirToCam = normalize(-gl_in[0].gl_Position.xyz);
86+
vec3 dirToCam;
87+
if (isOrthoProjection(u_projMatrix)) {
88+
// Orthographic: camera direction is constant +Z in view space
89+
dirToCam = vec3(0.0, 0.0, 1.0);
90+
} else {
91+
// Perspective: camera is at origin, direction varies per point
92+
dirToCam = normalize(-gl_in[0].gl_Position.xyz);
93+
}
8694
vec3 basisX;
8795
vec3 basisY;
8896
buildTangentBasis(dirToCam, basisX, basisY);
@@ -142,6 +150,7 @@ R"(
142150
float LARGE_FLOAT();
143151
vec3 lightSurfaceMat(vec3 normal, vec3 color, sampler2D t_mat_r, sampler2D t_mat_g, sampler2D t_mat_b, sampler2D t_mat_k);
144152
vec3 fragmentViewPosition(vec4 viewport, vec2 depthRange, mat4 invProjMat, vec4 fragCoord);
153+
void buildRayForFragment(vec4 viewport, vec2 depthRange, mat4 projMat, mat4 invProjMat, vec4 fragCoord, out vec3 rayStart, out vec3 rayDir);
145154
bool raySphereIntersection(vec3 rayStart, vec3 rayDir, vec3 sphereCenter, float sphereRad, out float tHit, out vec3 pHit, out vec3 nHit);
146155
float fragDepthFromView(mat4 projMat, vec2 depthRange, vec3 viewPoint);
147156
@@ -151,7 +160,8 @@ R"(
151160
{
152161
// Build a ray corresponding to this fragment
153162
vec2 depthRange = vec2(gl_DepthRange.near, gl_DepthRange.far);
154-
vec3 viewRay = fragmentViewPosition(u_viewport, depthRange, u_invProjMatrix, gl_FragCoord);
163+
vec3 rayStart, rayDir;
164+
buildRayForFragment(u_viewport, depthRange, u_projMatrix, u_invProjMatrix, gl_FragCoord, rayStart, rayDir);
155165
156166
float pointRadius = u_pointRadius;
157167
${ SPHERE_SET_POINT_RADIUS_FRAG }$
@@ -160,7 +170,7 @@ R"(
160170
float tHit;
161171
vec3 pHit;
162172
vec3 nHit;
163-
bool hit = raySphereIntersection(vec3(0., 0., 0), viewRay, sphereCenterView, pointRadius, tHit, pHit, nHit);
173+
bool hit = raySphereIntersection(rayStart, rayDir, sphereCenterView, pointRadius, tHit, pHit, nHit);
164174
if(tHit >= LARGE_FLOAT()) {
165175
discard;
166176
}
@@ -258,14 +268,22 @@ R"(
258268
${ GEOM_DECLARATIONS }$
259269
260270
void buildTangentBasis(vec3 unitNormal, out vec3 basisX, out vec3 basisY);
271+
bool isOrthoProjection(mat4 projMat);
261272
262273
void main() {
263274
264275
float pointRadius = u_pointRadius;
265276
${ SPHERE_SET_POINT_RADIUS_GEOM }$
266277
267278
// Construct the 4 corners of a billboard quad, facing the camera
268-
vec3 dirToCam = normalize(-gl_in[0].gl_Position.xyz);
279+
vec3 dirToCam;
280+
if (isOrthoProjection(u_projMatrix)) {
281+
// Orthographic: camera direction is constant +Z in view space
282+
dirToCam = vec3(0.0, 0.0, 1.0);
283+
} else {
284+
// Perspective: camera is at origin, direction varies per point
285+
dirToCam = normalize(-gl_in[0].gl_Position.xyz);
286+
}
269287
vec3 basisX;
270288
vec3 basisY;
271289
buildTangentBasis(dirToCam, basisX, basisY);

‎src/render/opengl/shaders/vector_shaders.cpp‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ R"(
218218
219219
float LARGE_FLOAT();
220220
vec3 fragmentViewPosition(vec4 viewport, vec2 depthRange, mat4 invProjMat, vec4 fragCoord);
221+
void buildRayForFragment(vec4 viewport, vec2 depthRange, mat4 projMat, mat4 invProjMat, vec4 fragCoord, out vec3 rayStart, out vec3 rayDir);
221222
bool rayCylinderIntersection(vec3 rayStart, vec3 rayDir, vec3 cylTail, vec3 cylTip, float cylRad, out float tHit, out vec3 pHit, out vec3 nHit);
222223
bool rayConeIntersection(vec3 rayStart, vec3 rayDir, vec3 coneBase, vec3 coneTip, float coneRad, out float tHit, out vec3 pHit, out vec3 nHit);
223224
float fragDepthFromView(mat4 projMat, vec2 depthRange, vec3 viewPoint);
@@ -228,7 +229,8 @@ R"(
228229
{
229230
// Build a ray corresponding to this fragment
230231
vec2 depthRange = vec2(gl_DepthRange.near, gl_DepthRange.far);
231-
vec3 viewRay = fragmentViewPosition(u_viewport, depthRange, u_invProjMatrix, gl_FragCoord);
232+
vec3 rayStart, rayDir;
233+
buildRayForFragment(u_viewport, depthRange, u_projMatrix, u_invProjMatrix, gl_FragCoord, rayStart, rayDir);
232234
233235
// geometric shape of hte vector
234236
float tipLengthFrac = 0.2;
@@ -241,13 +243,13 @@ R"(
241243
vec3 nHit = vec3(777,777,777);
242244
vec3 cylEnd = tailView + (1. - tipLengthFrac) * (tipView - tailView);
243245
float cylRad = tipWidthFrac * adjRadius;
244-
rayCylinderIntersection(vec3(0., 0., 0), viewRay, tailView, cylEnd, cylRad, tHit, pHit, nHit);
246+
rayCylinderIntersection(rayStart, rayDir, tailView, cylEnd, cylRad, tHit, pHit, nHit);
245247
246248
// Raycast to cone
247249
float tHitCone;
248250
vec3 pHitCone;
249251
vec3 nHitCone;
250-
bool coneHit = rayConeIntersection(vec3(0., 0., 0), viewRay, cylEnd, tipView, adjRadius, tHitCone, pHitCone, nHitCone);
252+
bool coneHit = rayConeIntersection(rayStart, rayDir, cylEnd, tipView, adjRadius, tHitCone, pHitCone, nHitCone);
251253
if(tHitCone < tHit) {
252254
tHit = tHitCone;
253255
pHit = pHitCone;

0 commit comments

Comments
 (0)