#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); }