Siavash wrote:
Is it possible to use your changes in engine to create a GUI lib? IMHO it's great to have a GUI lib based on shaders to accelerate heavy 2d scenes and adding support for png/mng anims ! Could you explain it a bit more ? It's too interesting for me
You could use the ideas from my shaders to create a
GUI renderer, yes.
These shaders do not use texture data, instead they just use mathematical descriptions of shapes within the fragment shader.
For example, a circle can be expressed mathematically as:
Code:
x^2 + y^2 = radius^2
These variables (x,y and radius) are given to the shader via 2 uniform variables:
Code:
uniform vec4 radius;// vec4(r, 0,0,0);
uniform vec4 offset;// vec4(x, y, 0,0);
The shader utilizes "texCoord" to determine the location of the pixel currently being rendered.
First, the shader measures the distance from the current pixel to the center of the circle:
Code:
distance( texCoord, offset.xy )
If this distance is less than the radius, then this pixel is inside the circle. Otherwise, the pixel is outside the circle.
To make the shaders easier to write, this distance is transformed into a standard distance-field representation.
Code:
float d = distance( texCoord, offset.xy ) - radius.x;
Now, the variable
d tells us the distance to the
edge of the circle (instead of the distance to the center).
If the distance is less than 0, the current pixel is inside the shape. If it is greater than 0, this pixel is outside the shape.
You can get anti-aliased smooth edges with the smoothstep function:
Code:
float alpha = 1.0-smoothstep( -half_pixel_size, half_pixel_size, distance_field );
gl_FragColor = vec4(color,alpha);
Distance fields can be combined using min and max.
One shape can be subtracted from another with: C = max( A, -1*B )
One shape can be added to another with: C = min( A, B )
E.g. you can cut one circle out of another to make a doughnut:
Code:
float circle_big = distance( texCoord, offset.xy ) - 0.5;
float circle_small = distance( texCoord, offset.xy ) - 0.125;
float doughnut = max( circle_big, -1.0*circle_small );