I am making an 8 bit game.
I am looking for a shader that creates a border on a Sprite.
Here is the output I want exactly.
But it is written in Unity shader.
Is there a way to use this shader in cocos2dx?
I’ve applied the similar shader in this article, but the texture is smaller and not applied to some corners.
If I can’t use the Unity shader, how can I fix the bug in the shader below?
Nice results (rockman / mega man) from this shader
basically you just need to look at the fragment shader part of the unity shader
// If outline is enabled and there is a pixel, try to draw an outline.
if (_Outline > 0 && c.a != 0) {
// Get the neighbouring four pixels.
fixed4 pixelUp = tex2D(_MainTex, IN.texcoord + fixed2(0, _MainTex_TexelSize.y));
fixed4 pixelDown = tex2D(_MainTex, IN.texcoord - fixed2(0, _MainTex_TexelSize.y));
fixed4 pixelRight = tex2D(_MainTex, IN.texcoord + fixed2(_MainTex_TexelSize.x, 0));
fixed4 pixelLeft = tex2D(_MainTex, IN.texcoord - fixed2(_MainTex_TexelSize.x, 0));
// If one of the neighbouring pixels is invisible, we render an outline.
if (pixelUp.a * pixelDown.a * pixelRight.a * pixelLeft.a == 0) {
c.rgba = fixed4(1, 1, 1, 1) * _OutlineColor;
}
}
c.rgb *= c.a;
And then you just tweak the outline shader from cpp test to become like the unity’s one
(using up, down, right, left textureCoordinate offsets instead of ‘radius’).
Do note that texelSize does not come built-in for glsl, you will have to pass it in as a uniform.
1). You can do a conditional check similar to this. Check surrounding 4 pixels’ alpha and maybe use the lowest non-zero value?
// If one of the neighbouring pixels is invisible, we render an outline.
if (pixelUp.a * pixelDown.a * pixelRight.a * pixelLeft.a == 0) {
c.rgba = fixed4(1, 1, 1, 1) * _OutlineColor;
}
2). Sorry i am not sure what this means, perhaps a screenshot might explain better?
3). The unity shader is using TexelSize instead of radius, which is 1 / TextureSizeInPixels. You can refer to this shader example which is doing something like that
ok, i’ve just taken a look at your shader code.
you are still using the same method from cpp test, only changing the texture offset values.
The issue in this shader is that it will accumulate the alpha values of those pixels around it. Those outline having higher opacity are those pixels with more neighbouring pixels that are non-transparent.
And how this shader works is that it will draw the outline on transparent pixels surrounding the colored pixels. So, when there is no transparent pixel above (just fit size), then there is no outline there.
If you change the shader to be like the unity one (in my first post), it will work differently. It will replace the colored pixel at the edge with outline color, instead of outline on the transparent pixel.
fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;
the first part of the unity shader is almost the same as this part of your shader
normal = texture2D(CC_Texture0, vec2(v_texCoord.x, v_texCoord.y));
except that it multiplies with IN.color, which is equivalent to v_fragmentColor
and as such it has already factored the opacity.
As you see, the very last part of the shader before returning the final color, it multiplies by the opacity that was factored in the first part, so there won’t be any issues with the opacity.
c.rgb *= c.a;
EDIT: Seeing that you have a u_thickness variable, it seems drawing the outline on transparent pixels is what will make the thickness work.
And regards to your #2 issue, it must have transparent pixels at the edge for the outline.
You should change the accumulate method to be using 4 different variables instead (for each of the surrounding pixels).