Attract-Mode Support Forum
Attract-Mode Support => Scripting => Topic started by: keilmillerjr on April 03, 2017, 05:08:03 PM
-
Is it possible to pass an image to a shader and create rounded (smooth) corners with transparency? Similar to how border-radius with css works. I have no knowledge at all about how shaders work.
-
I wrote a little demo for you which adds antialiased rounded corners without using a masking texture. It's aspect ratio agnostic. Have fun with it.
layout.nut
local flw = fe.layout.width
local flh = fe.layout.height
local snap_width = 500
local snap_height = 500
local radius = 0
local snap = fe.add_artwork( "snap", 0, 0, snap_width, snap_height )
snap.x = flw / 2
snap.y = flh / 2
snap.origin_x = snap.width / 2
snap.origin_y = snap.height / 2
snap.preserve_aspect_ratio = true
local snap_shader = fe.add_shader( Shader.Fragment, "shader.frag" );
snap.shader = snap_shader
fe.add_ticks_callback( "tick" )
function tick( tick_time ) {
radius += 2
if( radius > 100 ) radius -= 200
snap_shader.set_param( "radius" , radius)
snap_shader.set_param( "snap_dimensions" , snap.width, snap.height)
if ( snap.preserve_aspect_ratio) snap_shader.set_param( "subimg_dimensions" , snap.subimg_width, snap.subimg_height)
else snap_shader.set_param( "subimg_dimensions" , snap.width, snap.height)
}
shader.frag
uniform sampler2D texture;
uniform float radius;
uniform vec2 snap_dimensions;
uniform vec2 subimg_dimensions;
vec2 dimensions;
float roundCorners(vec2 p, vec2 b, float r)
{
return length(max(abs(p)-b+r,0.0))-r;
}
void main()
{
if (subimg_dimensions.x <= subimg_dimensions.y)
{
dimensions.x = snap_dimensions.x * subimg_dimensions.x / subimg_dimensions.y;
dimensions.y = snap_dimensions.y;
}
else
{
dimensions.x = snap_dimensions.x;
dimensions.y = snap_dimensions.y * subimg_dimensions.y / subimg_dimensions.x;
}
vec2 halfRes = 0.5 * dimensions;
float b = 1.0 - roundCorners(gl_TexCoord[0].xy * dimensions - halfRes, halfRes, abs(radius));
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
gl_FragColor = vec4(gl_Color.xyz * pixel, smoothstep(0.0,1.0,b));
}
-
A huge thank you to Oomek for making this shader, and working with me to resolve a bug using it on my mac. :D
The bug fix was changing the following from/to:
gl_FragColor = vec4(gl_Color.xyz * pixel, smoothstep(0.0,1.0,b));
gl_FragColor = vec4(gl_Color.xyz * pixel.xyz, smoothstep(0.0,1.0,b));
I added his shader to my shader module with his permission. It might make it a little easier to use it, and being a module means that it can be shared between multiple layouts. You can find it here: https://github.com/keilmillerjr/shader-module
If anyone is using any of my modules or plugins I have been creating lately, please let me know. Feedback would be appreciated, and I will take precaution not to break anything and add version tags on github if changes will cause incompatibility - if people other than myself are using them.
-
I wrote a little demo for you which adds antialiased rounded corners without using a masking texture. It's aspect ratio agnostic. Have fun with it.
layout.nut
local flw = fe.layout.width
local flh = fe.layout.height
local snap_width = 500
local snap_height = 500
local radius = 0
local snap = fe.add_artwork( "snap", 0, 0, snap_width, snap_height )
snap.x = flw / 2
snap.y = flh / 2
snap.origin_x = snap.width / 2
snap.origin_y = snap.height / 2
snap.preserve_aspect_ratio = true
local snap_shader = fe.add_shader( Shader.Fragment, "shader.frag" );
snap.shader = snap_shader
fe.add_ticks_callback( "tick" )
function tick( tick_time ) {
radius += 2
if( radius > 100 ) radius -= 200
snap_shader.set_param( "radius" , radius)
snap_shader.set_param( "snap_dimensions" , snap.width, snap.height)
if ( snap.preserve_aspect_ratio) snap_shader.set_param( "subimg_dimensions" , snap.subimg_width, snap.subimg_height)
else snap_shader.set_param( "subimg_dimensions" , snap.width, snap.height)
}
shader.frag
uniform sampler2D texture;
uniform float radius;
uniform vec2 snap_dimensions;
uniform vec2 subimg_dimensions;
vec2 dimensions;
float roundCorners(vec2 p, vec2 b, float r)
{
return length(max(abs(p)-b+r,0.0))-r;
}
void main()
{
if (subimg_dimensions.x <= subimg_dimensions.y)
{
dimensions.x = snap_dimensions.x * subimg_dimensions.x / subimg_dimensions.y;
dimensions.y = snap_dimensions.y;
}
else
{
dimensions.x = snap_dimensions.x;
dimensions.y = snap_dimensions.y * subimg_dimensions.y / subimg_dimensions.x;
}
vec2 halfRes = 0.5 * dimensions;
float b = 1.0 - roundCorners(gl_TexCoord[0].xy * dimensions - halfRes, halfRes, abs(radius));
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
gl_FragColor = vec4(gl_Color.xyz * pixel, smoothstep(0.0,1.0,b));
}
Your shader is awesome, exactly what I was looking for. Thank a lot!
-
very great! thanks alot!
oomek! do u also have a drop shadow with blur shader? seems u use this in your new preview theme :)
best greets
-
im not getting round corners.... >:(
not 100% hip to shaders....here is the code using your new module..
and what i get.
local flx = fe.layout.width;
local fly = fe.layout.height;
local flw = fe.layout.width;
local flh = fe.layout.height
// Create Artwork Variable
local snap = fe.add_artwork("snap", 0, 0, 640, 480);
// Load Shader Module
if (fe.load_module("shader")) {
// CrtLottes
local snapShader = CrtLottes();
// RoundCorners
if (snap.preserve_aspect_ratio) RoundCorners(100, snap.width, snap.height);
else RoundCorners(100, snap.width, snap.height, snap.subimg_width, snap.subimg_height);
// Apply the shader to your object
snap.shader = snapShader.shader;
}
(http://i67.tinypic.com/d4ldg.png)
ohh by the way thats a sad face not a mad face....
-
very great! thanks alot!
oomek! do u also have a drop shadow with blur shader? seems u use this in your new preview theme :)
best greets
No, it's just a png behind the snaps, but I'm thinking about making it in the shader. The principle is the same as for the blur.
-
im not getting round corners.... >:(
not 100% hip to shaders....here is the code using your new module..
and what i get.
You cannot add 2 shaders to one object unfortunately. You would need to combine them, or apply a second shader to a surface on which you have drawn the first object with the scanlines.