I'm looking for help with a little code/shader for an arcade project

  • O.T.T.
  • Topic Author
More
8 months 3 weeks ago - 8 months 3 weeks ago #1 by O.T.T. I'm looking for help with a little code/shader for an arcade project was created by O.T.T.
Hi everyone, I'm new to the forum and would like to ask the experts for help.

A brief introduction: I came across ReShade by chance, in my search for a solution to some problems I have while developing my arcade project. It is based on RetroArch and I need to associate some features (shaders) with hotkeys, which RetroArch does not allow or severely limits.

From what I have been able to observe/understand so far, ReShade seems to be the perfect solution to my needs, since it offers powerful shaders without the need of messing with tons of menu and sub-menu & settings just to activate one, has a very simple and straightforward user-interface and anything can be associated to hotkeys!!!

For my project I need:

1) being able to flip the image horizontally
2) being able to flip the image vertically
3) apply a "cocktail" visual to the image
4) scale the image to the size of a user-defined area (Horizontal & Vertical limits expressed in pixels, the scaled image should be centered)

Those who know RetroArch know that all these functions are available from internal menus or by applying shaders, however cannot be associated with hotkeys or you cannot activate more than one shader without chaining them - which is bad in every respect as far as I'm concerned.

Going back to the points in the list, I solved #1 & #2 thanks to the brilliant code provided by Marty McFly - whom I sincerely thank - found in a post on this forum from almost 7 years ago!

For point #3, there is a shader in RetroArch that is perfect, you can find it in "shaders_glsl/misc/cocktail-cab-portrait.glsl" (I can post the whole code here, if needed). Looking at Marty McFly's code, I could see that it is very similar to the code used in RetroArch shaders for the same functions, so my guess is that you can take RA's "cocktail" shader code and "transform" it into .fx code - that ReShade can use - without much effort. This is just my hypothesis, I don't understand anything about shaders and how to program them...so that's why I need your help 

For point #4, again it's about converting/re-proposing a RetroArch functionality accessible only from the internal menu: even in this case I think it shouldn't be too difficult for one of you experts

If there is anyone among you who has the patience and would be kind enough to develop a little code/shader for points 3&4 I would be infinitely grateful!!!

Many thanks in advance for the attention.
Last edit: 8 months 3 weeks ago by O.T.T..

Please Log in or Create an account to join the conversation.

  • O.T.T.
  • Topic Author
More
8 months 2 weeks ago - 8 months 2 weeks ago #2 by O.T.T. Replied by O.T.T. on topic I'm looking for help with a little code/shader for an arcade project
To make things easier and give an idea of what I'm asking for, below is the code of the "cocktail" shader for RetroArch which I would like to port to .fx format for ReShade.

I think that the goal can be achieved with a few minimal changes: please help!


#pragma parameter width "Cocktail Width" 1.0 0.0 2.0 0.01
#pragma parameter height "Cocktail Height" 0.49 0.0 2.0 0.01
#pragma parameter x_loc "Cocktail X Mod" 0.0 -2.0 2.0 0.01
#pragma parameter y_loc "Cocktail Y Mod" 0.51 -2.0 2.0 0.01
// important for hw-rendered cores
#pragma parameter flip_y "Flip Vertical Axis" 0.0 0.0 1.0 1.0

#if defined(VERTEX)

#if __VERSION__ >= 130
#define COMPAT_VARYING out
#define COMPAT_ATTRIBUTE in
#define COMPAT_TEXTURE texture
#else
#define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#endif

#ifdef GL_ES
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif

COMPAT_ATTRIBUTE vec4 VertexCoord;
COMPAT_ATTRIBUTE vec4 COLOR;
COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 COL0;
COMPAT_VARYING vec4 TEX0;
COMPAT_VARYING vec2 t1;

vec4 _oPosition1;
uniform mat4 MVPMatrix;
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;

// compatibility #defines
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float width, height, x_loc, y_loc, flip_y;
#else
#define width 1.0
#define height 0.49
#define x_loc 0.0
#define y_loc 0.51
#define flip_y 0.0
#endif

