Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - zpaolo11x

Pages: [1] 2
1
Scripting / GLSL colorizer and color conversion routines
« on: October 09, 2018, 07:46:44 AM »
I jsut developed a small shader for colorizing, it uses HSL color space which looks much better than HSV. But in the code you can find some useful color conversion functions that you can use for many purposes like desaturation, hue rotation etc.

The shader requires an HSL vector of three values that are used for colorizing, plus a texture mix value if you want to blend (in RGB) the colorized with the default image.

Code: [Select]
uniform sampler2D texture;
uniform vec3 hsl;
uniform float texmix;

vec3 hsl2rgb( in vec3 c )
{
    vec3 rgb = clamp( abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0, 0.0, 1.0 );
    return c.z + c.y * (rgb-0.5)*(1.0-abs(2.0*c.z-1.0));
}

vec3 rgb2hsl( in vec3 c ){
  float h = 0.0;
float s = 0.0;
float l = 0.0;
float r = c.r;
float g = c.g;
float b = c.b;
float cMin = min( r, min( g, b ) );
float cMax = max( r, max( g, b ) );

l = ( cMax + cMin ) / 2.0;
if ( cMax > cMin ) {
float cDelta = cMax - cMin;
       
        //s = l < .05 ? cDelta / ( cMax + cMin ) : cDelta / ( 2.0 - ( cMax + cMin ) ); Original
s = l < .0 ? cDelta / ( cMax + cMin ) : cDelta / ( 2.0 - ( cMax + cMin ) );
       
if ( r == cMax ) {
h = ( g - b ) / cDelta;
} else if ( g == cMax ) {
h = 2.0 + ( b - r ) / cDelta;
} else {
h = 4.0 + ( r - g ) / cDelta;
}

if ( h < 0.0) {
h += 6.0;
}
h = h / 6.0;
}
return vec3( h, s, l );
}


