Is there a way of making a png a shader?


#1

I am making and playing around with some transparent pngs (vignette, scanlines, masks effects) and wanted to know if there is a way like a very basic shader code to just simply call an image and place it full in the game area.

I do not want to use the overlay feature to achieve this, because not only I would have to make a lot of overlays with the different combination of all the effects as well as combinations of each core/game overlay, but also because I wont be able to use it on the different cores resolutions.

Thanks!


#2

Yes, you need a simple shader and a simple preset. The shader should be something like this:

   vec4 game = texture(Source, vTexCoord);
   vec4 effect = texture(overlaytest, vTexCoord);
   FragColor = mix(game, effect, effect.a);

and the preset should look something like this:

shaders = 1
shader0 = effect-overlay-test.slang
textures = "overlaytest"
overlaytest = overlaytest.png
filter_linear_overlaytest = true

That shader is just the main function, so it’ll need all of the normal boilerplate stuff around it. You’ll have to call out the LUT, as well, and if you’re making a GLSL shader, replace ‘texture’ with ‘COMPAT_TEXTURE’


#3

Thank you hunter! WIll give it a shot after work.

If I have more than one png effect, is just a matter of adding them as different shaders in the preset right?

If I would like to have a parameter for each shader that is only the Opacity of the png, is that an easy code to add? (if you have in mind a shader that already does it, let me know and I’ll check its code).


#4

You could add a pass for each effect, sure, or you could just add them all to the same pass by adding additional lines, like:

   vec4 game = texture(Source, vTexCoord);
   vec4 effect0 = texture(effect0_tex, vTexCoord);
   vec4 effect1 = texture(effect1_tex, vTexCoord);
   vec4 effect2 = texture(effect2_tex, vTexCoord);
   FragColor = mix(game, effect0, effect0.a);
   FragColor = mix(FragColor, effect1, effect1.a);
   FragColor = mix(FragColor, effect2, effect2.a);

And if you wanted to add opacity parameters, you could do that like this (you would need to set up a parameter pragma for each of them and add them to the proper structs, etc):

   vec4 game = texture(Source, vTexCoord);
   vec4 effect0 = texture(effect0_tex, vTexCoord);
   effect0.a *= params.effect0_opacity_mod;
   vec4 effect1 = texture(effect1_tex, vTexCoord);
   effect1.a *= params.effect0_opacity_mod;
   vec4 effect2 = texture(effect2_tex, vTexCoord);
   effect2.a *= params.effect0_opacity_mod;
   FragColor = mix(game, effect0, effect0.a);
   FragColor = mix(FragColor, effect1, effect1.a);
   FragColor = mix(FragColor, effect2, effect2.a);

#5

Awesome. One last question; in case I add multiple effects in the same pass, how do I call/refer each of their pngs?


#6

You just need to add the name to the “textures” list, separated by a semicolon and then connect a path to that alias, like this:

shaders = 1
shader0 = effect-overlay-test.slang
textures = "effect0_tex;effect1_tex;effect2_tex"
effect0_tex = /path/to/effect0.png
filter_linear_effect0_tex = true
effect1_tex = /path/to/effect1.png
filter_linear_effect1_tex = true
effect2_tex =/path/to/ effect2.png
filter_linear_effect2_tex = true

The linear filtering here isn’t completely necessary, but it makes LUTs look a lot better, typically.


#7

You rock! As always :slight_smile:

Ok, trying to make them now, although it is not working, which I suppose is because I am not typing all the required information.

  • I have the image: vignette.png
  • I made the glsl file called vignette.glsl
  • Its content is the following:
vec4 game = COMPAT_TEXTURE(Source, vTexCoord);
vec4 effect = COMPAT_TEXTURE(vignette, vTexCoord);
FragColor = mix(game, effect, effect.a);
  • I created a preset called test.glslp
  • Its content is:

shaders = 1

shader0 = vignette.glsl

textures = “vignette”

vignette = vignette.png

filter_linear_overlaytest = true

I need to fill more stuff right? (Where it says source, or vtext or coords?)

Sorry for bothering @hunterk


#8

Yeah, as I mentioned, those lines are just the main function. You need a whole bunch of other stuff in there to make the shader work:

// version directive if necessary

// good place for credits/license

// Parameter lines go here:
#pragma parameter WHATEVER "Whatever" 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;
// out variables go here as COMPAT_VARYING whatever

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 WHATEVER;
#else
#define WHATEVER 0.0
#endif

void main()
{
    gl_Position = MVPMatrix * VertexCoord;
    TEX0.xy = TexCoord.xy;
// Paste vertex contents here:
}

#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;
uniform sampler2D vignette;
COMPAT_VARYING vec4 TEX0;
// in variables go here as COMPAT_VARYING whatever

// 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)

// delete all 'params.' or 'registers.' or whatever in the fragment and replace
// texture(a, b) with COMPAT_TEXTURE(a, b) <-can't macro unfortunately

#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float WHATEVER;
#else
#define WHATEVER 0.0
#endif

void main()
{
   vec4 game = COMPAT_TEXTURE(Source, vTexCoord);
   vec4 effect = COMPAT_TEXTURE(vignette, vTexCoord);
   FragColor = mix(game, effect, effect.a);
} 
#endif

This is the slang-conversion-template.glsl shader with those lines pasted into it (and I went ahead and called out the vignette texture in the fragment, as well).


#9

Thank you. Will tinker with it later on.


#10

@hunterk I may be understanding things wrong but shouldn’t “filter_linear_overlaytest = true” be “filter_linear_vignette = true” in this situation?


#11

Yes, it should. It’s filter_linear_LUTNAME = bool


#12

Thanks for verifying, I’m trying to slowly figure this out.