molstar
Version:
A comprehensive macromolecular library.
141 lines (117 loc) • 4.39 kB
JavaScript
/**
* Copyright (c) 2019-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
export const spheres_vert = `
precision highp float;
precision highp int;
uniform mat4 uModelView;
uniform mat4 uInvProjection;
uniform float uIsOrtho;
uniform vec2 uTexDim;
uniform sampler2D tPositionGroup;
attribute mat4 aTransform;
attribute float aInstance;
varying float vRadius;
varying vec3 vPoint;
varying vec3 vPointViewPosition;
/**
* Bounding rectangle of a clipped, perspective-projected 3D Sphere.
* Michael Mara, Morgan McGuire. 2013
*
* Specialization by Arseny Kapoulkine, MIT License Copyright (c) 2018
* https://github.com/zeux/niagara
*/
void sphereProjection(const in vec3 p, const in float r, const in vec2 mapping) {
vec3 pr = p * r;
float pzr2 = p.z * p.z - r * r;
float vx = sqrt(p.x * p.x + pzr2);
float minx = ((vx * p.x - pr.z) / (vx * p.z + pr.x)) * uProjection[0][0];
float maxx = ((vx * p.x + pr.z) / (vx * p.z - pr.x)) * uProjection[0][0];
float vy = sqrt(p.y * p.y + pzr2);
float miny = ((vy * p.y - pr.z) / (vy * p.z + pr.y)) * uProjection[1][1];
float maxy = ((vy * p.y + pr.z) / (vy * p.z - pr.y)) * uProjection[1][1];
gl_Position.xy = vec2(maxx + minx, maxy + miny) * -0.5;
gl_Position.xy -= mapping * vec2(maxx - minx, maxy - miny) * 0.5;
gl_Position.xy *= gl_Position.w;
}
void main(void){
vec2 mapping = vec2(1.0, 1.0); // vertices 2 and 5
int m = imod(VertexID, 6);
int m = VertexID % 6;
if (m == 0) {
mapping = vec2(-1.0, 1.0);
} else if (m == 1 || m == 3) {
mapping = vec2(-1.0, -1.0);
} else if (m == 4) {
mapping = vec2(1.0, -1.0);
}
int vertexId = VertexID / 6;
vec4 positionGroup = readFromTexture(tPositionGroup, vertexId, uTexDim);
vec3 position = positionGroup.rgb;
float group = positionGroup.a;
vRadius = size * matrixScale(uModelView);
vec4 position4 = vec4(position, 1.0);
vModelPosition = (uModel * aTransform * position4).xyz; // for clipping in frag shader
float d;
if (uLod.w != 0.0 && (uLod.x != 0.0 || uLod.y != 0.0)) {
d = dot(uCameraPlane.xyz, vModelPosition) + uCameraPlane.w;
float f = min(
smoothstep(uLod.x, uLod.x + uLod.z, d),
1.0 - smoothstep(uLod.y - uLod.z, uLod.y, d)
) * uLod.w;
vRadius *= f;
}
vec4 mvPosition = uModelView * aTransform * position4;
vec4 mvCorner = vec4(mvPosition.xyz, 1.0);
mvCorner.xy += mapping * vRadius;
gl_Position = uProjection * mvCorner;
if (uIsOrtho == 1.0) {
vec4 mvCorner = vec4(mvPosition.xyz, 1.0);
mvCorner.xy += mapping * vRadius;
gl_Position = uProjection * mvCorner;
} else {
gl_Position = uProjection * vec4(mvPosition.xyz, 1.0);
sphereProjection(mvPosition.xyz, vRadius, mapping);
}
vec4 vPoint4 = uInvProjection * gl_Position;
vPoint = vPoint4.xyz / vPoint4.w;
vPointViewPosition = -mvPosition.xyz / mvPosition.w;
if (gl_Position.z < -gl_Position.w) {
mvPosition.z -= 2.0 * vRadius; // avoid clipping
gl_Position.z = (uProjection * vec4(mvPosition.xyz, 1.0)).z;
}
if (uLod.w != 0.0 && (uLod.x != 0.0 || uLod.y != 0.0)) {
if (d < uLod.x || d > uLod.y) {
// move out of [ -w, +w ] to 'discard' in vert shader
gl_Position.z = 2.0 * gl_Position.w;
}
}
if (clipTest(vModelPosition)) {
// move out of [ -w, +w ] to 'discard' in vert shader
gl_Position.z = 2.0 * gl_Position.w;
}
}
`;