1#include webgl_header.vs
2
3// Sphere impostor vertex shader
4
5uniform float sphere_size_scale;
6
7attribute vec4 a_vertex_radius;
8attribute vec4 a_Color;
9attribute float a_rightUpFlags;
10
11varying vec4 COLOR;
12varying vec3 sphere_center;
13varying float radius2;
14varying vec3 point;
15varying vec2 bgTextureLookup;
16
17/*
18 * horizontial and vertical adjustment of outer tangent hitting the
19 * impostor quad, in model view space.
20 */
21vec2 outer_tangent_adjustment(vec3 center, float radius_sq) {
22    vec2 xy_dist = vec2(length(center.xz), length(center.yz));
23
24    // without clamping, this caused flickering (divide-by-zero)
25    vec2 cos_a = clamp(center.z / xy_dist, -1., 1.);
26    vec2 cos_b = xy_dist / sqrt(radius_sq + (xy_dist * xy_dist));
27
28    // numerically more stable version of:
29    // vec2 tan_ab_sq = pow(tan(acos(cos_b) + acos(cos_a)), 2);
30    vec2 cos_ab = (cos_a * cos_b + sqrt(
31                (1. - cos_a * cos_a) *
32                (1. - cos_b * cos_b)));
33    vec2 cos_ab_sq = cos_ab * cos_ab;
34    vec2 tan_ab_sq = (1. - cos_ab_sq) / cos_ab_sq;
35
36    vec2 adjustment = sqrt(tan_ab_sq + 1.);
37
38    // max out (empirical) to avoid exploding (can happen for spheres outside of the viewport)
39    return min(adjustment, 10.);
40}
41
42void main(void)
43{
44    // Get billboard attributes
45    float radius = a_vertex_radius.w * sphere_size_scale;
46
47    // support uniform scaling
48    radius /= length(g_NormalMatrix[0]);
49
50    float right = -1. + 2.*mod(a_rightUpFlags, 2.);
51    float up = -1. + 2.*floor(mod(a_rightUpFlags/2., 2.));
52    vec4 tmppos = g_ModelViewMatrix * vec4(a_vertex_radius.xyz, 1.);
53
54    COLOR = a_Color;
55    radius2 = radius * radius; // compute squared radius
56
57    // uni-radius corner offset
58    vec2 corner_offset = vec2(right, up);
59
60#ifndef ortho
61    // horizontial and vertical adjustment due to projection
62    corner_offset *= outer_tangent_adjustment(tmppos.xyz, radius2);
63#endif
64
65    // corner vertex
66    vec4 eye_space_pos = tmppos;
67    eye_space_pos.xy += radius * corner_offset;
68
69    // Compute sphere position in modelview space
70    sphere_center = tmppos.xyz / tmppos.w;
71
72    // Compute ray direction and origin point
73    point = eye_space_pos.xyz / eye_space_pos.w;
74
75#ifndef PYMOL_WEBGL_IOS
76    // Pass the transformed vertex for clipping plane calculations
77    gl_ClipVertex = eye_space_pos;
78#endif
79
80    // Pass transformed vertex
81    gl_Position = g_ProjectionMatrix * eye_space_pos;
82    bgTextureLookup = (gl_Position.xy/gl_Position.w) / 2.0 + 0.5;
83}
84
85