void main()
{
gl_Position = MVPMatrix * VertexCoord;
TEX0.xy = TexCoord.xy;
TEX0.xy = TEX0.xy - 0.5 * InputSize / TextureSize;
TEX0.xy = TEX0.xy * vec2(1. / width, 1. / height);
TEX0.xy = TEX0.xy + 0.5 * InputSize / TextureSize;
t1.xy = 1.* InputSize / TextureSize - TEX0.xy;
TEX0.xy -= vec2(x_loc, y_loc) * InputSize / TextureSize;
t1.xy -= vec2(x_loc, y_loc) * InputSize / TextureSize;
if(flip_y > 0.5)
{
// have to compensate for the slightly reduced height and y_loc values
TEX0.y += 1.025* InputSize.y / TextureSize.y;
t1.y += 1.025* InputSize.y / TextureSize.y;
}
}

#elif defined(FRAGMENT)

#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif

#if __VERSION__ >= 130
#define COMPAT_VARYING in
#define COMPAT_TEXTURE texture
out COMPAT_PRECISION vec4 FragColor;
#else
#define COMPAT_VARYING varying
#define FragColor gl_FragColor
#define COMPAT_TEXTURE texture2D
#endif

uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0;
COMPAT_VARYING vec2 t1;

// compatibility #defines
#define Source Texture
#define vTexCoord TEX0.xy

#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

void main()
{
vec4 screen1 = COMPAT_TEXTURE(Source, vTexCoord);
screen1 *= float(vTexCoord.x > 0.0001) * float(vTexCoord.y > 0.0001) * float(vTexCoord.x < 0.9999) * float(vTexCoord.y < 0.9999);
vec4 screen2 = COMPAT_TEXTURE(Source, t1);
screen2 *= float(t1.x > 0.0001) * float(t1.y > 0.0001) * float(t1.x < 0.9999) * float(t1.y < 0.9999);
FragColor = screen1 + screen2;
}
#endif
Last edit: 8 months 2 weeks ago by O.T.T..

Please Log in or Create an account to join the conversation.

  • crosire
More
8 months 2 weeks ago #3 by crosire Replied by crosire on topic I'm looking for help with a little code/shader for an arcade project
There you go:
// Cocktail Table Portrait
// by hunterk
// license: public domain
 
uniform float width < ui_name = "Cocktail Width"; ui_type = "slider"; ui_min = 0.0; ui_max = 2.0; ui_step = 0.01; > = 1.0;
uniform float height < ui_name = "Cocktail Height"; ui_type = "slider"; ui_min = 0.0; ui_max = 2.0; ui_step = 0.01; > = 0.49;
uniform float x_loc < ui_name = "Cocktail X Mod"; ui_type = "slider"; ui_min = -2.0; ui_max = 2.0; ui_step = 0.01; > = 0.0;
uniform float y_loc < ui_name = "Cocktail Y Mod"; ui_type = "slider"; ui_min = -2.0; ui_max = 2.0; ui_step = 0.01; > = 0.51;
// important for hw-rendered cores
uniform bool flip_y < ui_name = "Flip Vertical Axis"; > = false;
 
uniform texture2D BackBufferTex : COLOR;
uniform sampler2D BackBuffer { Texture = BackBufferTex; };

#define InputSize float2(BUFFER_WIDTH, BUFFER_HEIGHT)
#define OutputSize InputSize
#define TextureSize InputSize

// compatibility #defines
#define Source BackBuffer
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

void vertex(in uint id : SV_VERTEXID, out float4 gl_Position : SV_POSITION, out float2 TEX0 : TEXCOORD0, out float2 t1 : TEXCOORD1)
{
	float2 TexCoord;
	TexCoord.x = (id == 2) ? 2.0 : 0.0;
	TexCoord.y = (id == 1) ? 2.0 : 0.0;
	gl_Position = float4(TexCoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);

	TEX0.xy = TexCoord.xy;
	TEX0.xy = TEX0.xy - 0.5 * InputSize / TextureSize;
	TEX0.xy = TEX0.xy * float2(1. / width, 1. / height);
	TEX0.xy = TEX0.xy + 0.5 * InputSize / TextureSize;
	t1.xy = 1.* InputSize / TextureSize - TEX0.xy;
	TEX0.xy -= float2(x_loc, y_loc) * InputSize / TextureSize;
	t1.xy -= float2(x_loc, y_loc) * InputSize / TextureSize;
	if(flip_y > 0.5)
	{
		// have to compensate for the slightly reduced height and y_loc values
		TEX0.y += 1.025* InputSize.y / TextureSize.y;
		t1.y += 1.025* InputSize.y / TextureSize.y;
	}
}
  
