speck-renderer
Version:
Browser-based WebGL molecule renderer with the goal of producing figures that are as attractive as they are practical.
78 lines (63 loc) • 1.81 kB
JavaScript
const atomsShader = `\
precision highp float;
attribute vec3 aImposter;
attribute vec3 aPosition;
attribute float aRadius;
attribute vec3 aColor;
uniform mat4 uView;
uniform mat4 uProjection;
uniform mat4 uModel;
uniform float uAtomScale;
uniform float uRelativeAtomScale;
uniform float uAtomShade;
varying vec3 vColor;
varying vec3 vPosition;
varying float vRadius;
void main() {
vRadius = uAtomScale * (1.0 + (aRadius - 1.0) * uRelativeAtomScale);
gl_Position = uProjection * uView * uModel * vec4(vRadius * aImposter + aPosition, 1.0);
vColor = mix(aColor, vec3(1,1,1), uAtomShade);
vPosition = vec3(uModel * vec4(aPosition, 1));
}
// __split__
precision highp float;
uniform vec2 uBottomLeft;
uniform vec2 uTopRight;
uniform float uRes;
uniform float uDepth;
uniform int uMode;
varying vec3 vPosition;
varying float vRadius;
varying vec3 vColor;
vec2 res = vec2(uRes, uRes);
float raySphereIntersect(vec3 r0, vec3 rd) {
float a = dot(rd, rd);
vec3 s0_r0 = r0 - vPosition;
float b = 2.0 * dot(rd, s0_r0);
float c = dot(s0_r0, s0_r0) - (vRadius * vRadius);
float disc = b*b - 4.0*a*c;
if (disc <= 0.0) {
return -1.0;
}
return (-b - sqrt(disc))/(2.0*a);
}
void main() {
vec3 r0 = vec3(uBottomLeft + (gl_FragCoord.xy/res) * (uTopRight - uBottomLeft), 0.0);
vec3 rd = vec3(0, 0, -1);
float t = raySphereIntersect(r0, rd);
if (t < 0.0) {
discard;
}
vec3 coord = r0 + rd * t;
vec3 normal = normalize(coord - vPosition);
if (uMode == 0) {
gl_FragColor = vec4(vColor, 1);
} else if (uMode == 1) {
gl_FragColor = vec4(normal * 0.5 + 0.5, 1.0);
}
gl_FragDepthEXT = -coord.z/uDepth;
}`
export default atomsShader;