Sprite outer outline shader

Hi all!

I am using Cocos Creator version 3.8.6.

I need a shader that draws the outer outline of a sprite. It would be interesting to write it myself, but difficulties arose.

Since this shader draws the outer contour, I need to prepare sprites with a sufficient size in advance and disable trimming in the editor.

Basically, I only need to pass two parameters to the shader:

  1. Color
  2. Thickness

Something like this:

properties:
	outlineColor: { value: [1.0, 1.0, 1.0, 1.0], editor: { type: color } }
	thickness: { value: 1.0 }

...

uniform Constant{
	vec4 outlineColor;
	float thickness;
};

At first I tried to use the textureOffset function:

vec4 topColor = textureOffset(cc_spriteTexture, uv0, ivec2(0, 1));

But I got an error:

ERROR: 0:80: 'texture2DOffset' : no matching overloaded function found
ERROR: 0:80: '=' : dimension mismatch
ERROR: 0:80: '=' : cannot convert from 'const mediump float' to 'highp 4-component vector of float'

I don’t understand how to convert. I borrowed the framework for the shader experiment from the built-in shader “builtin-sprite.effect”, which is located in “3.8.6\resources\resources\3d\engine\editor\assets\effects\for2d”. What can be done about this? I wonder what it writes about texture2DOffset, although I used textureOffset.

Since I don’t know the answer yet, I decided to go another way - add an offset to the current uv. But in order to do this, I need to know the texel size or at least the texture size. I write:

ivec2 textureSize = textureSize(cc_spriteTexture, 0);

I receive:

ERROR: 0:80: 'texture2DSize' : no matching overloaded function found
ERROR: 0:80: '=' : cannot convert from 'const mediump float' to 'mediump 2-component vector of int'

I couldn’t think of anything smarter than adding the textureSize parameter:

properties:
	textureSize: { value: [0, 0], editor: { type: vec2 } }
	outlineColor: { value: [1.0, 1.0, 1.0, 1.0], editor: { type: color } }
	thickness: { value: 1.0 }

...

uniform Constant{
	vec4 outlineColor;
	vec2 textureSize;
	float thickness;
};

I don’t like this. How can the situation be improved?

Another question related to atlases. Of course I want to take my sprites and put them in an atlas. Of course, I can add a huge empty space between the sprites. Or I can not add it. But what I definitely do not want is to read pixels of the neighboring sprite from the current sprite. Is it possible to somehow trim texture coordinates in the shader if they go beyond the current sprite in the atlas? Well, at least something that will help. Maybe get the minimum and maximum uv. Any ideas?