Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Stanford CS248: Implement an SVG Rasterizer (github.com/stanford-cs248)
208 points by adamnemecek on March 20, 2020 | hide | past | favorite | 80 comments


Same author (kayvonf) was behind this post, "Do Grades Matter? A Discussion About Thinking Bigger While at CMU" [1], a while back :).

[1] https://news.ycombinator.com/item?id=14694179


I've already implemented an SVG renderer at https://www.amanithsvg.com based on our openvg engine with software rasterization https://www.amanithvg.com

Both are closed source, but there are evaluation version available, if someone is interested in compare rendering quality and speed.


Why did you name a closed source product openX? :)


The name is AmanithVG and it is an implementation of OpenVG (a standard API for 2D vector graphics from Khronos group).


Can you recommend some resources for someone trying to do the same?


You can look at software rasterization from good opensource libs: Freetype, Agg, Cairo.


What's a good JavaScript-based solution to render SVG into an image? html2canvas doesn't work well with SVG, especially those heavily styled with CSS.


If you're not in a Node.js context, the Canvas API does a decent job of rasterizing SVGs nowadays. Once rasterized, you can call canvas.toDataURL() to get a download link. Here's a demo:

https://codepen.io/hypothete/pen/WNvKLEE


I used to have troubles with retina displays, I always got a blurred image, no matter to what trick I tried. Is there a way to fix the rendering pixel ratio to 1?


The usual approach with canvas for high dpi is to increase the size of the canvas and then scale it back down afterwards: https://codepen.io/graup/pen/jOPpopR


This downloads 200x200. How to scale it back to 100x100? Ideally so that the image is the same no matter the display where it was exported on. Also I would like to not need to include any image processing libs. The usecase is to export a HTML element (e.g. a chart) and send to another API (e.g. attach it to a report), without downloading.


Does the css need to be inlined?



Yup this is the problem. Workable but painful.


I’m surprised no one mentioned canvg: https://canvg.github.io/canvg/demo/index.html

If using CSS with SVG is important then it’s actually better to use a backend with a library like librsvg (e.g. Cairo) then run node-canvas on top of it like automattic does. Even Inkscape has problems with CSS in SVG files. CSS in browsers is subjective because nowadays they might be using an style that doesn’t have a straightforward approach that can be rasterized. I haven’t had much luck with rasterizing SVG styles past CSS2 spec.



This looks great, will test it out, thx!


Shameless Plug for a library I helped write: https://github.com/SVG-Edit/svgedit


This looks so cool! But your demo link is broken :(


not javascript, but screenshots work best - other approaches suffer from css and rendering bugs. best way is to just use your browser in headless mode from the command line. you can do a screenshot, and specify the window size.

https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Hea...

https://developers.google.com/web/updates/2017/04/headless-c...

and in dev panel https://developer.mozilla.org/en-US/docs/Tools/Taking_screen...


Does Path2D cover it? If it does, seems like you could just draw to a canvas and save the result. https://developer.mozilla.org/en-US/docs/Web/API/Path2D/Path...


Did not know this. Is that due to browser issues or a specification issue?


https://github.com/shakiba/svgexport

Is that what you’re looking for?


No. It does a perfect job because Puppeteer is just Chrome, not JavaScript :) Thanks though!


Kinda defeats the whole purpose of SVG. Only photos should be bitmaps. Graphics should be vectors. This is the 21st century, folks...


True, but if you have digital display - that is, which have separate, immovable pixels, working with pixels and not with vector-based analog primitives - you'll eventually have to convert "vector" picture into "pixel" picture.


Do you have a vector display of some kind?

No?

So someone somewhere is going to need to rasterise your vectors if you want to see them on a screen, aren't they?


I wish for that world to exist, but rasterized images are much easier to share and render nicely in iMessages etc.


One reason is to generate screenshots of HTML by combining this technique with SVG <foreignObject>.


Is there a similar course about Boolean operations on general Bezier shapes out there somewhere? Thanks!


Check out https://cs184.eecs.berkeley.edu/sp20

That's the class I'm currently taking.


Is there any good book/resource about how all that fancy stuff you can use in Inkscape/Illustrator is actually implemented in terms of rendering. E.g. how are curves and lines with a thickness rendered or shapes that are defined by boolean operations etc. ?


