ios - 几何入口点的 SceneKit 着色器修改器适用于 iOS 但不适用于 OS X

标签 ios macos shader scenekit heightmap

我正处于制作 SceneKit 着色器修改器(用于几何体入口点)的早期阶段,该修改器根据高度贴图纹理置换平面的几何体。计划是用它来创建地形。

在 iOS(编辑:iOS 模拟器)中,着色器正常工作,但会向控制台打印此警告:

SceneKit: error, modifier without code is invalid

How it looks on iOS

然而,当为 OS X 构建时,着色器会出现 fatal error ,地形几何体仅显示为粉红色矩形。

这是几何着色器修改器:

uniform sampler2D displacementMap;
const float intensity = 7.5;

# pragma body

vec4 displace = texture2D(displacementMap, _geometry.texcoords[0]);

_geometry.position.z += displace.r * intensity;

这就是着色器连接到几何体的方式。 terrainScene 是高度图,它被放置在漫反射内容和着色器修改器中的自定义 displacementMap 采样器值中:

    //displacement shader

    let mat = SCNMaterial()
    mat.diffuse.contents = terrainScene

    var displacementShader: String?
    guard let path = NSBundle.mainBundle().pathForResource("DisplaceGeometry", ofType: "shader") else {return}

    do {
        displacementShader = try String(contentsOfFile: path,  encoding: NSUTF8StringEncoding)
    } catch {
        return
    }
    mat.shaderModifiers = [SCNShaderModifierEntryPointGeometry: displacementShader!]
    let noiseProperty = SCNMaterialProperty(contents: terrainScene!)
    mat.setValue(noiseProperty, forKey: "displacementMap")

    //geometry
    let plane = SCNPlane(width: 80, height: 80)
    plane.widthSegmentCount = 40
    plane.heightSegmentCount = 40
    plane.materials = [mat]

这是 OS X 错误消息的开头:

SceneKit: error, modifier without code is invalid
2016-06-11 10:58:32.054 EndlessTerrainOSX[16923:5292387] SceneKit: error, Invalid shader modifier : no code provided
2016-06-11 10:58:32.640 EndlessTerrainOSX[16923:5292387] FATAL ERROR : failed loading compiling shader:

错误结束:

UserInfo={NSLocalizedDescription=Compilation failed: 
<program source>:343:8: error: global variables must have a constant address space qualifier
float4 displace = displacementMap.sample(displacementMapSampler, _geometry.texcoords[0]);
       ^
<program source>:343:19: error: use of undeclared identifier 'displacementMap'
float4 displace = displacementMap.sample(displacementMapSampler, _geometry.texcoords[0]);
                  ^
<program source>:343:42: error: use of undeclared identifier 'displacementMapSampler'
float4 displace = displacementMap.sample(displacementMapSampler, _geometry.texcoords[0]);
                                         ^
<program source>:344:1: error: unknown type name '_geometry'
_geometry.position.z += displace.r * intensity;
^
<program source>:344:10: error: cannot use dot operator on a type
_geometry.position.z += displace.r * intensity;
         ^
}
2016-06-11 10:58:32.646 EndlessTerrainOSX[16923:5292387] Shaders without a vertex function are not allowed

有谁知道为什么它在 iOS 上显示,但在 OS X 上显示失败?

最佳答案

我认为这可能不是 iOS 与 OSX 的问题,而是与使用 OpenGL 的设备和使用其他 Metal 的设备有关。

错误信息中的代码是Metal,表示SceneKit已经将你的代码从GLSL翻译成Metal。根据我的经验,这在 100% 的时间都不起作用。在您的情况下,最简单的解决方案可能是通过 passing in options when it's created 强制 SCNView 使用 OpenGL。 .我相信 Interface Builder 中也有一个下拉菜单。

如果您希望继续使用 Metal,并且有您这样做的原因,请继续阅读。

当着色器修改器无法编译时,着色器的全部内容都会转储到标准输出,这确实有助于调试过程。如果向上滚动到第 343 行,您会发现 SceneKit 在顶点着色器 之前包含了 float4 displace = displacementMap.sample(...); 方法。在函数外部定义意味着它是一个全局变量,因此需要 constant 地址空间修饰符,但这根本不是您想要的……在这种情况下,从 GLSL 到 Metal 的转换没有像您预期的那样工作。

我注意到您缺少 #pragma arguments 指令,这应该包含在统一定义之上(引用 "Writing a Shader Modifier Snippet" ),它可能会有所帮助。以我的经验,我认为您将很难将纹理传递到基于金属的着色器修改器中。我尝试过,失败了,然后写了一个 SCNProgram 来代替它。建议强制使用 OpenGL。

关于ios - 几何入口点的 SceneKit 着色器修改器适用于 iOS 但不适用于 OS X,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37762535/

相关文章:

unity3d - 是否可以在 Unity 的 HDRP 中创建 DepthMask 效果?

graphics - 使用 2D 元球绘制具有恒定厚度的轮廓

ios - 通过storyboards在同一个UICollectionView中注册多个header supplementary view

swift - 如何在 Swift (macOS) 中使状态栏显示文本而不是图标?

ios - 具有表情符号时 TTTAttributedLabel 不显示最后一行

c++ - 使用 Xcode 在 MacOS X 上安装 GMP

java - 终端动画 - 清除屏幕是正确的方法吗?

shader - 使用着色器函数从变量中删除负数

java - 在 iOS 上信任我自己的 CA

ios - UIView 的渐变层不符合约束集