带有GLSL数组的SceneKit着色器修改器 [英] SceneKit shader modifiers with GLSL arrays

查看:91
本文介绍了带有GLSL数组的SceneKit着色器修改器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将点数组传递到SceneKit中的着色器修改器中,但是我无法计算出正确的语法.在我的着色器扩展代码中,我有:

uniform vec2 points[100];

如果我打电话给我……

material.setValue(NSValue(point: CGPoint(x: 100.5, y: 50.5)), forKey: "points")

…然后设置points[0]的值,这使我认为这是不可能的.我已经尝试了很多其他组合来同时使用键和值,但是似乎没有任何效果.

是否有更好的方法可以做到这一点?我的最终目标是为数组中的一组点修改表面漫反射颜色,否则使用默认渲染.在着色器中,有没有比遍历vec2 s数组更好的方法了?

感谢您的帮助.

解决方案

shader数组变量只是从GL客户端传递到GPU的数据块,并且在shader代码中约定了一些大小和布局.

因此,要在SceneKit中执行此操作,您需要首先设置blob,然后将其包装在NSData中以传递给着色器.例如

// warning: coded in Safari and untested

import simd
let points: [float2] = [[100.5, 50.5], [110.5, 60.5], /* ... */ ]
// make sure you have 100...
let data = NSData(bytes: points, length: points.count * sizeof(float2))
material.setValue(data, forKey: "points")

此外,当您处理单点时,SceneKit将处理从CGPoint到GPU vec2的布局转换,但是当您传递数据块时,所有SceneKit都知道这是数据块. ..它无法查看内部并根据GPU的预期调整布局,因为它不知道您提供的布局是什么.

因此,您应该使用与GPU着色器中所需的大小和布局明确匹配的类型.这意味着没有CGPoint-它的组件是CGFloat,并且该类型的大小在CPU体系结构之间有所不同. SIMD库中的float2类型与GL vec2紧密匹配,而与金属float2完全匹配.

I'm trying to pass in an array of points into a shader modifier in SceneKit, but I can't work out the correct syntax. In my shader extension code I have:

uniform vec2 points[100];

If I call…

material.setValue(NSValue(point: CGPoint(x: 100.5, y: 50.5)), forKey: "points")

…then it sets the value of points[0], which makes me think that maybe it's not possible. I've tried lots of other combinations for both the key and the value, but nothing seems to work.

Is there a better way to do this? My end goal is to modify the surface diffuse colour for a set of points in the array, and use the default rendering otherwise. Is there a better way to do this in the shader than looping over an array of vec2s?

Thanks for your help.

解决方案

A shader array variable is just a blob of data passed from the GL client to the GPU, with some size and layout agreed upon in the shader code.

So, to do this in SceneKit, you'll need to first set up your blob, then wrap it in an NSData to pass to the shader. e.g.

// warning: coded in Safari and untested

import simd
let points: [float2] = [[100.5, 50.5], [110.5, 60.5], /* ... */ ]
// make sure you have 100...
let data = NSData(bytes: points, length: points.count * sizeof(float2))
material.setValue(data, forKey: "points")

Also, when you're working with single points, SceneKit will handle the layout conversion from CGPoint to GPU vec2, but when you pass a blob of data, all SceneKit knows is that it's a blob of data... it can't look inside and adjust the layout for what the GPU might expect, because it doesn't know what the layout you provided is.

So, you should use types that explicitly match the size and layout that you want in the GPU shader. That means no CGPoint—its components are CGFloat, and that type's size changes between CPU architectures. The float2 type from the SIMD library is a close match for GL vec2 and an exact match for Metal float2.

这篇关于带有GLSL数组的SceneKit着色器修改器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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