Как передать нетекстурные данные в шейдеры SCNTechnique Metal
Я могу передать пользовательский параметр типа sampler2D
к Metal fragment function
из SCNTechnique
и у меня есть рабочий 2-й проход:
Plist:
<key>inputs</key>
<dict>
<key>imageFromPass1</key>
<string>COLOR</string>
<key>myCustomImage</key>
<string>myCustomImage_sym</string>
</dict>
...
<key>symbols</key>
<dict>
<key>myCustomImage_sym</key>
<dict>
<key>type</key>
<string>sampler2D</string>
</dict>
</dict>
Соответствующий код Obj-C:
[technique setValue: UIImagePNGRepresentation(myCustomTexture) forKey:@"myCustomImage_sym"];
Металлические функциональные параметры:
fragment half4 myFS(out_vertex_t vert [[stage_in]],
texture2d<float, access::sample> imageFromPass1 [[texture(0)]],
texture2d<float, access::sample> myCustomImage [[texture(1)]],
constant SCNSceneBuffer& scn_frame [[buffer(0)]]) { ...
Я получаю доступ и использую все эти входы в функции шейдера. Оно работает!
Все идет нормально!
Тем не менее, когда я добавляю другой пользовательский параметр типа float
...
<key>blob_pos</key>
<string>blob_pos_sym</string>
...
<key>blob_pos_sym</key>
<dict>
<key>type</key>
<string>float</string>
</dict>
[_sceneView.technique setValue:[NSNumber numberWithFloat:0.5f] forKey:@"blob_pos_sym"];
constant float& blob_pos [[buffer(2)]]
... переданные значения никогда не достигают функции шейдера.
я пытался
- используя разные значения буфера (N) до 6
- имеющий пользовательский параметр в функции вершины
- введите vec3 и float3 вместо типа float
- различные способы кодирования моего float в NSData
оборачивая мой поплавок в структуру
[technique setValue:[NSValue valueWithSCNVector3: SCNVector3Make(0.5, 0.5, 0.5)] forKey:@"blob_pos_"]; SCNVector3 xx = SCNVector3Make(0.5, 0.5, 0.5); [technique setValue:[NSData dataWithBytes:&xx length:sizeof(xx)] forKey:@"blob_pos_"]; [technique setValue:[NSData dataWithBytesNoCopy:&xx length:sizeof(xx)] forKey:@"blob_pos_"]; simd_float3 x = simd_make_float3(0.5, 0.5, 0.5); [technique setValue:[NSData dataWithBytes:&x length:sizeof(x)] forKey:@"blob_pos_"]; float y = 0.5; [technique setValue:[NSData dataWithBytes:&y length:sizeof(y)] forKey:@"blob_pos_"]; struct MyStruct { float x; }; struct MyStruct myStruct = { 0.5 }; [technique setValue:[NSValue valueWithBytes:&myStruct objCType:@encode(struct MyStruct)] forKey:@"blob_pos_"]; [technique setObject:[NSValue valueWithBytes:&myStruct objCType:@encode(struct MyStruct)] forKeyedSubscript:@"blob_pos_"];
... и все это не удалось.
Затем я посмотрел на handleBindingOfSymbol: usingBlock:... но это только GLSL.
Я обнаружил, что это металлический аналог handleBindingOfBufferNamed:quency: usingBlock:... который недоступен в SCNTechnique.
Я гуглил SCNTechnique Metal... и понял, что во всех проектах используются только параметры sampler2D.
В конце концов я узнал, что это не ново, но ошибки разработчиков в течение многих лет.
Прежде чем я начну кодировать этот float в текстуре, дайте мне знать недостающий бит, чтобы заставить его работать так, как задумано.
1 ответ
Вы должны использовать структуру, чтобы обернуть ваши входные символы и обязательно использовать [SCNTechnique setObject:forKeyedSubscript:]
передать значения вашего символа в вашу технику. В документации для setObject: forKeyedSubscript: упоминается Metal, однако в нем не объясняется, как получить значение в функции Metal, что не очень хорошо.
Используя ваш пример:
Определение техники:
"inputs": [
"imageFromPass1": "COLOR",
"myCustomImage": "myCustomImage_sym",
"blob_pos": "blob_pos_sym",
],
...
"symbols": [
"myCustomImage_sym": ["type": "sampler2D"],
"blob_pos_sym": ["type": "float"]
]
Obj-C:
[_sceneView.technique setObject:[NSNumber numberWithFloat:0.5f] forKeyedSubscript:@"blob_pos_sym"];
Металл:
typedef struct {
float blob_pos; // Must be spelled exactly the same as in inputs dictionary.
} Inputs;
fragment half4 myFS(out_vertex_t vert [[stage_in]],
texture2d<float, access::sample> imageFromPass1 [[texture(0)]],
texture2d<float, access::sample> myCustomImage [[texture(1)]],
constant Inputs& myInputs [[buffer(0)]]) {
float blob_pos = myInputs.blob_pos;
...