Giter VIP home page Giter VIP logo

perfect-antialiasing's Introduction

Antialiasing via conservative rasterisation and analytical area computation

A new technique for rendering 3D triangles with 'perfect' anti-aliasing. Fonts and vectors are broken into triangles and rasterised conservatively then a fragment shader determines the triangle area coverage to compute the alpha for each fragment.

Process

GPU Rendering of vector graphics at a sub-pixel accuracy:

  1. Triangulate curves into triangles
  2. Render each triangle using conservative rasterisation
  3. For each fragment:
    1. Perform a triangle/box intersection, creating a polygon
    2. Sum the areas of the triangles in the polygon
    3. Divide the sum by the fragment area to give a percentage coverage
    4. Continue for all triangles, additively blending

Preview

Preview

Demos

Visit https://andrewlowndes.github.io/perfect-antialiasing/dist/ to see a set of demos showing the various techniques used in this repo.

Run

  1. Ensure NodeJS installed
  2. Run npm i to install dependencies
  3. Run npm start to open the demos in a web app

Roadmap

  • CPU Demo (Canvas)
    • Cubic/quadratic bezier tesselation
    • Triangulate path to polygons
    • Conservative rasterisation
    • SVG test
    • Cell logic
    • Custom font rendering
  • WebGL
    • Conservative rasterisation (vertex-shader based shifting)
    • Custom font rendering
    • 3D Triangle
    • 3D scene
    • Screen-space tesselation
    • Instancing
    • Performance test
  • Vulkan
    • Screen-space tesselation via geometry shader
    • Conservative rasterisation using gpu extensions
    • Instancing
    • Performance test
  • Further experiments
    • Exact curve coverage analytics
      • Quadratic Bezier
      • Cubic Bezier (prob too complicated)

Usages

  • Anti-aliasing in games (need to assess overhead of conservative rasterisation and the alpha computation in the fragment shader)
  • Font rendering (still relies on triangulation - use screen-space in tesselation shader for resolution independent rendering)

Development

Install VS Code and the following extensions:

  • EditorConfig for VS Code
  • ESLint
  • Prettier

References

Vertex-based conservative rasterisation based off algorithm 2 from GPU Gems 2 Chapter 43 (https://developer.nvidia.com/gpugems/gpugems2/part-v-image-oriented-computing/chapter-42-conservative-rasterization)

perfect-antialiasing's People

Contributors

andrewlowndes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

perfect-antialiasing's Issues

Could you give me some advice on text rendering?

Hi, I'm back with questions againπŸ˜‚.

I have been building a text tool for an UI design project recently, the current solution is the built-in Text of pixi.js. It looks like this:

image

We need zoom to scale lots of texts smoothly, but PIXI.Text use canvas to draw textures to render texts on update, It cost a lot of time, and text polygons needs to be editable like vectors in addition, so I try to find a solution.

First found is triangulation to render texts like this repo's approach, but the curve will produce many triangles, not sure if the performance can meet the requirements.

After that I found an approach was mentioned in this article https://medium.com/@evanwallace/easy-scalable-text-rendering-on-the-gpu-c3f4d782c5ac, I achieved according to it now, but it also has some problems like as follow:

image

There will be impacts between overlaps, I'm be solving it just now.

As a front-end programmer, text rendering and layout makes me feel very distressed, could you give me some suggestions?

cubicBezierToPoints does not consider the symmetry of control points

Current Behavior

when cubic bezier like this:

const p1 = { x: 0.0, y: 200.0 };
const p2 = { x: 100.0, y: 0.0 };
const p3 = { x: 200.0, y: 400.0 };
const p4 = { x: 300.0, y: 200.0 };

render as follow:

image

Expected Behavior

image

Possible Solution

Add flag first to force recursion for the first time

export const cubicBezierToPoints = (
  bezier: CubicBezier,
  splitThreshold: number
): Array<Point> => {
  const points = [
    { x: bezier.p1.x, y: bezier.p1.y },
    { x: bezier.p4.x, y: bezier.p4.y },
  ];

  const cubicBezierSplit = (
    bezier: CubicBezier,
    min: number,
    max: number,
    insertIndex: number,
    first = false
  ) => {
    const time = lerp(min, max, 0.5);
    const midLerp = lerp2(bezier.p2, bezier.p3, time);

    const pointOnCurve = lerp2(
      lerp2(lerp2(bezier.p1, bezier.p2, time), midLerp, time),
      lerp2(midLerp, lerp2(bezier.p3, bezier.p4, time), time),
      time
    );

    const prevPoint = points[insertIndex - 1];
    const nextPoint = points[insertIndex];

    points.splice(insertIndex, 0, pointOnCurve);

    if (
      dot(
        normalize(sub(prevPoint, pointOnCurve)),
        normalize(sub(nextPoint, pointOnCurve))
      ) > splitThreshold ||
      first
    ) {
      cubicBezierSplit(bezier, time, max, insertIndex + 1);
      cubicBezierSplit(bezier, min, time, insertIndex);
    }
  };

  cubicBezierSplit(bezier, 0, 1, 1, true);

  return points;
};

Can't understand DDA algorithm implementation

First of all, thank you very much for creating this project, I learned a lot from it πŸ‘πŸ‘πŸ‘.
Several demo codes are easy to understand, but when I saw the dda algorithm, I was very confused.
I searched the implementation of the dda algorithm, it seems very simple, the code is as follows:

image
image

Why are the algorithms in the project so different, what are the differences between them, and how to understand this code

export const dda = (p1: Point, p2: Point, opts: DdaOptions, cb: (cellPos: Point) => boolean | void) => {
    const dir = normalize(sub(p2, p1));
    const relativePos = sub(p1, opts.pos);
    const cellPos = floor(divide(relativePos, opts.cellSize));
    const tDelta = abs(divide(opts.cellSize, dir));
    const step = sign(dir);
    const distToClosestCell = multiply(opts.cellSize, add(cellPos, sign(adds(step, 1))));
    const tMax = divide(sub(distToClosestCell, relativePos), dir);
    const stopCell = floor(divide(sub(p2, opts.pos), opts.cellSize));
    
    for (let i = 0; i < opts.maxSteps; i++) {
        if (opts.min && opts.max && !inRange(cellPos, opts.min, opts.max)) {
            return true;
        }
        if (cb(cellPos) === false) {
            return false;
        }
        if (equal(stopCell, cellPos)) {
            return true;
        }
        if (tMax.x < tMax.y) {
            tMax.x += tDelta.x;
            cellPos.x += step.x;
        }
        else {
            tMax.y += tDelta.y;
            cellPos.y += step.y;
        }
    }
    return true;
};

Any help would be greatly appreciated!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.