vec3 rgb2hsv(vec3 c)
{
    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

    float d = q.x - min(q.w, q.y);
    float e = 1.0e-10;
    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

vec3 hsv2rgb(vec3 c)
{
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

void main()
{   

vec2 uv = gl_TexCoord[0].xy;

vec4 t0 = texture2D(texture, uv);
vec3 hsl0 = rgb2hsl (t0.rgb);

vec3 hsl1 = vec3(hsl.x,hsl.y,hsl0.z);

vec3 tch = hsl2rgb (hsl1);


gl_FragColor = vec4(mix(hsl.z*tch.xyz,t0.xyz,texmix) , gl_Color.a*t0.a);

}

This is a sample layout

Code: [Select]
local pic1 = fe.add_artwork("snap",0,0,400,400)
pic1.video_flags = Vid.ImagesOnly
pic1.preserve_aspect_ratio = false

local pic2 = fe.add_artwork("snap",400,0,400,400)
pic2.video_flags = Vid.ImagesOnly
pic2.preserve_aspect_ratio = false

local pic3 = fe.add_artwork("snap",800,0,400,400)
pic3.video_flags = Vid.ImagesOnly
pic3.preserve_aspect_ratio = false

local colorshader1 = fe.add_shader(Shader.Fragment,"colorizer.glsl")
colorshader1.set_texture_param("texture")
colorshader1.set_param("hsl",0.6,0.5,1.0)
colorshader1.set_param("texmix",0.0)
pic1.shader = colorshader1

local colorshader2 = fe.add_shader(Shader.Fragment,"colorizer.glsl")
colorshader2.set_texture_param("texture")
colorshader2.set_param("hsl",0.6,1.0,1.0)
colorshader2.set_param("texmix",0.0)
pic2.shader = colorshader2



2
Scripting / GLSL gaussian blur without nested surfaces
« on: October 08, 2018, 02:19:10 AM »
Inspired by Oomek work with feedback trails, I put together a quick and dirty layout for gaussian blur using a similar trick without need for nested surfaces.

What do you think? It scales down the initial surface so it can work on a lower resolution instance of the picture, but has issues if you turn on aspect ratio (you should then pass the actual resolution to the shader using subimg.x and subimg.y).

Code:

Code: [Select]

local picwidth = 64.0
local su0 = fe.add_surface(picwidth,picwidth)
local su1 = fe.add_surface(picwidth,picwidth)

local pic = su0.add_artwork("snap",0,0,picwidth,picwidth)
pic.video_flags = Vid.ImagesOnly
pic.preserve_aspect_ratio = false

local sh0 = fe.add_shader( Shader.Fragment, "gauss_kernsigma_o2.glsl" )
local sh1 = fe.add_shader( Shader.Fragment, "gauss_kernsigma_o2.glsl" )

pic = su0.add_clone (pic)
sh0.set_texture_param( "texture",pic)
sh0.set_param("kernelData", 21.0, 3.0)
sh0.set_param("offsetFactor", 1.0/picwidth, 0.0)
sh0.set_param("reverse",1.0)
pic.shader = sh0

pic = su1.add_clone (pic)
sh1.set_texture_param( "texture",su0)
sh1.set_param("kernelData", 21.0, 3.0)
sh1.set_param("offsetFactor", 0.0, 1.0/picwidth)
sh1.set_param("reverse",0.0)
pic.shader = sh1

su0.visible = false
su1.set_pos (0,0,600,600)


shader:

Code: [Select]

uniform sampler2D texture;
uniform vec2 kernelData;
uniform vec2 offsetFactor;
uniform float reverse;

void main() {

    vec3 incrementalGaussian;
    incrementalGaussian.x = 1.0 / (sqrt(2.0 * 3.14) * kernelData.y);
    incrementalGaussian.y = exp(-0.5 / (kernelData.y * kernelData.y));
    incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;

    vec2 uv = gl_TexCoord[0].xy;
    if (reverse == 1.0) {
       uv.y = 1.0 - uv.y;
    }
    vec4 color = vec4(0.0);
    float kersum = 0.0;

    color += texture2D(texture, uv) * incrementalGaussian.x;
    kersum += incrementalGaussian.x;
    incrementalGaussian.xy *= incrementalGaussian.yz;


    for (float i = 1.0 ; i <=   (kernelData.x - 1.0)*0.5 ; i++) {
        color += texture2D(texture, uv - i * offsetFactor ) * incrementalGaussian.x;         
        color += texture2D(texture, uv + i * offsetFactor ) * incrementalGaussian.x;         
        kersum += 2.0 * incrementalGaussian.x;
        incrementalGaussian.xy *= incrementalGaussian.yz;
    }
   
    gl_FragColor = color/kersum;
}


3
Scripting / Frosted glass menu background
« on: October 01, 2018, 01:30:23 AM »
I've worked a bit on this, and it seems I'm very close to have something working, you can see from the screenshots that I managed to make it work both on standard menus (like exit menu called with "esc" button, or filters menu) and on "custom" menus. I jsut need some other trickery to prevent the effect to be "doubled" if you call a standard menu from a custom menu :D

There are still some issues, but most of all I can't find a way to delete the screenshot I generate every time I need to update the background. Any suggestion?



4
Scripting / Screenshots and how to check if a file exists
« on: September 18, 2018, 01:06:20 AM »
I want to do this: take a screenshot of AM and then load it as an image file.
I can easily write a routine that scans through the AM folder and selects the last screenshot pathname. My idea was to do something like, in a on_signal routine:

generate the screenshot through signal("screenshot")
run through the folder and get the filename
add the filename to the image

The issue is that, as far as I can see, it takes some time to create the screenshot so the routine finds the previous one. Is there a way to wait until the intended file is created?

5
Scripting / OpenGL versions and Attract Mode
« on: September 14, 2018, 08:37:01 AM »
I'm on a Mac, which of course is a PITA for emulation but I don't want to use Parallels anymore for this :D

My question (maybe a stupid question) is how is OpenGL support implemented in Attract Mode for Mac? I ask this because technically Mac OS supports OpenGL up to a certain level, but for example XQuartz (the X11 display server for Mac OS) only support certain versions of OpenGL, and to add insult to injury in the future Apple is going to deprecate OpenGL in favor of its own Metal framework. I'm not an expert or a programmer, but I'm wondering what would happen of laouts using GLSL filters if Apple removes OpenGL support altogether, and how can I tell what version of GLSL I can use with my setup? Is AttractMode for Mac running on XQuartz?

6
Scripting / Nested surfaces and speed of update
« on: September 03, 2018, 08:40:23 AM »
I built a simple layout with some examples of nested surfaces. If I run it on my PC I get 60 fps with case 1 (just a single surface), 30 fps with case 2 (two nested surfaces) and about 15 to 20 fps with case 3 (three nested surfaces). You can change the level of "nestyness" in the layout option, I'd like to know how it performs on other machines.

In the past I used some tricks to speed up scrolling in this situations (adding and updating a text item for example) but now I really want to know what is happening and how to speed things up.

Hope someone can help!

7
Scripting / GLSL shader: how to "downsample" an image?
« on: September 03, 2018, 12:31:46 AM »
Some filters (like blur filters ;) ) work best with a reduced texture size, for example a gaussian blur on a 128x128 pixel image can be smoother with few semples, while the same gaussian blur on a 512 x 512 pixel image requires a lot of samples. In AM I use this trick of adding the 512x512 image on a 128x128 surface, then apply the shader on the surface and rescale it to the desired size.

I'm quite sure that there's a way to write a GLSL shader (vertex?) that downsamples the image before rasterizing it, but I cant' find it, except the use of mipmaps that is so good but doesn't work on my mac :D

Any idea?

8
Scripting / Shader for sharper pixel upscaler
« on: August 29, 2018, 11:59:46 PM »
I found this site with a neat GLSL fragment shader http://www.iquilezles.org/www/articles/texture/texture.htm : it implements a way to enlarge a low resolution, high contrast image obtaining better pixels definition.

It's very clever: when a low resolution image is rendered you usually get linear interpolation between the color values, which looks pretty bad in high contrast pictures (star shaped artifacts). This filter alters the texture coordinate that you are sampling so to reduce and smooth the transition between the color samples. You can apply it to your image using the code below where "texture" is the image, and "resol" is a vector of the picture pixel size (width , height).

To give you an idea I attach a sample with bilinear filtered image on the left, shader filtered image in the middle and original high resolution image on the right (the effect is more visible on low res images so I downsampled the image before)

Code: [Select]
uniform sampler2D texture;
uniform vec2 resol;

void main()
{   

    vec2 uv = gl_TexCoord[0].xy;

    uv = uv*resol + 0.5;

    vec2 i = floor(uv);
    vec2 f = uv - i;
    f = f*f*f*(f*(f*6.0-15.0)+10.0);
    uv = i + f;
    uv = (uv - 0.5)/resol;

    gl_FragColor = texture2D(texture, uv);

}

By editing the f = f*f*f*(f*(f*6.0-15.0)+10.0); part you can have a sharper effect or a different transition shape.

9
Scripting / Framerate counter
« on: August 25, 2018, 02:13:23 AM »
There's probably a better way to see if a theme is smooth or not, but this small code allowed me to track the performance of my theme while adding lots and lots of shaders...

Code: [Select]

local monitor = fe.add_text ("",0,0,fe.layout.width,100)
monitor.align = Align.Centre
monitor.set_bg_rgb (255,0,0)
monitor.charsize = 50

local monitor2 = fe.add_text ("",0,0,1,1)
local monitor_tick0 = 0
local monitor_x0 = 0

fe.add_ticks_callback(this,"monitortick")

function monitortick(tick_time){
monitor2.x ++
if (monitor2.x - monitor_x0 == 10) {
monitor.msg = 10000/(tick_time - monitor_tick0)
monitor_tick0 = tick_time
monitor_x0 = monitor2.x
}

if (monitor2.x >= flw) {
monitor2.x = 0
monitor_x0 = 0
monitor_tick0=0
}
}


You can add it at the end of your layout, it will create a red banner on the top with a number reporting the current frame rate. It works like this: every tick_callback it moves a text object by one pixel, once the object has moved 10 pixels it calculates the time taken. Ideally if you are on a 60Hz screen you should get a pixel movement every 1/60 of a second and on this basis the framerate is calculated and displayed.

10
Scripting / mipmap = 1 is a game changer!
« on: August 24, 2018, 01:37:40 AM »
Not only mipmap = 1 improves dramatically the scaling of pictures, but when a GLSL fragment shader is applied to an image with mipmap enabled the fragment shader can sample the desired mipmap level! This is a godsend for smoothnig and blurring filters, and also for averaging and in all those cases where it's better to work with a lower resolution image that is then upscaled. Definitely very cool!

The only issue is what happens on AM 2.3? Is it time to ditch the old good guy and develop only for AM 2.4+? Also, there's probably a way to pass mipmaps to the fragment shader through a vertex shader, but I'm not good enough at GLSL ;D

11
Scripting / GLSL how to pass an array via set_param
« on: August 20, 2018, 06:38:39 AM »
Is it possible to pass an array of float values with a single "set_param" command? I know I can send a 2D, 3D or 4D vector, but what if I need to send an array of, say, 13 floats? Is it possible?

12
Scripting / Vertex shader...
« on: August 15, 2018, 09:17:45 AM »
I found this code for a vertex shader, it should be a blur shader AFAIK but there's no example layout so I'm lost at how to call it. Anyone has a clue?

Code: [Select]
/* VBlurVertexShader.glsl */
attribute vec4 a_position;
attribute vec2 a_texCoord;
 
varying vec2 v_texCoord;
varying vec2 v_blurTexCoords[14];
 
void main()
{
    gl_Position = a_position;
    v_texCoord = a_texCoord;
    v_blurTexCoords[ 0] = v_texCoord + vec2(0.0, -0.028);
    v_blurTexCoords[ 1] = v_texCoord + vec2(0.0, -0.024);
    v_blurTexCoords[ 2] = v_texCoord + vec2(0.0, -0.020);
    v_blurTexCoords[ 3] = v_texCoord + vec2(0.0, -0.016);
    v_blurTexCoords[ 4] = v_texCoord + vec2(0.0, -0.012);
    v_blurTexCoords[ 5] = v_texCoord + vec2(0.0, -0.008);
    v_blurTexCoords[ 6] = v_texCoord + vec2(0.0, -0.004);
    v_blurTexCoords[ 7] = v_texCoord + vec2(0.0,  0.004);
    v_blurTexCoords[ 8] = v_texCoord + vec2(0.0,  0.008);
    v_blurTexCoords[ 9] = v_texCoord + vec2(0.0,  0.012);
    v_blurTexCoords[10] = v_texCoord + vec2(0.0,  0.016);
    v_blurTexCoords[11] = v_texCoord + vec2(0.0,  0.020);
    v_blurTexCoords[12] = v_texCoord + vec2(0.0,  0.024);
    v_blurTexCoords[13] = v_texCoord + vec2(0.0,  0.028);
}

13
General / Possible new feature: add alpha channel to images
« on: July 25, 2018, 11:35:09 PM »
I know you can use PNG with transparency, but what I'd love to see in AM is the possibility to create a fe.image object and add an alpha channel to it from a different source image. Like for example

local snapshot = fe,add_artwork ("snap",0,0,200,200)
snapshot.alpha_channel = "faded_borders.png"

so that the transparency of the snapshots is inherited from the "faded_borders.png" greyscale image.

That would open so many neat opportunities for themes.

14
Scripting / Arcade cabinet picture for missing artwork...
« on: July 05, 2018, 07:29:16 AM »
In my theme I use the "wheel" artwork to add game titles, but when a game doesn't have a proper png title file I get a small "arcade cabinet" icon instead. Is this happening only for the "wheel" artwork, and is there a workaround for that?

15
Scripting / Search string for mutiple fields
« on: June 19, 2018, 02:07:56 AM »
Is it possible to craft a search string for fe.overlay.search_string that looks into more fields at the same time?

Right now the syntax I know is something like "Field contains regexp" where "Field" can be Title, Year, Manufacturer etc, while regexp is the text to find (but also allows some regexp tricks like [] to insert multiple letters etc). I don't know if it's possible to apply a search string that looks in title or manufacturer or year or category. Something like "Title contains regexp || Manufacturer contains regexp" etc

Is it even possible?

The way I would use it is not to create refined searches but just to look for the same user-input text in ALL meaningful fields. So that if I put 198 in search I'll end with all the games done in the 80's, or if I put Toaplan I get all the games made by toaplan, without having to chose beforehand what field to apply the search.

Pages: [1] 2