Я пытаюсь создать контурный шейдер для 2d спрайтов, в основном он берет спрайт и проверяет цвет, если фрагмент имеет этот цвет, он считается контуром, тогда проверяет текселей вокруг него, и если ни один из них не являются прозрачными его альфа устанавливается в 0.GLSL ES Проверьте, находится ли фрагмент на границе текстуры
Вот код шейдера, gm_Matrices [MATRIX_WORLD], gm_BaseTexture и т.д. устанавливаются GameMaker, но это все стандартные я предполагаю:
http://paste.ofcode.org/XHJkmxQCVnQWhQJAqkk68D
Релевантные линии - это линия 22 и Line 57.
В принципе, мне нужно сделать, чтобы шейдер игнорировал границы текстуры, так как если фрагмент находится на границе, он всегда будет считаться контуром.
Я отправляю переменную custom_FragCoord, содержащую абсолютные координаты uv из вершинного шейдера в шейдер фрагмента, а затем говорю, например, если «custom_FragCoord.x> 1. выполнить проверку контура», чтобы сделать все нарисованным на первый столбец считается контуром.
Проблема заключается в том, что у спрайта есть граница с ничем нарисованным на нем, тогда шейдер, кажется, не начинает рисовать на границе спрайта, так, например, если спрайт ничего не имеет на левой границе, тогда он начнет рисовать по custom_FragCoord.x = 1., а не 0., поэтому он не будет автоматически рассматривать его в виде контура и вместо этого проверяет соседние тексели, а когда он проверяет левый тексель, он не найдет прозрачный тексель, потому что он попытался проверить левый тексель на границе текстуры.
Если кто-то может пролить свет на то, что можно было бы сделать, это было бы огромной помощью.
Вот код, если ссылка не работает:
//////////////////////// 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;
}
Ваш код должен быть в самом вопросе, а не в ссылке, так что, если связь умирает, quesiton может оказаться полезным для кого-то другого. – xaxxon
О, простите об этом. –