void fragment(in float4 vpos : SV_POSITION, in float2 TEX0 : TEXCOORD0, in float2 t1 : TEXCOORD1, out float4 FragColor : SV_TARGET)
{
	float4 screen1 = tex2D(Source, vTexCoord);
	screen1 *= float(vTexCoord.x > 0.0001) * float(vTexCoord.y > 0.0001) * float(vTexCoord.x < 0.9999) * float(vTexCoord.y < 0.9999);
	float4 screen2 = tex2D(Source, t1);
	screen2 *= float(t1.x > 0.0001) * float(t1.y > 0.0001) * float(t1.x < 0.9999) * float(t1.y < 0.9999);
	FragColor = screen1 + screen2;
}

technique Cocktail
{
    pass
    {
        VertexShader = vertex;
        PixelShader = fragment;
    }
}
The following user(s) said Thank You: O.T.T.

Please Log in or Create an account to join the conversation.

  • O.T.T.
  • Topic Author
More
8 months 2 weeks ago - 8 months 2 weeks ago #4 by O.T.T. Replied by O.T.T. on topic I'm looking for help with a little code/shader for an arcade project
It works like a charm! Thank you so much crosire!!!
I ❤️ you! 

About  the last point (#4), i.e. "scale the image to the size of a user-defined area (Horizontal & Vertical limits expressed in pixels, the scaled image should be centered)" unfortunately I don't have any code/shader as reference because it is a function integrated into RetroArch accessible only from the internal menu. It's the last obstacle for my project - at least concerning the image output  : are you able to help me in this case too?

Your software is fantastic, it may have solved a series of problems that have been hindering my project development for a long time: if you tell me how to do it, I can make a small donation (I'm not rich    ) in recognition of your work and as a thank you.
Last edit: 8 months 2 weeks ago by O.T.T..

Please Log in or Create an account to join the conversation.

  • crosire
More
8 months 2 weeks ago #5 by crosire Replied by crosire on topic I'm looking for help with a little code/shader for an arcade project
github.com/papadanku/CShade/blob/main/shaders/cTransform.fx does what you want I think (scale is expressed in multiples, but that's not hard to convert from pixel counts). Can just install it by selecting the CShade effect package in the ReShade setup tool.

I have a Patreon linked on the home page, but there's no need to worry about donating, I'm not doing this for money, so if money is needed elsewhere, please rather use it there.
The following user(s) said Thank You: O.T.T.

Please Log in or Create an account to join the conversation.

  • O.T.T.
  • Topic Author
More
8 months 2 weeks ago #6 by O.T.T. Replied by O.T.T. on topic I'm looking for help with a little code/shader for an arcade project

github.com/papadanku/CShade/blob/main/shaders/cTransform.fx does what you want I think (scale is expressed in multiples, but that's not hard to convert from pixel counts). Can just install it by selecting the CShade effect package in the ReShade setup tool.

I have a Patreon linked on the home page, but there's no need to worry about donating, I'm not doing this for money, so if money is needed elsewhere, please rather use it there.
Thank you so much crosire!

Well, I still think it's right to give a sign of appreciation for your work. And then I'm very happy to have discovered ReShade, which, as mentioned, solves a series of problems for me that I wouldn't have been able to find a solution to otherwise. Furthermore, since you have been so helpful and kind in listening to my bizarre requests, making a donation seems like the minimum 
The following user(s) said Thank You: crosire

Please Log in or Create an account to join the conversation.

  • O.T.T.
  • Topic Author
More
8 months 2 weeks ago - 8 months 2 weeks ago #7 by O.T.T. Replied by O.T.T. on topic I'm looking for help with a little code/shader for an arcade project

github.com/papadanku/CShade/blob/main/shaders/cTransform.fx does what you want I think (scale is expressed in multiples, but that's not hard to convert from pixel counts). Can just install it by selecting the CShade effect package in the ReShade setup tool.

I have a Patreon linked on the home page, but there's no need to worry about donating, I'm not doing this for money, so if money is needed elsewhere, please rather use it there.



 

I took some time to test the shader: it more or less does what I need but I experienced some difficulties. Below I will try to summarize the good and the bad, along with what I wish could be changed.

The good:

- allows 90° rotation (actually any angle you like) which is another option I needed
- allows you to position the image within the display area
- allows image scaling


The bad:

1) the rotation @90° completely stretches the image along the entire horizontal axis of the display. Of course I was expecting to lose the original aspect ratio, which is totally obvious, but this extends the time needed to achieve the desired result even more due to the non-intuitive (and in my opinion unnecessarily complicated) image scaling method (read below). RA internal menu option does a better job at this.

2) the positioning of the image does not occur by entering coordinates (which is what I would like) but with a parameter that I don’t quite understand how it works: it seems to be 1 pixel (@ minimun) shift and this more or less applies to the X axis but for the Y axis the math doesn’t add up. In essence, it is not possible to determine the position of the image exactly (the exact number of pixels shifted). Moreover it moves the image starting from its current position, while the RA internal menu option places the initial position of the image on coordinates XY 0,0 (rightly, IMO) allowing a convenient calculation of the pixels to be shifted to obtain the desired position: this second placement method would be ideal for me.

3) I don’t quite understand how the scaling is expressed…seems a sort of strange multiplier but the essence is that it makes the work of setting a precise aspect ratio unnecessarily laborious. Moreover, for my project I need to set not only the aspect ratio in itself but the exact number of pixels of the displayed area (X,Y)

4) even after I managed to reach with many trials and attempts more or less the desired result, after changing RA core (or even just the game!) I got a completely different result, so in the end the work done became useless (at least for my purpose). Again, RA internal menu option produce the same result (view) regardless of core and loaded game - which is what I need.


The simple and best solution would be that the shader accepts clear (= straightforward and immediately understandable) and fixed (not proportional or %, therefore not influenceable) parameters for its routines: pixels

Below, I report the shader code:
#include "shared/cGraphics.fxh"

/*
[Shader Options]
*/

uniform float _Angle <
ui_label = "Rotation Angle";
ui_type = "drag";
> = 0.0;

uniform float2 _Translate <
ui_label = "Translation";
ui_type = "drag";
> = 0.0;

uniform float2 _Scale <
ui_label = "Scaling";
ui_type = "drag";
> = 1.0;

/*
[Vertex Shaders]
*/

VS2PS_Quad VS_Matrix(APP2VS Input)
{
// Calculate the shader's HPos and Tex0
// We modify the Tex0's output afterward
VS2PS_Quad Output = VS_Quad(Input);

float RotationAngle = radians(_Angle);

float2x2 RotationMatrix = float2x2
(
cos(RotationAngle), -sin(RotationAngle), // Row 1
sin(RotationAngle), cos(RotationAngle) // Row 2
);

float3x3 TranslationMatrix = float3x3
(
1.0, 0.0, 0.0, // Row 1
0.0, 1.0, 0.0, // Row 2
_Translate.x, _Translate.y, 1.0 // Row 3
);

float2x2 ScalingMatrix = float2x2
(
_Scale.x, 0.0, // Row 1
0.0, _Scale.y // Row 2
);

// Scale TexCoord from [0,1] to [-1,1]
Output.Tex0 = Output.Tex0 * 2.0 - 1.0;

// Do transformations here
Output.Tex0 = mul(Output.Tex0, RotationMatrix);
Output.Tex0 = mul(float3(Output.Tex0, 1.0), TranslationMatrix).xy;
Output.Tex0 = mul(Output.Tex0, ScalingMatrix);

// Scale TexCoord from [-1,1] to [0,1]
Output.Tex0 = Output.Tex0 * 0.5 + 0.5;

return Output;
}

/*
[Pixel Shaders]
*/

float4 PS_Matrix(VS2PS_Quad Input) : SV_TARGET0
{
return tex2D(CShade_SampleColorTex, Input.Tex0);
}

technique CShade_Transform
{
pass
{
SRGBWriteEnable = WRITE_SRGB;

VertexShader = VS_Matrix;
PixelShader = PS_Matrix;
}
}
 

Does anyone have an idea of how the shader can be modified according to the criteria I explained?
Last edit: 8 months 2 weeks ago by O.T.T..

Please Log in or Create an account to join the conversation.

We use cookies
We use cookies on our website. Some of them are essential for the operation of the forum. You can decide for yourself whether you want to allow cookies or not. Please note that if you reject them, you may not be able to use all the functionalities of the site.