I have two questions regarding GLSL and would appreciate any insights: glsl_planar_mesh_clip.gh (31.2 KB)
Q1: Clipping Mesh with Bounding Box: As shown in the image, I have a planar mesh with inner holes. I want to use GLSL to display only the intersection (highlighted in blue) between this mesh and a specific Bounding Box (BBox). My current approach involves passing the min and max points of the BBox as uniforms. Is passing these two points the only way to achieve this, or is there a method to input the entire BBox object directly into the shader?
Q2: Shading Internal Areas Without Geometry: Following the previous question, is there a way to color the “hole” areas (as shown in the image, colored red) using GLSL, without actually generating the physical geometry for those holes in the original mesh?
#version 330
// Input mesh vertex position
layout(location = 0) in vec3 _meshVertex;
// Matrix to transform vertex from world space to clip space
uniform mat4 _worldToClip;
// Pass local vertex coordinates for clipping in fragment shader
out vec3 v_localPos;
void main() {
// Pass local position directly
v_localPos = _meshVertex;
gl_Position = _worldToClip * vec4(_meshVertex, 1.0);
}
Fragment:
#version 330
// Input color from the application
uniform vec4 color_;
// Bounding box for clipping
uniform vec3 clipMin_;
uniform vec3 clipMax_;
// Received local position from vertex shader
in vec3 v_localPos;
// Output color for the fragment
out vec4 fragment_color;
void main() {
// Clipping logic: discard pixels outside the min/max bounds
if (v_localPos.x < clipMin_.x || v_localPos.x > clipMax_.x ||
v_localPos.y < clipMin_.y || v_localPos.y > clipMax_.y ||
v_localPos.z < clipMin_.z || v_localPos.z > clipMax_.z) {
discard;
}
// Apply the input color
fragment_color = color_;
}
However, the issue now is that Z-fighting persists on the section plane during viewport zooming and real-time geometry updates. This causes the red fill to flicker or drop out intermittently. As shown below:
Geometry:
#version 330
layout(triangles) in;
layout(triangle_strip, max_vertices = 7) out;
uniform mat4 _worldToClip;
uniform vec3 bboxCorners_[8];
uniform float _cameraFar;
uniform float _cameraNear;
in vec3 v_pos_world[];
out vec3 f_pos_world;
out float f_type;
void main() {
// 1. Calculate an adaptive bias based on the entire viewing range
// This ensures that regardless of the scene scale, the bias is effective.
float range = _cameraFar - _cameraNear;
float adaptiveBias = range * 0.000005; // Base ratio for depth separation
// PART A: Render the Blue Mesh
for (int i = 0; i < 3; i++) {
f_type = 0.0;
f_pos_world = v_pos_world[i];
vec4 clipPos = _worldToClip * vec4(v_pos_world[i], 1.0);
// Pull forward: bias scaled by w and the camera range
clipPos.z -= adaptiveBias * clipPos.w;
gl_Position = clipPos;
EmitVertex();
}
EndPrimitive();
// PART B: Render the Dynamic Red Section Plane
if (gl_PrimitiveID == 0) {
f_type = 1.0;
vec3 p0 = v_pos_world[0];
vec3 v1 = normalize(v_pos_world[1] - p0);
vec3 v2 = normalize(v_pos_world[2] - p0);
vec3 normal = normalize(cross(v1, v2));
vec3 tangent = v1;
vec3 bitangent = normalize(cross(normal, tangent));
float S = 0.0;
for(int i = 0; i < 8; i++) {
float dist = distance(p0, bboxCorners_[i]);
if(dist > S) S = dist;
}
S *= 1.1;
vec3 corners[4];
corners[0] = p0 + (-tangent - bitangent) * S;
corners[1] = p0 + ( tangent - bitangent) * S;
corners[2] = p0 + (-tangent + bitangent) * S;
corners[3] = p0 + ( tangent + bitangent) * S;
for (int i = 0; i < 4; i++) {
f_pos_world = corners[i];
vec4 clipPos = _worldToClip * vec4(corners[i], 1.0);
// Push backward: bias scaled by w and the camera range
clipPos.z += adaptiveBias * clipPos.w;
gl_Position = clipPos;
EmitVertex();
}
EndPrimitive();
}
}