I am trying to create a vector rendering library for OpenGL in Rust. Currently, the goal is to produce nanovg-like rendering. I have found two approaches to doing my rendering:
- The pure shader approach, where I just render a single fullscreen quad in OpenGL, and use shaders draw all my vector shapes
- The pure geometry approach, where I create a canvas, add all my shapes, triangulate the vertices on CPU, then upload the vertices to GPU and render with a basic vertex and fragment shader
For instance, using the pure shader approach, I would potentially use some GLSL code that looks like this:
uniform vec2 u_resolution;
vec3 circle(vec2 uv, vec2 center, float radius, vec3 color) {
float x = sqrt(pow(uv.x - center.x, 2.) + pow(uv.y - center.y, 2.));
if (x < radius) {
return color;
} else {
return vec3(1., 1., 1.);
}
}
vec3 rectangle(vec2 uv, vec2 p1, vec2 p2, vec3 color)
{
if (uv.x > p1.x && uv.x < p2.x && uv.y > p1.y && uv.y < p2.y)
{
return color;
} else {
return vec3(1.0, 1.0, 1.0);
}
}
void main() {
vec2 uv = gl_FragCoord.xy/u_resolution.xy;
vec3 color1 = circle(uv, vec2(0.3, 0.5), 0.2, vec3(1.0, 0.0, 1.0));
vec3 color2 = rectangle(uv, vec2(0.3, 0.2), vec2(0.7, 0.5), vec3(0.5, 0.2, 1.0));
vec3 color = mix(color1, color2, color1);
gl_FragColor = vec4(color,1.0);
}
whereas with the pure geometry approach, I would use some code that looks like this:
fn main() {
let canvas = Canvas::new();
canvas.addCircle(0.1, 0.2, 0.3);
canvas.addRect(0.5, 0.2, 4.0, 5.0);
let vertices = triangulate(canvas.to_vertices());
// Some general OpenGL code to render some vertices etc.
}
However, both approaches seem to have issues - the pure shader approach is very difficult to add a large number of shapes, and the pure geometry approach is hard to get working and possibly not as efficient. Does anyone have any suggestions for an alternate approach?