In an OpenGL program you typical declare something like this in a vertex shader
varying bool aBooleanVariable;
and then read the value in the fragment shader. How do you do this within the framework of an SCNShadable
entry point? For example from SCNShaderModifierEntryPointGeometry
to SCNShaderModifierEntryPointFragment
.
Receiving the argument seems to be defined by using the pragma arguments, I provide my test SCNShaderModifierEntryPointFragment
to illustrate.
#pragma arguments
bool clipFragment
#pragma body
if (clipFragment) {
discard_fragment();
}
However, the arguments pragma doesn't work for outputting the value in the SCNShaderModifierEntryPointGeometry
entry point.
I found an article that suggests that it can be done with GLSL syntax, but I was trying to find the Metal way and I wasn't even able to reproduce the result.
I had a similar problem and managed to figure out the solution. I'm not sure how far back this works, but it works on XCode 9 with iOS 11. Here's an example of looking up a custom cubemap texture using a varying float3 for the coordinate.
The geometry modifier:
#include <metal_stdlib>
#pragma varyings
float3 cubemapCoord;
#pragma body
out.cubemapCoord = _geometry.normal;
The surface modifier:
#include <metal_stdlib>
#pragma arguments
texturecube<float> texture;
#pragma body
constexpr sampler s(filter::linear, mip_filter::linear);
_surface.diffuse = texture.sample(s, in.cubemapCoord);
And the Swift code for assigning the material:
do {
let loader = MTKTextureLoader.init(device: MTLCreateSystemDefaultDevice()!)
let url = Bundle.main.url(forResource: "cubemap", withExtension: "pvr", subdirectory: "art.scnassets")!
let texture = try loader.newTexture(URL: url, options: nil)
let materialProperty = SCNMaterialProperty.init(contents: texture)
geometry.setValue(materialProperty, forKey: "texture")
} catch {
print(error.localizedDescription)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With