|
73 | 73 | ${ GEOM_DECLARATIONS }$ |
74 | 74 |
|
75 | 75 | void buildTangentBasis(vec3 unitNormal, out vec3 basisX, out vec3 basisY); |
| 76 | + bool isOrthoProjection(mat4 projMat); |
76 | 77 |
|
77 | 78 | void main() { |
78 | 79 | |
|
82 | 83 | // Construct the 4 corners of a billboard quad, facing the camera |
83 | 84 | // Quad is shifted pointRadius toward the camera, otherwise it doesn't actually necessarily |
84 | 85 | // 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 | + } |
86 | 94 | vec3 basisX; |
87 | 95 | vec3 basisY; |
88 | 96 | buildTangentBasis(dirToCam, basisX, basisY); |
|
142 | 150 | float LARGE_FLOAT(); |
143 | 151 | vec3 lightSurfaceMat(vec3 normal, vec3 color, sampler2D t_mat_r, sampler2D t_mat_g, sampler2D t_mat_b, sampler2D t_mat_k); |
144 | 152 | 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); |
145 | 154 | bool raySphereIntersection(vec3 rayStart, vec3 rayDir, vec3 sphereCenter, float sphereRad, out float tHit, out vec3 pHit, out vec3 nHit); |
146 | 155 | float fragDepthFromView(mat4 projMat, vec2 depthRange, vec3 viewPoint); |
147 | 156 | |
|
151 | 160 | { |
152 | 161 | // Build a ray corresponding to this fragment |
153 | 162 | 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); |
155 | 165 |
|
156 | 166 | float pointRadius = u_pointRadius; |
157 | 167 | ${ SPHERE_SET_POINT_RADIUS_FRAG }$ |
|
160 | 170 | float tHit; |
161 | 171 | vec3 pHit; |
162 | 172 | 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); |
164 | 174 | if(tHit >= LARGE_FLOAT()) { |
165 | 175 | discard; |
166 | 176 | } |
@@ -258,14 +268,22 @@ R"( |
258 | 268 | ${ GEOM_DECLARATIONS }$ |
259 | 269 |
|
260 | 270 | void buildTangentBasis(vec3 unitNormal, out vec3 basisX, out vec3 basisY); |
| 271 | + bool isOrthoProjection(mat4 projMat); |
261 | 272 |
|
262 | 273 | void main() { |
263 | 274 | |
264 | 275 | float pointRadius = u_pointRadius; |
265 | 276 | ${ SPHERE_SET_POINT_RADIUS_GEOM }$ |
266 | 277 | |
267 | 278 | // 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 | + } |
269 | 287 | vec3 basisX; |
270 | 288 | vec3 basisY; |
271 | 289 | buildTangentBasis(dirToCam, basisX, basisY); |
|
0 commit comments