Skip to content

Commit

Permalink
implement clip planes in GLMakie
Browse files Browse the repository at this point in the history
  • Loading branch information
ffreyer committed Jun 12, 2024
1 parent a77b876 commit 11f4da8
Show file tree
Hide file tree
Showing 15 changed files with 218 additions and 9 deletions.
20 changes: 19 additions & 1 deletion GLMakie/assets/shader/dots.vert
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,29 @@ void colorize(sampler1D color, float intensity, vec2 color_norm){
vec4 _position(vec3 p){return vec4(p,1);}
vec4 _position(vec2 p){return vec4(p,0,1);}

uniform int num_clip_planes;
uniform vec4 clip_planes[8];
out float gl_ClipDistance[8];

void process_clip_planes(vec3 world_pos)
{
// distance = dot(world_pos - plane.point, plane.normal)
// precalculated: dot(plane.point, plane.normal) -> plane.w
for (int i = 0; i < num_clip_planes; i++)
gl_ClipDistance[i] = dot(world_pos, clip_planes[i].xyz) - clip_planes[i].w;

// TODO: can be skipped?
for (int i = num_clip_planes; i < 8; i++)
gl_ClipDistance[i] = 1.0;
}

uniform mat4 projectionview, model;

void main(){
colorize(color_map, color, color_norm);
o_objectid = uvec2(objectid, gl_VertexID+1);
gl_Position = projectionview * model * _position(vertex);
vec4 world_pos = model * _position(vertex);
process_clip_planes(world_pos.xyz);
gl_Position = projectionview * world_pos;
gl_Position.z += gl_Position.w * depth_shift;
}
20 changes: 19 additions & 1 deletion GLMakie/assets/shader/heatmap.vert
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@ ivec2 ind2sub(ivec2 dim, int linearindex){
return ivec2(linearindex % dim.x, linearindex / dim.x);
}

uniform int num_clip_planes;
uniform vec4 clip_planes[8];
out float gl_ClipDistance[8];

void process_clip_planes(vec3 world_pos)
{
// distance = dot(world_pos - plane.point, plane.normal)
// precalculated: dot(plane.point, plane.normal) -> plane.w
for (int i = 0; i < num_clip_planes; i++)
gl_ClipDistance[i] = dot(world_pos, clip_planes[i].xyz) - clip_planes[i].w;

// TODO: can be skipped?
for (int i = num_clip_planes; i < 8; i++)
gl_ClipDistance[i] = 1.0;
}

void main(){
//Outputs for ssao, which we don't use for 2d shaders like heatmap/image
o_view_pos = vec3(0);
Expand All @@ -38,6 +54,8 @@ void main(){
float x = texelFetch(position_x, index2D.x, 0).x;
float y = texelFetch(position_y, index2D.y, 0).x;

gl_Position = projection * view * model * vec4(x, y, 0, 1);
vec4 world_pos = model * vec4(x, y, 0, 1);
process_clip_planes(world_pos.xyz);
gl_Position = projection * view * world_pos;
gl_Position.z += gl_Position.w * depth_shift;
}
12 changes: 12 additions & 0 deletions GLMakie/assets/shader/line_segment.geom
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ struct Nothing{ //Nothing type, to encode if some variable doesn't contain any d
};

layout(lines) in;

// Need to set size of ClipDistance
in gl_PerVertex {
vec4 gl_Position;
float gl_PointSize;
float gl_ClipDistance[8];
} gl_in[];

layout(triangle_strip, max_vertices = 4) out;

uniform vec2 resolution;
Expand Down Expand Up @@ -33,6 +41,7 @@ flat out float f_cumulative_length;
flat out ivec2 f_capmode;
flat out vec4 f_linepoints;
flat out vec4 f_miter_vecs;
out float gl_ClipDistance[8];

const float AA_RADIUS = 0.8;
const float AA_THICKNESS = 2.0 * AA_RADIUS;
Expand Down Expand Up @@ -108,6 +117,9 @@ void main(void)
f_linewidth = halfwidth;
f_id = g_id[x];

for (int i = 0; i < 8; i++)
gl_ClipDistance[i] = gl_in[x].gl_ClipDistance[i];

for (int y = 0; y < 2; y++) {
// Get offset in y direction & compute vertex position
float n_offset = (2 * y - 1) * (halfwidth + AA_THICKNESS);
Expand Down
21 changes: 20 additions & 1 deletion GLMakie/assets/shader/line_segment.vert
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,30 @@ out float g_thickness;
vec4 to_vec4(vec3 v){return vec4(v, 1);}
vec4 to_vec4(vec2 v){return vec4(v, 0, 1);}

uniform int num_clip_planes;
uniform vec4 clip_planes[8];
out float gl_ClipDistance[8];

void process_clip_planes(vec3 world_pos)
{
// distance = dot(world_pos - plane.point, plane.normal)
// precalculated: dot(plane.point, plane.normal) -> plane.w
for (int i = 0; i < num_clip_planes; i++)
gl_ClipDistance[i] = dot(world_pos, clip_planes[i].xyz) - clip_planes[i].w;

// TODO: can be skipped?
for (int i = num_clip_planes; i < 8; i++)
gl_ClipDistance[i] = 1.0;
}


void main()
{
g_id = uvec2(objectid, gl_VertexID + 1);
g_color = color;
g_thickness = px_per_unit * thickness;
gl_Position = projectionview * model * to_vec4(vertex);
vec4 world_pos = model * to_vec4(vertex);
process_clip_planes(world_pos.xyz);
gl_Position = projectionview * world_pos;
gl_Position.z += gl_Position.w * depth_shift;
}
11 changes: 11 additions & 0 deletions GLMakie/assets/shader/lines.geom
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ struct Nothing{ //Nothing type, to encode if some variable doesn't contain any d
{{define_fast_path}}

layout(lines_adjacency) in;

// Need to set size of ClipDistance
in gl_PerVertex {
vec4 gl_Position;
float gl_PointSize;
float gl_ClipDistance[8];
} gl_in[];

layout(triangle_strip, max_vertices = 4) out;

in {{stripped_color_type}} g_color[];
Expand All @@ -34,6 +42,7 @@ flat out float f_cumulative_length;
flat out ivec2 f_capmode;
flat out vec4 f_linepoints;
flat out vec4 f_miter_vecs;
out float gl_ClipDistance[8];

out vec3 o_view_pos;
out vec3 o_view_normal;
Expand Down Expand Up @@ -79,6 +88,8 @@ void emit_vertex(LineVertex vertex) {
f_linestart = vertex.linestart;
f_linelength = vertex.linelength;
f_id = g_id[vertex.index];
for (int i = 0; i < 8; i++)
gl_ClipDistance[i] = gl_in[vertex.index].gl_ClipDistance[i];
EmitVertex();
}

Expand Down
20 changes: 19 additions & 1 deletion GLMakie/assets/shader/lines.vert
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ int get_valid_vertex(Nothing se){return 1;}

uniform float depth_shift;

uniform int num_clip_planes;
uniform vec4 clip_planes[8];
out float gl_ClipDistance[8];

void process_clip_planes(vec3 world_pos)
{
// distance = dot(world_pos - plane.point, plane.normal)
// precalculated: dot(plane.point, plane.normal) -> plane.w
for (int i = 0; i < num_clip_planes; i++)
gl_ClipDistance[i] = dot(world_pos, clip_planes[i].xyz) - clip_planes[i].w;

// TODO: can be skipped?
for (int i = num_clip_planes; i < 8; i++)
gl_ClipDistance[i] = 1.0;
}

void main()
{
g_lastlen = lastlen;
Expand All @@ -43,8 +59,10 @@ void main()
g_thickness = px_per_unit * thickness;

g_color = color;
vec4 world_pos = model * to_vec4(vertex);
process_clip_planes(world_pos.xyz);
#ifdef FAST_PATH
gl_Position = projectionview * model * to_vec4(vertex);
gl_Position = projectionview * world_pos;
#else
gl_Position = to_vec4(vertex);
#endif
Expand Down
3 changes: 3 additions & 0 deletions GLMakie/assets/shader/mesh.vert
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ in vec3 normals;

uniform mat4 projection, view, model;

uniform int num_clip_planes;
uniform vec4 clip_planes[8];

void render(vec4 position_world, vec3 normal, mat4 view, mat4 projection);
vec4 get_color_from_cmap(float value, sampler1D color_map, vec2 colorrange);

Expand Down
10 changes: 10 additions & 0 deletions GLMakie/assets/shader/sprites.geom
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
struct Nothing{ bool _; };

layout(points) in;
// Need to set size of ClipDistance
in gl_PerVertex {
vec4 gl_Position;
float gl_PointSize;
float gl_ClipDistance[8];
} gl_in[];

layout(triangle_strip, max_vertices = 4) out;

mat4 qmat(vec4 quat){
Expand Down Expand Up @@ -61,6 +68,7 @@ flat out uvec2 f_id;
out vec2 f_uv;
flat out vec4 f_uv_texture_bbox;
flat out vec2 f_sprite_scale;
out float gl_ClipDistance[8];

uniform mat4 projection, view, model;

Expand Down Expand Up @@ -89,6 +97,8 @@ void emit_vertex(vec4 vertex, vec2 uv)
f_glow_color = g_glow_color[0];
f_id = g_id[0];
f_sprite_scale = g_offset_width[0].zw;
for (int i = 0; i < 8; i++)
gl_ClipDistance[i] = gl_in[0].gl_ClipDistance[i];
EmitVertex();
}

Expand Down
5 changes: 4 additions & 1 deletion GLMakie/assets/shader/sprites.vert
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,16 @@ out vec4 g_glow_color;

vec4 to_vec4(vec3 x){return vec4(x, 1.0);}
vec4 to_vec4(vec4 x){return x;}
void process_clip_planes(vec3 world_pos);

void main(){
int index = gl_VertexID;
g_primitive_index = index;
vec3 pos;
{{position_calc}}
vec4 p = preprojection * model * vec4(pos, 1);
vec4 world_pos = model * vec4(pos, 1);
process_clip_planes(world_pos.xyz);
vec4 p = preprojection * world_pos;
if (scale_primitive)
g_position = p.xyz / p.w + mat3(model) * marker_offset;
else
Expand Down
19 changes: 19 additions & 0 deletions GLMakie/assets/shader/util.vert
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,23 @@ vec4 _color(Nothing color, float intensity, sampler1D color_map, vec2 color_norm
}


uniform int num_clip_planes;
uniform vec4 clip_planes[8];
out float gl_ClipDistance[8];

void process_clip_planes(vec3 world_pos)
{
// distance = dot(world_pos - plane.point, plane.normal)
// precalculated: dot(plane.point, plane.normal) -> plane.w
for (int i = 0; i < num_clip_planes; i++)
gl_ClipDistance[i] = dot(world_pos, clip_planes[i].xyz) - clip_planes[i].w;

// TODO: can be skipped?
for (int i = num_clip_planes; i < 8; i++)
gl_ClipDistance[i] = 1.0;
}


uniform float depth_shift;

// TODO maybe ifdef SSAO this stuff?
Expand All @@ -271,6 +288,8 @@ out vec3 o_camdir;

void render(vec4 position_world, vec3 normal, mat4 view, mat4 projection)
{
process_clip_planes(position_world.xyz);

// position in view space (as seen from camera)
vec4 view_pos = view * position_world;
view_pos /= view_pos.w;
Expand Down
18 changes: 18 additions & 0 deletions GLMakie/assets/shader/voxel.vert
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@ uniform float depth_shift;
uniform bool depthsorting;
uniform float gap;

uniform int num_clip_planes;
uniform vec4 clip_planes[8];
out float gl_ClipDistance[8];

void process_clip_planes(vec3 world_pos)
{
// distance = dot(world_pos - plane.point, plane.normal)
// precalculated: dot(plane.point, plane.normal) -> plane.w
for (int i = 0; i < num_clip_planes; i++)
gl_ClipDistance[i] = dot(world_pos, clip_planes[i].xyz) - clip_planes[i].w;

// TODO: can be skipped?
for (int i = num_clip_planes; i < 8; i++)
gl_ClipDistance[i] = 1.0;
}


const vec3 unit_vecs[3] = vec3[]( vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1) );
const mat2x3 orientations[3] = mat2x3[](
mat2x3(0, 1, 0, 0, 0, 1), // xy -> _yz (x normal)
Expand Down Expand Up @@ -149,6 +166,7 @@ void main() {
vec3 plane_vertex = size * (orientations[dim] * vertices) + displacement;
vec4 world_pos = model * vec4(plane_vertex, 1.0f);
o_world_pos = world_pos.xyz;
process_clip_planes(world_pos.xyz);
gl_Position = projectionview * world_pos;
gl_Position.z += gl_Position.w * depth_shift;

Expand Down
15 changes: 15 additions & 0 deletions GLMakie/src/GLAbstraction/GLRender.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,26 @@ function render(list::Tuple)
end
return
end

function setup_clip_planes(robj)
N = to_value(get(robj.uniforms, :num_clip_planes, 0))
for i in 0:min(7, N-1)
glEnable(GL_CLIP_DISTANCE0 + UInt32(i))
end
# TODO: This crashes?
# for i in N:7
# glDisable(GL_CLIP_DISTANCE0 + UInt32(i))
# end
end


"""
When rendering a specialised list of Renderables, we can do some optimizations
"""
function render(list::Vector{RenderObject{Pre}}) where Pre
isempty(list) && return nothing
first(list).prerenderfunction()
setup_clip_planes(first(list))
vertexarray = first(list).vertexarray
program = vertexarray.program
glUseProgram(program.id)
Expand Down Expand Up @@ -57,6 +71,7 @@ a lot of objects.
function render(renderobject::RenderObject, vertexarray=renderobject.vertexarray)
if renderobject.visible
renderobject.prerenderfunction()
setup_clip_planes(renderobject)
program = vertexarray.program
glUseProgram(program.id)
for (key, value) in program.uniformloc
Expand Down
4 changes: 2 additions & 2 deletions GLMakie/src/GLAbstraction/GLTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ function RenderObject(
# Otherwise just let the value pass through
# TODO: Is this ok/ever not filtered?
else
# @debug "Passed on $k -> $(typeof(v)) without conversion."
@debug "Passed on $k -> $(typeof(v)) without conversion."
end
end
end
Expand All @@ -403,7 +403,7 @@ function RenderObject(

# remove all uniforms not occuring in shader
# ssao, instances transparency are special for rendering passes. TODO do this more cleanly
special = Set([:ssao, :transparency, :instances, :fxaa])
special = Set([:ssao, :transparency, :instances, :fxaa, :num_clip_planes])
for k in setdiff(keys(data), keys(program.nametype))
if !(k in special)
delete!(data, k)
Expand Down
Loading

0 comments on commit 11f4da8

Please sign in to comment.