Ich versuche einen Umriss-Shader für 2D-Sprites zu erstellen, im Grunde nimmt es ein Sprite und prüft auf eine Farbe, wenn das Fragment diese Farbe hat, wird es als Umriss betrachtet die Texel um sie überprüft, und wenn keiner von ihnen transparent sind die alpha auf 0 gesetztGLSL ES Prüfe, ob das Fragment an der Grenze der Textur ist
Hier ist der Shader-Code, gm_Matrices [MATRIX_WORLD], gm_BaseTexture usw. von Spielmachers eingestellt sind, aber es ist alles Standard ich gehe davon aus:
http://paste.ofcode.org/XHJkmxQCVnQWhQJAqkk68D
Relevante Linien sind Linie 22 und Linie 57.
Grundsätzlich muss ich den Shader die Grenzen der Textur ignorieren lassen, denn wenn das Fragment an einem Rand ist, wird es immer als Umriss betrachtet.
Ich sende die custom_FragCoord-Variable, die die absoluten uv-Koordinaten enthält, vom Vertex-Shader zum Fragment-Shader, und dann sage ich zum Beispiel, ob "custom_FragCoord.x> 1. outline check", alles auf der gezeichnet erste Spalte wird als Umriss betrachtet.
Das Problem ist, wenn das Sprite einen Rahmen hat, der nichts gezeichnet hat, dann scheint der Shader nicht am Rand des Sprites zu zeichnen, also wenn zum Beispiel ein Sprite nichts am linken Rand hat Es beginnt mit custom_FragCoord.x = 1., nicht 0. So wird es nicht automatisch als Umriss betrachtet und stattdessen werden die angrenzenden Texel überprüft, und wenn es das linke Texel überprüft, wird es kein transparentes Texel finden, weil es es ist versuchte das linke Texel an der Grenze der Textur zu überprüfen.
Wenn jemand könnte bitte etwas Licht auf was könnte getan werden könnte, wäre eine immense Hilfe.
Hier ist der Code, wenn der Link nicht funktioniert:
//////////////////////// Vertex shader ////////////////////////
attribute vec3 in_Position; // (x,y,z)
//attribute vec3 in_Normal; // (x,y,z) unused in this shader.
attribute vec4 in_Colour; // (r,g,b,a)
attribute vec2 in_TextureCoord; // (u,v)
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
varying vec2 custom_FragCoord;
void main()
{
vec4 object_space_pos = vec4(in_Position.x, in_Position.y, in_Position.z, 1.0);
gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
v_vColour = in_Colour;
v_vTexcoord = in_TextureCoord;
//Send absolute fragment coordinate to fragment shader, maybe there's a different coordinate that should be sent instead since checks using this one only work when the sprite's texture touches all borders of the sprite size
custom_FragCoord = (gm_Matrices[MATRIX_WORLD] * object_space_pos).xy;
}
//////////////////////// Fragment shader ////////////////////////
///Outlines shader
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform vec3 sl_v3_ColorTo; //What color should the outline be
uniform vec2 sl_v2_PixelSize; //Distance to next fragment's x/y, for size of step calculation
uniform vec2 sl_v2_SpriteSize; //Size of current drawn sprite (Not used currently, but could be relevant idk)
varying vec2 custom_FragCoord; //Absolute fragment coordinate
void main()
{
vec3 v3_colorToTest = vec3(1.,1.,1.); //White outline color, for testing
vec3 v3_outLineColor = vec3(0.149, 0.149, 0.149); //Color of outline to look for, if fragment is not this color just ignore
//Check difference between fragment color and acceptable outline color
vec3 v3_colDiff = vec3 ( texture2D(gm_BaseTexture, v_vTexcoord).r - v3_outLineColor.r,
texture2D(gm_BaseTexture, v_vTexcoord).g - v3_outLineColor.g,
texture2D(gm_BaseTexture, v_vTexcoord).b - v3_outLineColor.b);
//How much does the fragment's color differ from the outline color it seeks
float f_colDiff = (v3_colDiff.x+v3_colDiff.y+v3_colDiff.z)/3.;
//If fragment color varies by more than 0.001 set alpha to 0, otherwise set it to 8
float alpha = 8.*floor(texture2D(gm_BaseTexture, v_vTexcoord).a + 0.001 -abs(f_colDiff));
//Bunch of conditionals, just to test, I'll take them off once stuff works
/*Here lies the problem: If the sprite is, for instance, 32x32, but only the bottom-half of it has stuff to draw, the "custom_FragCoord.y > 1" check will be useless,
since it will start drawing at custom_FragCoord.y = 15, not custom_FragCoord.y = 0*/
if (custom_FragCoord.x > 1. && custom_FragCoord.y > 1. && custom_FragCoord.x < sl_v2_SpriteSize.x-1. && custom_FragCoord.y < sl_v2_SpriteSize.y-1.)
{
//Check all around for transparency, if none is found it is not an outline
for (float i = 0.; i <= 315.; i+= 45.)
{
alpha -= ceil(texture2D(gm_BaseTexture, v_vTexcoord +vec2(sign(cos(i))*sl_v2_PixelSize.x,sign(sin(i))*sl_v2_PixelSize.y)).a);
}
}
//Paint result, with a white color to test out
vec4 col = vec4(v3_colorToTest, alpha);
gl_FragColor = col;
}
Ihr Code sollte in der Frage selbst sein, nicht in einem Link, so dass, wenn der Link stirbt, die Frage immer noch hilfreich für jemand anderen sein kann. – xaxxon
Oh, tut mir leid. –