Hi all!
I use Cocos Creator version 3.8.3.
I want to write a shader. In this shader I need to be able to determine the position of a fragment relative to the geometry it belongs to. Whether this position will be in normalized coordinates from 0 to 1 or in a value from 0 to the width/height of the sprite - 1, it is not so important to me. I need the shader exclusively for the UI, it will be used with the Sprite component.
I haven’t worked with shaders in Cocos Creator before. Here they are called effects. I created my effect file test from the contents of the file at “internal/effects/for2d/builtin-sprite.effect”. I created a test material and used the test effect in it.
I created a 200x400 image with this appearance:
Added it to the project, placed it on the scene. If you do not set CustomMaterial in the Sprite component, then changing the Grayscale flag is reflected in the appearance of the sprite.
But as soon as I set my test material in CustomMaterial, the entire sprite turns white. In general, I have to enable the USE TEXTURE field in the material itself. Similarly, I have to enable the IS GRAY field myself. I understand that depending on the preprocessor definitions, there are many variants of the same shader. Apparently, the Sprite component itself selects the desired variant from the standard ones. Well, is there any way to make it select the desired variant from my shader? Ultimately, I do not change the structure or the list of preprocessor definitions - everything remains as is.
In general, so far I have only checked the USE TEXTURE box in the test material.
If we talk about the method of obtaining the fragment coordinate, then when using a texture, I could use UV. As far as I remember, the center of the sprite would be the fragment at coordinates (0.5, 0.5). I decided to add the following lines of code to the shader:
if (uv0.x > 0.45 && uv0.x < 0.55 && uv0.y > 0.45 && uv0.y < 0.55) {
return vec4(1, 0, 0, 1);
}
Of course, this is only if there is a texture:
The expected result:
But this is in the editor. And if you run it in the browser, you will see:
Why is that?
I changed the paint condition to:
if (uv0.y > 0.5) {
Experimented with other pictures and noticed that if the picture is in an atlas, the result may be incorrect. Apparently, in the first case, my sprite was pasted somewhere when launched in the browser.
Then the question is, how do I take into account in the shader if the sprite is in the atlas? That is, how do I get local UV?
That’s the UV thing. Can’t Cocos Creator output a sprite without a texture at all? Doesn’t it just create two triangles for them? At the beginning of the fragment shader I wrote:
return vec4(0.25, 0.5, 1, 1);
However, nothing was output when I cleared the Sprite Frame field of the Sprite component (the size of the UITransform component was 200x400).
In general, how else can you find out from a fragment shader about the position of a fragment relative to the geometry to which it belongs?