123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- /**
- * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- *
- * heavily based on code by WestLangley from https://github.com/WestLangley/three.js/blob/af28b2fb706ac109771ecad0a7447fad90ab3210/examples/js/lines/LineMaterial.js
- */
- export const lines_vert = `
- precision highp float;
- precision highp int;
- #include common
- #include read_from_texture
- #include common_vert_params
- #include color_vert_params
- #include size_vert_params
- #include common_clip
- uniform float uPixelRatio;
- uniform float uViewportHeight;
- attribute mat4 aTransform;
- attribute float aInstance;
- attribute float aGroup;
- attribute vec2 aMapping;
- attribute vec3 aStart;
- attribute vec3 aEnd;
- void trimSegment(const in vec4 start, inout vec4 end) {
- // trim end segment so it terminates between the camera plane and the near plane
- // conservative estimate of the near plane
- float a = uProjection[2][2]; // 3rd entry in 3rd column
- float b = uProjection[3][2]; // 3rd entry in 4th column
- float nearEstimate = -0.5 * b / a;
- float alpha = (nearEstimate - start.z) / (end.z - start.z);
- end.xyz = mix(start.xyz, end.xyz, alpha);
- }
- void main(){
- #include assign_group
- #include assign_color_varying
- #include assign_marker_varying
- #include assign_clipping_varying
- #include assign_size
- mat4 modelView = uView * uModel * aTransform;
- // camera space
- vec4 start = modelView * vec4(aStart, 1.0);
- vec4 end = modelView * vec4(aEnd, 1.0);
- // assign position
- vec4 position4 = vec4((aMapping.y < 0.5) ? aStart : aEnd, 1.0);
- vec4 mvPosition = modelView * position4;
- vViewPosition = mvPosition.xyz;
- vModelPosition = (uModel * aTransform * position4).xyz; // for clipping in frag shader
- // special case for perspective projection, and segments that terminate either in, or behind, the camera plane
- // clearly the gpu firmware has a way of addressing this issue when projecting into ndc space
- // but we need to perform ndc-space calculations in the shader, so we must address this issue directly
- // perhaps there is a more elegant solution -- WestLangley
- bool perspective = (uProjection[2][3] == -1.0); // 4th entry in the 3rd column
- if (perspective) {
- if (start.z < 0.0 && end.z >= 0.0) {
- trimSegment(start, end);
- } else if (end.z < 0.0 && start.z >= 0.0) {
- trimSegment(end, start);
- }
- }
- // clip space
- vec4 clipStart = uProjection * start;
- vec4 clipEnd = uProjection * end;
- // ndc space
- vec2 ndcStart = clipStart.xy / clipStart.w;
- vec2 ndcEnd = clipEnd.xy / clipEnd.w;
- // direction
- vec2 dir = ndcEnd - ndcStart;
- // account for clip-space aspect ratio
- dir.x *= uPixelRatio;
- dir = normalize(dir);
- // perpendicular to dir
- vec2 offset = vec2(dir.y, - dir.x);
- // undo aspect ratio adjustment
- dir.x /= uPixelRatio;
- offset.x /= uPixelRatio;
- // sign flip
- if (aMapping.x < 0.0) offset *= -1.0;
- // calculate linewidth
- float linewidth;
- #ifdef dLineSizeAttenuation
- linewidth = size * uPixelRatio * ((uViewportHeight / 2.0) / -start.z) * 5.0;
- #else
- linewidth = size * uPixelRatio;
- #endif
- // adjust for linewidth
- offset *= linewidth;
- // adjust for clip-space to screen-space conversion
- offset /= uViewportHeight;
- // select end
- vec4 clip = (aMapping.y < 0.5) ? clipStart : clipEnd;
- // back to clip space
- offset *= clip.w;
- clip.xy += offset;
- gl_Position = clip;
- #include clip_instance
- }
- `;
|