| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- local function knot(u, p, q, r)
- local c1, s1 = math.cos(u), math.sin(u)
- local c2, s2 = math.cos(q / p * u), math.sin(q / p * u)
- return
- r * (2 + c2) * .5 * c1,
- r * (2 + c2) * .5 * s1,
- r * s2 * .5
- end
- points = {}
- local ct = 300
- local p, q, r = 2, 3, 1
- for t = 0, ct do
- local th = t / ct * p * 2 * math.pi
- local x, y, z = knot(th, p, q, r)
- table.insert(points, x)
- table.insert(points, y)
- table.insert(points, z)
- end
- local quads = {}
- local indexData = { 0,1,2, 2,1,3 ; 1,5,3, 3,5,7 }
- for i = 1, ct do
- for j = 1, #indexData do
- table.insert(quads, (i - 1) * 8 + indexData[j])
- end
- end
- local vertices = lovr.graphics.newBuffer('float', points)
- local indices = lovr.graphics.newBuffer('u16', quads)
- local shader = lovr.graphics.newShader([[
- readonly buffer Points { float data[]; };
- flat out vec3 head;
- flat out vec3 tail;
- flat out vec4 headColor;
- flat out vec4 tailColor;
- out float width;
- vec3 hsv2rgb(vec3 c) {
- vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
- vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
- return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
- }
- vec4 lovrmain() {
- uint p = 3 * (VertexIndex >> 3);
- head = vec3(ViewFromLocal * vec4(data[p + 0], data[p + 1], data[p + 2], 1.));
- tail = vec3(ViewFromLocal * vec4(data[p + 3], data[p + 4], data[p + 5], 1.));
- vec4 headClip = ClipFromView * vec4(head, 1.);
- vec4 tailClip = ClipFromView * vec4(tail, 1.);
- vec3 mid = mix(head, tail, .5);
- vec3 az = normalize(tail - head);
- vec3 a_ = normalize(cross(az, mid));
- vec3 ax = normalize(cross(az, a_));
- vec3 ay = normalize(cross(az, ax));
- float x = (VertexIndex & 0x1) >> 0;
- float y = (VertexIndex & 0x2) >> 1;
- float z = (VertexIndex & 0x4) >> 2;
- if (dot(mid, ax) > 0.) x = 1. - x;
- if (dot(mid, az) < 0.) z = 1. - z;
- width = .4;
- float w = mix(headClip.w, tailClip.w, z);
- if (w > 0.) {
- float minPixelWidth = 1.;
- width = max(width, Projection[0][0] * w * (minPixelWidth / Resolution.x));
- }
- vec3 local = vec3(x - .5, y - .5, z);
- mat3 basis = mat3(ax * width, ay * width, az * (length(tail - head) + width));
- vec3 start = head - az * width * .5;
- PositionWorld = start + basis * local;
- headColor = vec4(hsv2rgb(vec3(float(p/3 + 0) / 101., 1, 1)), 1.);
- tailColor = vec4(hsv2rgb(vec3(float(p/3 + 1) / 101., 1, 1)), 1.);
- return ClipFromView * vec4(PositionWorld, 1.);
- }
- ]], [[
- flat in vec3 head;
- flat in vec3 tail;
- flat in vec4 headColor;
- flat in vec4 tailColor;
- in float width;
- layout(depth_less) out float FragDepth;
- vec4 lovrmain() {
- vec3 A = tail - head;
- vec3 B = head;
- float AoA = dot(A, A);
- float AoB = dot(A, B);
- float BoB = dot(B, B);
- float r = width * .5;
- int coverage = 0;
- float param;
- for (int i = 0; i < 4; i++) {
- vec3 N = normalize(interpolateAtSample(PositionWorld, i));
- float NoA = dot(N, A);
- float NoB = dot(N, B);
- float a = AoA - NoA * NoA;
- float t1 = clamp((NoB * NoA - AoB) / a, 0., 1.);
- float t2 = t1 * NoA + NoB;
- float dist = distance(N * t2, head + A * t1);
- if (dist <= r) {
- coverage |= (1 << i);
- param = t1;
- }
- }
- gl_SampleMask[0] = coverage;
- if (coverage == 0) {
- discard;
- }
- vec3 N = normalize(PositionWorld);
- B = -head;
- AoB = dot(A, B);
- BoB = dot(B, B);
- float NoA = dot(N, A);
- float NoB = dot(N, B);
- // Quadratic formula
- float a = AoA - NoA * NoA;
- float b = AoA * NoB - AoB * NoA;
- float c = AoA * BoB - AoB * AoB - r * r * AoA;
- float d = max(b * b - a * c, 0.);
- float t1 = (-b - sqrt(d)) / a;
- float t2 = (AoB + t1 * NoA) / AoA;
- // If the hit is outside the cylindrical part of the capsule, see if it intersects the end caps
- if (t2 <= 0. || t2 >= 1.) {
- vec3 C = t2 <= 0. ? B : -tail;
- b = dot(N, C);
- c = dot(C, C) - r * r;
- d = max(b * b - c, 0.);
- t1 = -b - sqrt(d);
- }
- vec3 P = N * t1;
- vec4 clip = Projection * vec4(P, 1.);
- FragDepth = clip.z / clip.w;
- return Color * mix(headColor, tailColor, clamp(t2, 0., 1.));
- }
- ]])
- function lovr.draw(pass)
- pass:push()
- pass:translate(0, 1.7, -3)
- pass:rotate(lovr.timer.getTime() / 3, 0, 1, 0)
- pass:setShader(shader)
- pass:send('Points', vertices)
- pass:mesh(nil, indices)
- pass:pop()
- end
|