我从未遇到过如下所示的不使用已定义变量的莫名其妙行为。该代码是通过精心将大型程序煮沸至显示问题所需的最低限度而产生的。
我的SKScene中的以下代码创建了三个精灵并显示一个,但使用着色器显示作为制服传入的其他精灵之一的纹理。
SKSpriteNode *background = [[SKSpriteNode alloc] initWithImageNamed:@"background"];
SKSpriteNode* piece1 = [[SKSpriteNode alloc] initWithImageNamed:@"piece1"];
SKSpriteNode *piece2 = [[SKSpriteNode alloc] initWithImageNamed:@"piece2"];
SKShader* shader = [SKShader shaderWithFileNamed:@"test.fsh"];
[shader addUniform:[SKUniform uniformWithName:@"u1" texture:background.texture]];
[shader addUniform:[SKUniform uniformWithName:@"piece1Texture" texture:piece1.texture]];
[shader addUniform:[SKUniform uniformWithName:@"u2" float:0.0]];
[shader addUniform:[SKUniform uniformWithName:@"u3" float:0.0]];
piece2.shader = shader;
[self addChild:piece2];
这是着色器:
void main(void) {
gl_FragColor = texture2D(piece1Texture, v_tex_coord);
}
着色器应显示piece1,而不是显示piece2。但是,它实际上显示了背景(来自未使用的“u1”制服)。对于设备和模拟器都是如此。
[嗯,okaaaay ....]
如果我更改未使用的制服的名称,或更改制服的顺序,或删除其中一个未使用的制服,则着色器将按预期工作。< / p>
[真的?]
此外,在玩了各种各样的名字之后,我找到了曾经失败但后来成功的名字。
[叹息]
在SKShader docs中,有关于向着色器添加制服的这一令人费解的评论:
必须在片段着色器中访问制服。
这对我来说听起来很奇怪。为什么这是真的,这是什么意思?在我的真实着色器中,我有由于if条件和用户行为而无法访问的制服。
可以吗?或者,我是否需要人为地访问每件制服,以防有些人无法访问?
据我所知,SKShader doc是“初步文档”,但行为是如此出乎意料,我不禁想知道是否需要更多解释。这是一个SpriteKit问题,还是一般适用于OpenGL ES?
答案 0 :(得分:1)
我根据技术支持的建议提交了一个错误(#20629165)。
我:&#34;为什么必须在片段着色器中使用制服?如果a会发生什么 没有使用制服?&#34;
Apple:&#34;原因在于提高效率,如果声明制服但未在着色器源中使用,Sprite Kit仍然会将着色器均匀值上传到GPU以进行当前绘制。话虽如此,如果宣布制服但未使用,结果应该仍然是正确的。我鼓励你提交一个错误:https://developer.apple.com/bug-reporting/&#34;