[英]How to draw specific part of texture in fragment shader (SpriteKit)
我的节点大小为 64x32,纹理大小为 192x192,我试图在第一个节点处绘制该纹理的第一部分,在第二个节点处绘制第二部分......
片段着色器(附加到 SKSpriteNode,纹理大小为 64x32)
void main() {
float bX = 64.0 / 192.0 * (offset.x + 1);
float aX = 64.0 / 192.0 * (offset.x );
float bY = 32.0 / 192.0 * (offset.y + 1);
float aY = 32.0 / 192.0 * (offset.y);
float normalizedX = (bX - aX) * v_tex_coord.x + aX;
float normalizedY = (bY - aY) * v_tex_coord.y + aY;
gl_FragColor = texture2D(u_temp, vec2(normalizedX, normalizedY));
}
offset.x
- [0, 2]offset.y
- [0, 5]u_temp
- 纹理大小为 192x192但结果似乎是错误的:
带有附加纹理的 SKSpriteNode
SKSpriteNode 没有纹理(我想用纹理实现)
当纹理位于 altas 中时,不再通过(0,0)
到(1,1)
的坐标来处理它。 地图集真的是一个在幕后组装的大纹理。 当您在普通精灵中使用来自图集的特定命名图像时,SpriteKit 会在有关图集如何组装的信息中查找该图像名称,然后告诉 GPU 类似“使用bigAtlasTexture
绘制此精灵,坐标(0.1632,0.8814)
通过(0.1778, 0.9143)
“。 如果您要使用相同的纹理编写自定义着色器,则需要有关它在图集中的位置的信息,您可以从textureRect
获得这些信息:
https://developer.apple.com/documentation/spritekit/sktexture/1519707-texturerect
因此,您的纹理实际上不是一个图像,而是由许多纹理的大打包图像中的位置textureRect()
定义的。 我发现从(0,0)
到(1,1)
的角度来思考最容易,所以在编写着色器时,我通常会做textureRect
=> 减法和缩放以达到(0,0)-(1,1)
= > 计算所需的修改坐标 => 缩放并再次添加到textureRect
=> texture2D
查找。
由于您的着色器需要了解textureRect
但您不能从着色器代码中调用它,因此您有两种选择:
textureRect
的着色器代码,即它只是在纹理代码中包含一些常量。这是使用方法 #2 的示例的一部分:
func myShader(forTexture texture: SKTexture) -> SKShader {
// Be careful not to assume that the texture has v_tex_coord ranging in (0, 0) to
// (1, 1)! If the texture is part of a texture atlas, this is not true. I could
// make another attribute or uniform to pass in the textureRect info, but since I
// only use this with a particular texture, I just pass in the texture and compile
// in the required v_tex_coord transformations for that texture.
let rect = texture.textureRect()
let shaderSource = """
void main() {
// Normalize coordinates to (0,0)-(1,1)
v_tex_coord -= vec2(\(rect.origin.x), \(rect.origin.y));
v_tex_coord *= vec2(\(1 / rect.size.width), \(1 / rect.size.height));
// Update the coordinates in whatever way here...
// v_tex_coord = desired_transform(v_tex_coord)
// And then go back to the actual coordinates for the real texture
v_tex_coord *= vec2(\(rect.size.width), \(rect.size.height));
v_tex_coord += vec2(\(rect.origin.x), \(rect.origin.y));
gl_FragColor = texture2D(u_texture, v_tex_coord);
}
"""
let shader = SKShader(source: shaderSource)
return shader
}
这是此处某些特定示例的简化版本: https://github.com/bg2b/RockRats/blob/master/Asteroids/Hyperspace.swift
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.