Does anyone know similar courses where you get to do similar kind of practical assignments?


CS148 [1] varies from year to year (most people complained that I made the final assignment on subdivision surfaces too hard, but I had at least a few "Thank you, this was awesome") and is the pre-cursor to 248. I'd recommend it if you're getting started.

If you like ray tracing, Cem Yuksel currently teaches most of the related courses at Utah [2].

[1] http://web.stanford.edu/class/cs148/assignments.html

[2] http://www.cemyuksel.com/courses/


Sometimes I kick myself for not doing CS while I was at Utah. :(


There's tons of material online now. If you want a "traditional Utah graphics" curriculum, Cem is teaching most of the stuff (with updates!) from 15 years ago. You can also probably find the old course slides and assignments. I'd suggest cs6620, personally:

https://graphics.cs.utah.edu/courses/cs6620/fall2019/


CS 140 (hope I remembered the course number right) where you write an operating system mostly from scratch is notoriously time consuming and rewarding, at least back when I was there.

Edit: http://www.scs.stanford.edu/20wi-cs140/notes/


As an alternative if you build SDKs or do work in gaming, mobile, or anything involving images really you will end up understanding / implementing this or more than this.


An interesting challenge, are the accompanying lectures also available?


Slides are available at http://cs248.stanford.edu/winter20/


The code doesn't strike me as very well structured nor documenten. Too bad, because it's an interesting challenge


It's pretty ridiculous and has a ton of just bizarre stuff you have to read through (and do!) to even get to something remotely interesting.

One of the first projects I "assigned" to myself when learning to program was to create a 3d environment and be able to scale, rotate, translate objects in 3d. It was easy and fun because I got to choose the language, the rules, etc.

This assignment makes me cringe a bit because there are a lot of hoops to jump through. But yeah, I guess, no pain no gain or something like that :)


This is a good example of a CS project you would do at Stanford and wouldn't get assigned at your local university.


I talk to people who think a CS degree has the same content and the same level of rigour and challenge everywhere. Absolutely baffles me.


Is that true for literally any degree from a top 5 university?


What makes you so confident saying this?


Because I’ve been to multiple universities myself and I know it to not be true from my own eyes.

You can also just go to any university website yourself and compare their syllabi and see how different they are.


No. We implemented a 3d software frame buffer pipeline at my non-Standford, non-"elite" computer science school, in C and with no dependencies other than the standard library, for our computer graphics class.


Well, that is a good example of an assignment you'd do at your local university and wouldn't get assigned at Stanford.


They're the same. The only difference here is you have to use an xml parsing library to read the input instead of rolling your own parser and spec.


You can easily do this on your own.


I think the spirit of the post is correct: the quality of instructors can dramatically increase the quality and relevance of course content in the curriculum. Stanford courses tend to produce new, interesting assignments that other schools crib. Same applies to all the top engineering departments.

My friend tried to get a CS degree at Pepperdine and the curriculum was 15 years out of date. To students who are new to the field, it is hard to figure out where to start even if they could do it independently.


If "you" are 19 and can do this on your own, then chances are you are a CS student at Stanford, or a peer institution.


I don't understand your point.


Can you work us through what you don’t understand?


So? You can do anything on your own given enough effort and discipline.


2d graphics are kinda hard. The problem is that gpus don't support them out of the box so you have to do a Lot yourself.


I assume the point is that you have to implement a pure software rasterizer. It's not actually that difficult, but it feels like a lot for an undergrad who's not familiar with the space. I assume this is done as part of a class that gives you context.

For an example of a rasterizer, you can take a look at my pure JS implementation of canvas (which is roughly the same imaging model as SVG). All lines and shapes are flattened into a pure line polygon, then drawn with a scanline rasterizer. Getting the basics working is fairly easy. Handling the endless edge cases, however.... :)

https://github.com/joshmarinacci/node-pureimage


Yeah, writing a scanline rasterizer from scratch is fun. For beginners, I advocate the sample-based approach I've written about, as functional "is inside shape" can be easier to reason about for simple cases. It's harder for non-convex polygons though :)

https://magcius.github.io/xplain/article/rast1.html

The edge cases are similar -- precision in computing the path intersections and winding curves.


