适用于几何体入口点的SceneKit着色器修改器可在iOS中使用,但不适用于OS X [英] SceneKit shader modifier for geometry entry points works in iOS but not OS X

查看:255
本文介绍了适用于几何体入口点的SceneKit着色器修改器可在iOS中使用,但不适用于OS X的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm in the early stages of making a SceneKit shader modifier (for the geometry entry point) that displaces a plane's geometry according to a height-map texture. The plan is to use it for creating terrain.

在iOS(iOS Simulator)中,着色器可以正常工作,但会在控制台上显示以下警告:

In iOS (edit: the iOS Simulator) the shader works as it should, but does print this warning to the console:

SceneKit:错误,没有代码的修饰符无效

SceneKit: error, modifier without code is invalid

但是,在为OS X构建时,着色器出现致命错误,并且地形几何图形仅显示为粉红色矩形.

When building for OS X however, the shader gets a fatal error, and the terrain geometry just displays as a pink rectangle.

这是几何着色器修改器:

This is the geometry shader modifier:

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采样器值中:

And this is how the shader is connected to the geometry. terrainScene is the height map, it is placed in both the diffuse contents, and the custom displacementMap sampler value in the shader modifier:

    //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错误消息的开头:

This is the beginning of the OS X error message:

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上失败吗?

Does anyone know why it displays on iOS, but fails on OS X?

推荐答案

我建议这可能不是iOS与OSX的问题,而是与使用OpenGL的一个设备和另一个使用Metal的设备有关.

I'd suggest it may not be a iOS vs OSX issue, but related to one device using OpenGL and the other Metal.

错误消息中的代码是Metal,表明SceneKit已将您的代码从GLSL转换为Metal.以我的经验,这不可能100%地起作用.在您的情况下,最简单的解决方案可能是通过

The code in the error message is Metal, indicating that SceneKit has translated your code from GLSL to Metal. In my experience this doesn't work 100% of the time. In your case the simplest solution may be to force the SCNView to use OpenGL by passing in options when it's created. I believe there's also a dropdown in Interface Builder for this too.

如果您希望继续使用Metal,并且出于某些原因,请继续阅读.

If you wish to keep using Metal, and there are reasons why you would, read on.

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

When a shader modifier fails to compile the entire contents of the shader is dumped to stdout, this really helps the debugging process. If you scroll up to line 343 you will find that SceneKit has included the float4 displace = displacementMap.sample(...); method before the vertex shader. Being defined outside a function means that it is a global variable, hence requiring the constant address space modifier, but this isn't what you wanted at all... In this instance the translation from GLSL to Metal hasn't worked as you expected.

我注意到您缺少#pragma arguments指令,该指令应包含在统一定义上方(请参阅),可能会有所帮助.根据我的经验,我认为将纹理传递到基于金属的着色器修改器中会很困难.我尝试失败,然后写了SCNProgram来代替它.建议强制使用OpenGL.

I note you're missing the #pragma arguments directive, this should be included above the uniform definition (refer to "Writing a Shader Modifier Snippet"), it may help. In my experience I think you'll have a tough time passing a texture into a Metal based shader modifier. I tried, failed, and wrote a SCNProgram to do it instead. Suggest forcing OpenGL.

这篇关于适用于几何体入口点的SceneKit着色器修改器可在iOS中使用,但不适用于OS X的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