Skip to content
Snippets Groups Projects
Commit 309e3dd9 authored by Alexander Rose's avatar Alexander Rose
Browse files

impostor per-pixel object clipping

parent 4ff5ed3b
No related branches found
No related tags found
No related merge requests found
...@@ -12,6 +12,7 @@ Note that since we don't clearly distinguish between a public and private interf ...@@ -12,6 +12,7 @@ Note that since we don't clearly distinguish between a public and private interf
- Fix sphere near-clipping with orthographic projection - Fix sphere near-clipping with orthographic projection
- Fix cylinder near-clipping - Fix cylinder near-clipping
- Add interior cylinder caps - Add interior cylinder caps
- Add per-pixel object clipping
## [v3.26.0] - 2022-12-04 ## [v3.26.0] - 2022-12-04
......
export const clip_instance = ` export const clip_instance = `
#if defined(dClipVariant_instance) && dClipObjectCount != 0 #if defined(dClipVariant_instance) && dClipObjectCount != 0
int flag = 0;
#if defined(dClipping)
flag = int(floor(vClipping * 255.0 + 0.5));
#endif
vec4 mCenter = uModel * aTransform * vec4(uInvariantBoundingSphere.xyz, 1.0); vec4 mCenter = uModel * aTransform * vec4(uInvariantBoundingSphere.xyz, 1.0);
if (clipTest(vec4(mCenter.xyz, uInvariantBoundingSphere.w), flag)) if (clipTest(vec4(mCenter.xyz, uInvariantBoundingSphere.w)))
// move out of [ -w, +w ] to 'discard' in vert shader // move out of [ -w, +w ] to 'discard' in vert shader
gl_Position.z = 2.0 * gl_Position.w; gl_Position.z = 2.0 * gl_Position.w;
#endif #endif
......
export const clip_pixel = ` export const clip_pixel = `
#if defined(dClipVariant_pixel) && dClipObjectCount != 0 #if defined(dClipVariant_pixel) && dClipObjectCount != 0
#if defined(dClipping) if (clipTest(vec4(vModelPosition, 0.0)))
int clippingFlag = int(floor(vClipping * 255.0 + 0.5));
#else
int clippingFlag = 0;
#endif
if (clipTest(vec4(vModelPosition, 0.0), clippingFlag))
discard; discard;
#endif #endif
`; `;
\ No newline at end of file
/** /**
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* *
* @author Ludovic Autin <autin@scripps.edu> * @author Ludovic Autin <autin@scripps.edu>
* @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Alexander Rose <alexander.rose@weirdbyte.de>
...@@ -7,45 +7,45 @@ ...@@ -7,45 +7,45 @@
export const common_clip = ` export const common_clip = `
#if dClipObjectCount != 0 #if dClipObjectCount != 0
vec3 quaternionTransform(vec4 q, vec3 v) { vec3 quaternionTransform(const in vec4 q, const in vec3 v) {
vec3 t = 2.0 * cross(q.xyz, v); vec3 t = 2.0 * cross(q.xyz, v);
return v + q.w * t + cross(q.xyz, t); return v + q.w * t + cross(q.xyz, t);
} }
vec4 computePlane(vec3 normal, vec3 inPoint) { vec4 computePlane(const in vec3 normal, const in vec3 inPoint) {
return vec4(normalize(normal), -dot(normal, inPoint)); return vec4(normalize(normal), -dot(normal, inPoint));
} }
float planeSD(vec4 plane, vec3 center) { float planeSD(const in vec4 plane, const in vec3 center) {
return -dot(plane.xyz, center - plane.xyz * -plane.w); return -dot(plane.xyz, center - plane.xyz * -plane.w);
} }
float sphereSD(vec3 position, vec4 rotation, vec3 size, vec3 center) { float sphereSD(const in vec3 position, const in vec4 rotation, const in vec3 size, const in vec3 center) {
return ( return (
length(quaternionTransform(vec4(-rotation.x, -rotation.y, -rotation.z, rotation.w), center - position) / size) - 1.0 length(quaternionTransform(vec4(-rotation.x, -rotation.y, -rotation.z, rotation.w), center - position) / size) - 1.0
) * min(min(size.x, size.y), size.z); ) * min(min(size.x, size.y), size.z);
} }
float cubeSD(vec3 position, vec4 rotation, vec3 size, vec3 center) { float cubeSD(const in vec3 position, const in vec4 rotation, const in vec3 size, const in vec3 center) {
vec3 d = abs(quaternionTransform(vec4(-rotation.x, -rotation.y, -rotation.z, rotation.w), center - position)) - size; vec3 d = abs(quaternionTransform(vec4(-rotation.x, -rotation.y, -rotation.z, rotation.w), center - position)) - size;
return min(max(d.x, max(d.y, d.z)), 0.0) + length(max(d, 0.0)); return min(max(d.x, max(d.y, d.z)), 0.0) + length(max(d, 0.0));
} }
float cylinderSD(vec3 position, vec4 rotation, vec3 size, vec3 center) { float cylinderSD(const in vec3 position, const in vec4 rotation, const in vec3 size, const in vec3 center) {
vec3 t = quaternionTransform(vec4(-rotation.x, -rotation.y, -rotation.z, rotation.w), center - position); vec3 t = quaternionTransform(vec4(-rotation.x, -rotation.y, -rotation.z, rotation.w), center - position);
vec2 d = abs(vec2(length(t.xz), t.y)) - size.xy; vec2 d = abs(vec2(length(t.xz), t.y)) - size.xy;
return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)); return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
} }
float infiniteConeSD(vec3 position, vec4 rotation, vec3 size, vec3 center) { float infiniteConeSD(const in vec3 position, const in vec4 rotation, const in vec3 size, const in vec3 center) {
vec3 t = quaternionTransform(vec4(-rotation.x, -rotation.y, -rotation.z, rotation.w), center - position); vec3 t = quaternionTransform(vec4(-rotation.x, -rotation.y, -rotation.z, rotation.w), center - position);
float q = length(t.xy); float q = length(t.xy);
return dot(size.xy, vec2(q, t.z)); return dot(size.xy, vec2(q, t.z));
} }
float getSignedDistance(vec3 center, int type, vec3 position, vec4 rotation, vec3 scale) { float getSignedDistance(const in vec3 center, const in int type, const in vec3 position, const in vec4 rotation, const in vec3 scale) {
if (type == 1) { if (type == 1) {
vec3 normal = quaternionTransform(rotation, vec3(0.0, 1.0, 0.0)); vec3 normal = quaternionTransform(rotation, vec3(0.0, 1.0, 0.0));
vec4 plane = computePlane(normal, position); vec4 plane = computePlane(normal, position);
...@@ -65,7 +65,7 @@ export const common_clip = ` ...@@ -65,7 +65,7 @@ export const common_clip = `
#if __VERSION__ == 100 #if __VERSION__ == 100
// 8-bit // 8-bit
int bitwiseAnd(int a, int b) { int bitwiseAnd(const in int a, const in int b) {
int d = 128; int d = 128;
int result = 0; int result = 0;
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
...@@ -78,17 +78,23 @@ export const common_clip = ` ...@@ -78,17 +78,23 @@ export const common_clip = `
return result; return result;
} }
bool hasBit(int mask, int bit) { bool hasBit(const in int mask, const in int bit) {
return bitwiseAnd(mask, bit) == 0; return bitwiseAnd(mask, bit) == 0;
} }
#else #else
bool hasBit(int mask, int bit) { bool hasBit(const in int mask, const in int bit) {
return (mask & bit) == 0; return (mask & bit) == 0;
} }
#endif #endif
bool clipTest(const in vec4 sphere) {
// flag is a bit-flag for clip-objects to ignore (note, object ids start at 1 not 0) // flag is a bit-flag for clip-objects to ignore (note, object ids start at 1 not 0)
bool clipTest(vec4 sphere, int flag) { #if defined(dClipping)
int flag = int(floor(vClipping * 255.0 + 0.5));
#else
int flag = 0;
#endif
#pragma unroll_loop_start #pragma unroll_loop_start
for (int i = 0; i < dClipObjectCount; ++i) { for (int i = 0; i < dClipObjectCount; ++i) {
if (flag == 0 || hasBit(flag, UNROLLED_LOOP_INDEX + 1)) { if (flag == 0 || hasBit(flag, UNROLLED_LOOP_INDEX + 1)) {
......
...@@ -34,7 +34,7 @@ bool CylinderImpostor( ...@@ -34,7 +34,7 @@ bool CylinderImpostor(
in vec3 rayOrigin, in vec3 rayDir, in vec3 rayOrigin, in vec3 rayDir,
in vec3 start, in vec3 end, in float radius, in vec3 start, in vec3 end, in float radius,
out vec3 cameraNormal, out bool interior, out vec3 cameraNormal, out bool interior,
out vec3 viewPosition, out float fragmentDepth out vec3 modelPosition, out vec3 viewPosition, out float fragmentDepth
){ ){
vec3 ba = end - start; vec3 ba = end - start;
vec3 oc = rayOrigin - start; vec3 oc = rayOrigin - start;
...@@ -60,8 +60,12 @@ bool CylinderImpostor( ...@@ -60,8 +60,12 @@ bool CylinderImpostor(
if (y > 0.0 && y < baba) { if (y > 0.0 && y < baba) {
interior = false; interior = false;
cameraNormal = (oc + t * rayDir - ba * y / baba) / radius; cameraNormal = (oc + t * rayDir - ba * y / baba) / radius;
viewPosition = (uView * vec4(rayOrigin + t * rayDir, 1.0)).xyz; modelPosition = rayOrigin + t * rayDir;
viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
fragmentDepth = calcDepth(viewPosition); fragmentDepth = calcDepth(viewPosition);
#if defined(dClipVariant_pixel) && dClipObjectCount != 0
if (clipTest(vec4(modelPosition, 0.0))) fragmentDepth = -1.0;
#endif
if (fragmentDepth > 0.0) return true; if (fragmentDepth > 0.0) return true;
} }
...@@ -71,7 +75,8 @@ bool CylinderImpostor( ...@@ -71,7 +75,8 @@ bool CylinderImpostor(
if (abs(k1 + k2 * t) < h) { if (abs(k1 + k2 * t) < h) {
interior = false; interior = false;
cameraNormal = -ba / baba; cameraNormal = -ba / baba;
viewPosition = (uView * vec4(rayOrigin + t * rayDir, 1.0)).xyz; modelPosition = rayOrigin + t * rayDir;
viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
fragmentDepth = calcDepth(viewPosition); fragmentDepth = calcDepth(viewPosition);
if (fragmentDepth > 0.0) return true; if (fragmentDepth > 0.0) return true;
} }
...@@ -81,7 +86,8 @@ bool CylinderImpostor( ...@@ -81,7 +86,8 @@ bool CylinderImpostor(
if (abs(k1 + k2 * t) < h) { if (abs(k1 + k2 * t) < h) {
interior = false; interior = false;
cameraNormal = ba / baba; cameraNormal = ba / baba;
viewPosition = (uView * vec4(rayOrigin + t * rayDir, 1.0)).xyz; modelPosition = rayOrigin + t * rayDir;
viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
fragmentDepth = calcDepth(viewPosition); fragmentDepth = calcDepth(viewPosition);
if (fragmentDepth > 0.0) return true; if (fragmentDepth > 0.0) return true;
} }
...@@ -95,7 +101,8 @@ bool CylinderImpostor( ...@@ -95,7 +101,8 @@ bool CylinderImpostor(
if (y > 0.0 && y < baba) { if (y > 0.0 && y < baba) {
interior = true; interior = true;
cameraNormal = -(oc + t * rayDir - ba * y / baba) / radius; cameraNormal = -(oc + t * rayDir - ba * y / baba) / radius;
viewPosition = (uView * vec4(rayOrigin + t * rayDir, 1.0)).xyz; modelPosition = rayOrigin + t * rayDir;
viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
fragmentDepth = calcDepth(viewPosition); fragmentDepth = calcDepth(viewPosition);
return true; return true;
} }
...@@ -106,7 +113,8 @@ bool CylinderImpostor( ...@@ -106,7 +113,8 @@ bool CylinderImpostor(
if (abs(k1 + k2 * t) < -h) { if (abs(k1 + k2 * t) < -h) {
interior = true; interior = true;
cameraNormal = ba / baba; cameraNormal = ba / baba;
viewPosition = (uView * vec4(rayOrigin + t * rayDir, 1.0)).xyz; modelPosition = rayOrigin + t * rayDir;
viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
fragmentDepth = calcDepth(viewPosition); fragmentDepth = calcDepth(viewPosition);
if (fragmentDepth > 0.0) return true; if (fragmentDepth > 0.0) return true;
} }
...@@ -116,7 +124,8 @@ bool CylinderImpostor( ...@@ -116,7 +124,8 @@ bool CylinderImpostor(
if (abs(k1 + k2 * t) < -h) { if (abs(k1 + k2 * t) < -h) {
interior = true; interior = true;
cameraNormal = -ba / baba; cameraNormal = -ba / baba;
viewPosition = (uView * vec4(rayOrigin + t * rayDir, 1.0)).xyz; modelPosition = rayOrigin + t * rayDir;
viewPosition = (uView * vec4(modelPosition, 1.0)).xyz;
fragmentDepth = calcDepth(viewPosition); fragmentDepth = calcDepth(viewPosition);
if (fragmentDepth > 0.0) return true; if (fragmentDepth > 0.0) return true;
} }
...@@ -127,15 +136,14 @@ bool CylinderImpostor( ...@@ -127,15 +136,14 @@ bool CylinderImpostor(
} }
void main() { void main() {
#include clip_pixel
vec3 rayOrigin = vModelPosition; vec3 rayOrigin = vModelPosition;
vec3 rayDir = mix(normalize(vModelPosition - uCameraPosition), uCameraDir, uIsOrtho); vec3 rayDir = mix(normalize(vModelPosition - uCameraPosition), uCameraDir, uIsOrtho);
vec3 cameraNormal; vec3 cameraNormal;
vec3 modelPosition;
vec3 viewPosition; vec3 viewPosition;
float fragmentDepth; float fragmentDepth;
bool hit = CylinderImpostor(rayOrigin, rayDir, vStart, vEnd, vSize, cameraNormal, interior, viewPosition, fragmentDepth); bool hit = CylinderImpostor(rayOrigin, rayDir, vStart, vEnd, vSize, cameraNormal, interior, modelPosition, viewPosition, fragmentDepth);
if (!hit) discard; if (!hit) discard;
if (fragmentDepth < 0.0) discard; if (fragmentDepth < 0.0) discard;
...@@ -143,7 +151,10 @@ void main() { ...@@ -143,7 +151,10 @@ void main() {
gl_FragDepthEXT = fragmentDepth; gl_FragDepthEXT = fragmentDepth;
vec3 vModelPosition = (uInvView * vec4(viewPosition, 1.0)).xyz; vec3 vViewPosition = viewPosition;
vec3 vModelPosition = modelPosition;
#include clip_pixel
#include assign_material_color #include assign_material_color
#if defined(dRenderVariant_pick) #if defined(dRenderVariant_pick)
......
...@@ -229,7 +229,7 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) { ...@@ -229,7 +229,7 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) {
#if defined(dClipVariant_pixel) && dClipObjectCount != 0 #if defined(dClipVariant_pixel) && dClipObjectCount != 0
vec3 vModelPosition = v3m4(unitPos * uGridDim, modelTransform); vec3 vModelPosition = v3m4(unitPos * uGridDim, modelTransform);
if (clipTest(vec4(vModelPosition, 0.0), 0)) { if (clipTest(vec4(vModelPosition, 0.0))) {
prevValue = value; prevValue = value;
pos += step; pos += step;
continue; continue;
......
...@@ -23,7 +23,7 @@ varying float vRadiusSq; ...@@ -23,7 +23,7 @@ varying float vRadiusSq;
varying vec3 vPoint; varying vec3 vPoint;
varying vec3 vPointViewPosition; varying vec3 vPointViewPosition;
bool SphereImpostor(out vec3 cameraPos, out vec3 cameraNormal, out bool interior, out float fragmentDepth){ bool SphereImpostor(out vec3 modelPos, out vec3 cameraPos, out vec3 cameraNormal, out bool interior, out float fragmentDepth, out bool clipped){
vec3 cameraSpherePos = -vPointViewPosition; vec3 cameraSpherePos = -vPointViewPosition;
vec3 rayOrigin = mix(vec3(0.0, 0.0, 0.0), vPoint, uIsOrtho); vec3 rayOrigin = mix(vec3(0.0, 0.0, 0.0), vPoint, uIsOrtho);
...@@ -40,14 +40,23 @@ bool SphereImpostor(out vec3 cameraPos, out vec3 cameraNormal, out bool interior ...@@ -40,14 +40,23 @@ bool SphereImpostor(out vec3 cameraPos, out vec3 cameraNormal, out bool interior
float negT = mix(B - sqrtDet, B + sqrtDet, uIsOrtho); float negT = mix(B - sqrtDet, B + sqrtDet, uIsOrtho);
cameraPos = rayDirection * negT + rayOrigin; cameraPos = rayDirection * negT + rayOrigin;
modelPos = (uInvView * vec4(cameraPos, 1.0)).xyz;
fragmentDepth = calcDepth(cameraPos); fragmentDepth = calcDepth(cameraPos);
#if defined(dClipVariant_pixel) && dClipObjectCount != 0
if (clipTest(vec4(modelPos, 0.0))) {
clipped = true;
fragmentDepth = -1.0;
}
#endif
if (fragmentDepth > 0.0) { if (fragmentDepth > 0.0) {
cameraNormal = normalize(cameraPos - cameraSpherePos); cameraNormal = normalize(cameraPos - cameraSpherePos);
interior = false; interior = false;
return true; return true;
} else if (uDoubleSided) { } else if (uDoubleSided) {
cameraPos = rayDirection * posT + rayOrigin; cameraPos = rayDirection * posT + rayOrigin;
modelPos = (uInvView * vec4(cameraPos, 1.0)).xyz;
fragmentDepth = calcDepth(cameraPos); fragmentDepth = calcDepth(cameraPos);
cameraNormal = -normalize(cameraPos - cameraSpherePos); cameraNormal = -normalize(cameraPos - cameraSpherePos);
interior = true; interior = true;
...@@ -58,25 +67,27 @@ bool SphereImpostor(out vec3 cameraPos, out vec3 cameraNormal, out bool interior ...@@ -58,25 +67,27 @@ bool SphereImpostor(out vec3 cameraPos, out vec3 cameraNormal, out bool interior
} }
void main(void){ void main(void){
#include clip_pixel vec3 modelPos;
vec3 cameraPos; vec3 cameraPos;
vec3 cameraNormal; vec3 cameraNormal;
float fragmentDepth; float fragmentDepth;
bool hit = SphereImpostor(cameraPos, cameraNormal, interior, fragmentDepth); bool clipped = false;
bool hit = SphereImpostor(modelPos, cameraPos, cameraNormal, interior, fragmentDepth, clipped);
if (!hit) discard; if (!hit) discard;
if (fragmentDepth < 0.0) discard; if (fragmentDepth < 0.0) discard;
if (fragmentDepth > 1.0) discard; if (fragmentDepth > 1.0) discard;
if (interior) { vec3 vViewPosition = cameraPos;
vec3 vModelPosition = modelPos;
if (interior && !clipped) {
fragmentDepth = 0.0 + (0.0000001 / vRadius); fragmentDepth = 0.0 + (0.0000001 / vRadius);
} }
gl_FragDepthEXT = fragmentDepth; gl_FragDepthEXT = fragmentDepth;
vec3 vViewPosition = cameraPos; #include clip_pixel
vec3 vModelPosition = (uInvView * vec4(vViewPosition, 1.0)).xyz;
#include assign_material_color #include assign_material_color
#if defined(dRenderVariant_pick) #if defined(dRenderVariant_pick)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment