我正在尝试在我的spritekit 2d像素艺术游戏中应用调色板交换功能,并且在应用SKShader时,似乎忽略了SKSpriteNode纹理上的filteringMode。
因此,我认为我需要首先应用最近邻居着色,然后再进行调色板交换逻辑。
基于在着色器玩具上找到的一些代码,我已经做了这个尝试,这似乎是正确的方向,如果坐标被标准化并且(0.0,0.0)是左下角和(1.0,1.0)顶部,逻辑看起来对我来说是合理的是的,但结果是太过块了。
https://www.shadertoy.com/view/MllSzX
我对shader.fsh
文件的改编:
void main() {
float texSize = 48.0;
vec2 pixel = v_tex_coord * texSize;
float c_onePixel = 1.0 / texSize;
pixel = (floor(pixel) / texSize);
gl_FragColor = texture2D(u_texture, pixel + vec2(c_onePixel/2.0));
}
在继续进行调色板交换之前,如何让最近的邻居在我的SKShader上工作?
不是我自己的完美答案,但我设法通过在我的info.plist中添加PrefersOpenGL
到YES
来防止这个问题但是我知道在ios上尽可能使用Metal是首选
我遇到了类似的问题。我想围绕像素创建一个轮廓,同时保持像素化,但它会使现有像素模糊,使其看起来很糟糕。我最终实现了最近邻居,然后在计算最近邻居位置后检查邻居像素,以查看像素是否具有大于0的alpha。如果是,我将填充像素。我是这样做的:
Outline.fsh:
vec2 nearestNeighbor(vec2 loc, vec2 size) {
vec2 onePixel = vec2(1.0, 1.0) / size;
vec2 coordinate = floor(loc * size) / size;
return coordinate + onePixel / 2.0;
}
void main() {
vec2 onePixel = vec2(1.0, 1.0) / a_sprite_size;
vec4 texture = texture2D(u_texture, nearestNeighbor(v_tex_coord, a_sprite_size)); // Nearest neighbor for the current pixel
if (texture.a == 0.0) {
// Pixel has no alpha, check if any neighboring pixels have a non 0 alpha
vec4 outlineColor = vec4(0.9, 0.9, 0.0, 1.0);
if (texture2D(u_texture, nearestNeighbor(v_tex_coord + vec2(onePixel.x, 0), a_sprite_size)).a > 0.0) {
// Right neighbor has an alpha > 0
gl_FragColor = outlineColor;
} else if (texture2D(u_texture, nearestNeighbor(v_tex_coord + vec2(-onePixel.x, 0), a_sprite_size)).a > 0.0) {
// Left neighbor has an alpha > 0
gl_FragColor = outlineColor;
} else if (texture2D(u_texture, nearestNeighbor(v_tex_coord + vec2(0, onePixel.y), a_sprite_size)).a > 0.0) {
// Top neighbor has an alpha > 0
gl_FragColor = outlineColor;
} else if (texture2D(u_texture, nearestNeighbor(v_tex_coord + vec2(0, -onePixel.y), a_sprite_size)).a > 0.0) {
// Bottom neighbor has an alpha > 0
gl_FragColor = outlineColor;
} else {
// No neighbors with an alpha > 0, don't change the color
gl_FragColor = texture;
}
} else {
// Pixel has an alpha > 0
gl_FragColor = texture;
}
}
然后,您需要将着色器添加到精灵中,并在精灵和着色器上设置已定义的属性,以便可以使用着色器中定义的值。
spriteNode.setValue(SKAttributeValue(vectorFloat2: vector_float2(Float(spriteNode.size.width), Float(spriteNode.size.height))), forAttribute: "a_sprite_size")
let shader = SKShader(fileNamed: "Outline.fsh")
shader.attributes = [
SKAttribute(name: "a_sprite_size", type: .vectorFloat2)
]
spriteNode.shader = shader
希望这可以帮助其他有类似问题的人!