Making a 2D rasterizer is fairly trivial, making a rasterizer that looks good is insanely difficult. Handling things like aliasing without overblowing and making it work in all possible cases is tricky and one spends 99% of time addressing those tiny little details that "make one fall in love with software".


It's get somewhat tricky when you want things like gpu support, text rendering etc.

You have to do things like stencil texture to speed things up etc etc.


GPUs aren't really designed for 2D graphics out of the box. I've written about this before [0].

Text rendering can be tricky, but not that much trickier -- it's just the same curves at smaller scales.

Not sure what you mean by stencil textures. Are you talking about the NV_path_rendering approach where you stencil out the path? Yeah, that's not really a thing that people do these days.

[0] https://blog.mecheye.net/2019/05/why-is-2d-graphics-is-harde...


> it's just the same curves at smaller scales.

It's not that simple unfortunately. Hinting for TrueType fonts is a thing and without properly aligning resulting pixels at their own scale fonts tend to look very ugly when following pure curve definitions. Oversampling at e.g. 8x size is one possible option but then there are other problems that pop up once downscaling to display size.


Yeah I'm talking about that. What do people use then?


Fast, efficient 2D graphics using the PostScript (i.e. SVG) rendering model is still an open research problem. Most shipping implementations these days do full tessellation to triangles on CPU.


This is a beginner CS course, it's a lot simpler than that.


Of course GPUs support 2D. It is just 3D with one less dimension.


What do you mean GPUs don't support them? Most opengl tutorials I've read have people building triangles in 2d to learn fragment shaders and vertices before going 3d. Most of them also support parametric curves, so even hardware accelerated bezier curves should be possible.


Wait, why do you say GPUs support parametric curves? GPUs are based on triangles mostly.



That's like saying "GPUs support Master Chief". You can model Master Chief with triangles, and you can model parametric curves with triangles. But I wouldn't call it "supporting parametric curves", you're still rasterizing triangles, they're just morphed into the shape of a curve. And most practical, shipping versions of this technique would do adaptive triangulation on the CPU, since otherwise you don't have an idea of your mesh density and are either over-submitting or under-submitting triangles.

Loop-Blinn, similarly, is mostly a CPU-side approach and has a lot of drawbacks, but at it's core it's using the pixel shader to define a curve profile.


The parametric curves don't get transformed into triangles. This isn't tessellation or similar techniques. You aren't feeding the GPU any triangles - you're only feeding it the function that defines the parametric curve. Then, using that function for the parametric curve the GPU can calculate pixel output. Again, modern GPUs (really, most GPUs in the past decade) can support more than just triangles. These more exotic techniques don't get as much attention, since most graphics assets are still implemented with triangle meshes.


GPUs can take in way more than just triangles as input. There are particle simulation and even Ray tracing implemented on GPUs nowadays. Support for parametric curves was one of the more recent additions.


That's a very... naive view of how a GPU works. Particle simulation is done in compute, and ray tracing, as implemented in RTX/DXR, is done on a soup of triangles. The core of rasterization is still done on triangles, and can't easily be done in compute. Have any references to parametric curves on GPUs? All the approaches I know of, like the recent mesh shader work, still output triangle meshes.


This is from 2007: https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-...

Again, the vast majority of use cases for GPUs is 3d vertex graphics. But they're capable of more than that. Modern GPUs are very different from early GPUs that only worked with triangles. Some of the early ones were actually ASICs, and couldn't even load different shader programs.


"In compute" just means that there aren't inputs and outputs related to the current output frame in the calculation job - the computational possibilities are the same.

Triangles aren't necessarily involved in in rendering either, see eg how the stuff on shadertoy.com works.


GPU aren't based on anything. They are turing complete, you can run Linux on it if you wanted to.

What you are saying is outdated by maybe a couple of decades.


A Turing Machine is turing-complete, but it would be inefficient to run Linux on it. We're not talking about raw computability here, but feasibility. And still, I am not aware of anything "running Linux on a GPU", their scheduling engines are not designed for those sorts of workloads.


The first triangle is still in 3d space but the z coordinates are set to 0


Or you can just not define a z coordinate in the vertex buffer object (at least, in opengl). I think the vertex shader might still need to output a 3rd coordinate. But you can always just discard it.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: