Przeglądaj źródła

Add fancy line example;

bjorn 9 godzin temu
rodzic
commit
4cdf38fee0
2 zmienionych plików z 172 dodań i 0 usunięć
  1. 171 0
      examples/Effects/Fancy_Line/main.lua
  2. 1 0
      examples/init.lua

+ 171 - 0
examples/Effects/Fancy_Line/main.lua

@@ -0,0 +1,171 @@
+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[]; };
+
+layout(location = 0) flat out vec3 head;
+layout(location = 1) flat out vec3 tail;
+layout(location = 2) flat out vec4 headColor;
+layout(location = 3) flat out vec4 tailColor;
+layout(location = 4) 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.);
+}
+]], [[
+layout(location = 0) flat in vec3 head;
+layout(location = 1) flat in vec3 tail;
+layout(location = 2) flat in vec4 headColor;
+layout(location = 3) flat in vec4 tailColor;
+layout(location = 4) 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

+ 1 - 0
examples/init.lua

@@ -48,6 +48,7 @@ return {
   'Effects/Billboards',
   'Effects/Blur',
   'Effects/Clipping',
+  'Effects/Fancy_Line',
   'Effects/Stereo_Image',
   'Effects/Cubemap_Generate',
   'Effects/Cubemap_Texturing',