Post

Replies

Boosts

Views

Activity

SKAttributes do not work as expected with SKShapeNode instance
The documentation suggests that it should be possible to use a single shader with multiple instances of an SKNode, such that each instance will use the unique SKAttributes that are passed to it. Let's try that with an SKShapeNode. This is the fragment shader testFill.fsh, simply coloring based on the value for a_test: void main() {     gl_FragColor = vec4(vec3(a_test), 1.0); } And here we make two nodes `testNode0`, and `testNode1`, each using the same shader, but with a different value for `a_test`: class GameScene: SKScene {     override func didMove(to view: SKView) {         let testShader = shaderWithFilename( "testFill", fileExtension: "fsh", uniforms: [])         testShader.attributes = [             SKAttribute(name: "a_test", type: .float)         ] let testNode0 = SKShapeNode(rect: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)) testNode0.fillShader = testShader testNode0.position = CGPoint(x: -100, y: 300) testNode0.setValue(SKAttributeValue(float: 0.2), forAttribute: "a_test") addChild(testNode0) let testNode1 = SKShapeNode(rect: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)) testNode1.fillShader = testShader testNode1.position = CGPoint(x: 100, y: 300) testNode1.setValue(SKAttributeValue(float: 0.8), forAttribute: "a_test") addChild(testNode1) } } Here is the result: The squares are the same color, in particular the result of passing the second value 0.8 for a_test. Now, let's try the same thing with SKSpriteNode: class GameScene: SKScene {     override func didMove(to view: SKView) {         let testShader = shaderWithFilename( "testFill", fileExtension: "fsh", uniforms: [])         testShader.attributes = [             SKAttribute(name: "a_test", type: .float)         ] let testNode0 = SKSpriteNode() testNode0.size = CGSize(width: 100.0, height: 100.0) testNode0.shader = testShader testNode0.position = CGPoint(x: -100, y: 300) testNode0.setValue(SKAttributeValue(float: 0.2), forAttribute: "a_test") addChild(testNode0) let testNode1 = SKSpriteNode() testNode1.size = CGSize(width: 100.0, height: 100.0) testNode1.shader = testShader testNode1.position = CGPoint(x: 100, y: 300) testNode1.setValue(SKAttributeValue(float: 0.8), forAttribute: "a_test") addChild(testNode1) } } And it works! Why does the documentation not say that this is not possible with an SKSpriteNode? Why does an SKSpriteNode have a .setValue method if it does not function as expected? Is this a bug? Or something that is expected to be obvious? I am not sure, but I am sharing this in case somebody else ends up stuck on this issue as I was when otherwise trying to do something relatively straightforward. The solution (if your shape is a simple rect, as it is in my case) is to initialize an empty SKSpriteNode and size it accordingly, after which SKAttributes should work as expected. Apple, please either fix this, or update the documentation.
2
2
1.5k
Jan ’23
Is it possible to use AVAudioEngine to monitor an input device through an output device?
I understand that with AVAudioEngine, I can access .inputNode and .outputNode. I also understand that it is possible to point audio at a particular output device: var outputDeviceID: AudioDeviceID = 50  // External display speakers guard let outputUnit: AudioUnit = engine.outputNode.audioUnit else { return } AudioUnitSetProperty(outputUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 1, &outputDeviceID, UInt32(MemoryLayout<AudioDeviceID>.size)) Yet, if I try to capture, or even simply access the .inputNode, this will fail. Doing this: let input = engine.inputNode let output = engine.outputNode and then setting a custom outputDeviceID as show above, will cause this error: Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=com.apple.coreaudio.avfaudio Code=-10875 "(null)" UserInfo={false condition=IsFormatSampleRateAndChannelCountValid(outputHWFormat)} I could not find any documentation about this, but I did find others on StackOverflow who had similar issues and came to the conclusion that it cannot be done this way. I am looking for an alternative. My goal is to simply connect Input Device A with Output Device B, where B is not necessarily the System Output device. I saw one suggestion to create an AudioUnit to pass the data through, but I am not clear on how to do that without explicitly referring to engine.inputNode, which will cause the above error. I know that this has to be possible because applications like Logic Pro and GarageBand have preference panes where one can select an input device and output device and do live monitoring with very low latency. While I would prefer an option that has no latency, I'd be interested in whatever is possible. Thank you!
0
1
1.2k
Jan ’21