97 lines
3.2 KiB
Text
97 lines
3.2 KiB
Text
#version 150 compatibility
|
|
#extension GL_EXT_geometry_shader4 : enable
|
|
|
|
layout(points) in;
|
|
layout(triangle_strip, max_vertices = 4) out;
|
|
|
|
uniform bool measure_point_size_in_pixel;
|
|
uniform float reference_point_size;
|
|
|
|
uniform bool orient_splats;
|
|
uniform float outline_width_from_pixel;
|
|
uniform float percentual_outline_width;
|
|
uniform float percentual_halo;
|
|
uniform float pixel_extent_per_depth;
|
|
|
|
in vec3 normal_gs[];
|
|
in vec4 color_gs[];
|
|
|
|
out vec3 normal;
|
|
out vec2 uv;
|
|
out vec4 color;
|
|
out vec3 position;
|
|
|
|
out float percentual_outline_start;
|
|
out float percentual_halo_start;
|
|
out float percentual_pixel_extent;
|
|
out float percentual_splat_size;
|
|
flat out int side; // 0 is back facing and 1 is front facing
|
|
|
|
int surface_side_handling(in vec3 position, inout vec3 normal, inout vec4 color);
|
|
|
|
void emit_corner(in vec3 corner, in float u, in float v)
|
|
{
|
|
position = corner;
|
|
|
|
uv = vec2(u,v);
|
|
|
|
// compute position in clip space
|
|
gl_Position = gl_ProjectionMatrix * vec4(position,1.0);
|
|
|
|
EmitVertex();
|
|
}
|
|
|
|
void main()
|
|
{
|
|
// set color to color attribute
|
|
color = color_gs[0];
|
|
// transform normal to eye space
|
|
normal = normalize(gl_NormalMatrix*(normal_gs[0]));
|
|
// transform position to eye space
|
|
vec3 position_eye = (gl_ModelViewMatrix*gl_PositionIn[0]).xyz;
|
|
// sign of dot product between normal and view vector tells us side that we see
|
|
float sign_indicator = dot(normal, position_eye);
|
|
|
|
// determine side in eye space
|
|
side = surface_side_handling(position_eye, normal, color);
|
|
if (side == -1)
|
|
return;
|
|
|
|
// compute percentual size of splat and its radius
|
|
float depth = abs(position_eye.z);
|
|
float point_radius = 0.5 * gl_PointSizeIn[0];
|
|
if (measure_point_size_in_pixel) {
|
|
point_radius *= pixel_extent_per_depth * depth;
|
|
}
|
|
else {
|
|
point_radius *= reference_point_size;
|
|
}
|
|
// compute percentage of one pixel with respect to point radius
|
|
percentual_pixel_extent = pixel_extent_per_depth * depth / point_radius;
|
|
float percentual_outline_width_final = max(percentual_outline_width, outline_width_from_pixel * percentual_pixel_extent);
|
|
float percentual_halo_width_final = max(percentual_halo, outline_width_from_pixel * percentual_pixel_extent);
|
|
// compute splat size to be one pixel larger than point plus outline
|
|
percentual_splat_size = 1.0 + 0.5 * (percentual_outline_width_final + percentual_pixel_extent);
|
|
percentual_outline_start = 1.0 - 0.5 * (percentual_outline_width_final + percentual_pixel_extent);
|
|
percentual_halo_start = 2.0;
|
|
if (percentual_halo > 0.0)
|
|
percentual_halo_start = 1.0 - 0.5 * (percentual_halo_width_final + percentual_pixel_extent);
|
|
float splat_radius = point_radius * percentual_splat_size;
|
|
|
|
// compute splat base vectors and scale by splat radius
|
|
vec3 dx = vec3(1.0 ,0.0, 0.0);
|
|
vec3 dy = vec3(0.0, 1.0, 0.0);
|
|
|
|
if (orient_splats) {
|
|
dx = normalize(cross(dy, normal));
|
|
dy = cross(normal, dx);
|
|
}
|
|
dx *= splat_radius;
|
|
dy *= splat_radius;
|
|
|
|
// generate splat vertices
|
|
emit_corner(position_eye + dx - dy, percentual_splat_size, -percentual_splat_size);
|
|
emit_corner(position_eye + dx + dy, percentual_splat_size, percentual_splat_size);
|
|
emit_corner(position_eye - dx - dy, -percentual_splat_size, -percentual_splat_size);
|
|
emit_corner(position_eye - dx + dy, -percentual_splat_size, percentual_splat_size);
|
|
}
|