GLSL + Scenekit:不允许函数定义

Posted

技术标签:

【中文标题】GLSL + Scenekit:不允许函数定义【英文标题】:GLSL + Scenekit: Function definition not allowed 【发布时间】:2020-09-01 04:30:51 【问题描述】:

我正在尝试在 Scenekit 中创建一个顶点着色器。着色器已成功添加到 SCNNode 的几何体中,但由于出现错误,它显示为紫色。我使用 SCNShaderModifiers 将着色器添加到几何体,并且知道它们已成功找到并附加。

我收到的确切错误消息是:

2020-08-31 21:26:53.977977-0700 Azure[69834:3664712] [SceneKit] Error: FATAL ERROR : failed compiling shader:
Error Domain=MTLLibraryErrorDomain Code=3 "Compilation failed: 

program_source:2901:97: error: function definition is not allowed here
float2 wavedx(float2 position, float2 direction, float speed, float frequency, float timeshift) 
                                                                                                ^
program_source:2908:49: error: function definition is not allowed here
float getwaves(float2 position, int iterations) 
                                                ^
" UserInfo=NSLocalizedDescription=Compilation failed: 

program_source:2901:97: error: function definition is not allowed here
float2 wavedx(float2 position, float2 direction, float speed, float frequency, float timeshift) 
                                                                                                ^
program_source:2908:49: error: function definition is not allowed here
float getwaves(float2 position, int iterations) 
                                                ^

但是,当我不使用方法时,着色器可以完美运行。为了测试这一点,我使用了一个常规的正弦着色器。以下示例有效:

uniform float Amplitude = 0.1;
_geometry.position.z += sin(u_time + _geometry.position.x);

我试图开始工作的代码是这样的,它具有以下功能:

float Time = u_time;
float DRAG_MULT = 0.048;

vec2 wavedx(vec2 position, vec2 direction, float speed, float frequency, float timeshift) 
    float x = dot(direction, position) * frequency + timeshift * speed;
    float wave = exp(sin(x) - 1.0);
    float dx = wave * cos(x);
    return vec2(wave, -dx);


float getwaves(vec2 position, int iterations) 
    
    float iter = 0.0;
    float phase = 6.0;
    float speed = 2.0;
    float weight = 1.0;
    float w = 0.0;
    float ws = 0.0;
    
    for(int i = 0; i < iterations; i++)
        vec2 p = vec2(sin(iter), cos(iter));
        vec2 res = wavedx(position, p, speed, phase, Time);
        position += normalize(p) * res.y * weight * DRAG_MULT;
        w += res.x * weight;
        iter += 12.0;
        ws += weight;
        weight = mix(weight, 0.0, 0.2);
        phase *= 1.18;
        speed *= 1.07;
    
    return w / ws;

我不知道这里出了什么问题。这些都是独立的 GLSL sn-ps。谢谢!

【问题讨论】:

【参考方案1】:

我使用 SCNShaderModifiers 将着色器添加到几何体,并且知道它们已成功找到并附加。

如果您使用SCNShaderModifiers,您还必须遵守他们的documentation:

    自定义全局函数。如果您的着色器修改器受益于将通用代码分解为函数,请将它们的定义放在这里。如果 如果您在 sn-p 中包含自定义函数,则必须将 #pragma body 指令位于你的函数定义和 sn-p 的主体之间。

【讨论】:

我正在查看他们的文档,但它似乎将 OpenGL 和 Metal 结合在一个代码 sn-p 中,所以我非常迷茫。你能举个例子吗? 我链接的页面一个代码示例,它还显示了您如何在其中处理 Metal 和 OpenGL。 感谢您的回复,将您的答案标记为正确。对我造成问题的aprt是顶部金属代码的额外sn-p,不知道他们为什么将它们放在一个sn-p中。

以上是关于GLSL + Scenekit:不允许函数定义的主要内容,如果未能解决你的问题,请参考以下文章

WebGL-Shader入门(4.着色器语言GLSL ES函数定义与流程控制)

GLSL Uniform

GLSL Uniform

GLSL Uniform

Bazel 内建函数

NO.15 - OpenGL ES 使用GLSL加载图片