SceneKit: ошибка, отсутствует буфер [-1/2] при попытке передать униформу металлическому шейдеру.

Я прикрепил SCNProgram к геометрии SceneKit и пытаюсь передать униформу фрагментному шейдеру. В моем простом фрагменте кода я просто передаю выходной цвет фрагментному шейдеру как форму, который возвращает его как выходное значение.

Я уже тестировал шейдеры, и они работают в том смысле, что я могу успешно повернуть объект в вершинном шейдере или нарисовать объект другим цветом во фрагментном шейдере и т. Д., Но проблема в том, когда я передаю униформа. Это мой фрагментный шейдер:

struct Uniforms
{
    float4 color;
};


fragment float4 myFragment(MyVertexOutput in [[ stage_in ]],
                           constant Uniforms& uniforms [[buffer(2)]])
{
    return uniforms.color;
}

И вот как я пытаюсь передать униформу в моем коде SceneKit + Swift:

SCNTransaction.begin()
cube.geometry?.setValue(NSValue(SCNVector4:SCNVector4(0.0,1.0,0.0,1.0)), forKey: "uniforms.color")
SCNTransaction.commit()

Но мой объект (это куб) даже не нарисован (он черный), и я получаю такую ​​ошибку:

2016-04-01 01: 00: 34.485 Затененный куб [30266: 12687154] SceneKit: ошибка, отсутствует буфер [-1/0]

ИЗМЕНИТЬ. Я попытался последовать советам @lock, но все равно получаю ту же ошибку. Это полный репозиторий проекта: https://github.com/ramy89/Shaded-Cube.git < / а>


person Ramy Al Zuhouri    schedule 31.03.2016    source источник
comment
Привет, Рами, могу я написать тебе о потенциальном проекте? Не удалось найти ваш адрес электронной почты на странице GitHub. Спасибо!   -  person Crashalot    schedule 03.07.2016


Ответы (1)


Ваш шейдерный код выглядит нормально, и способ, которым вы передаете форму, близок к рабочему.

Имя формы шейдера должно соответствовать тому, что используется в setValue. В этом случае ваше имя переменной Metal - uniforms, а значение, которое вы используете в setValue, - uniforms.color. Они не совпадают, поэтому вы видите ошибку. Предложите изменить быстрый код, чтобы просто использовать uniforms в вызове setValue.

Затем вам нужно убедиться, что данные, передаваемые в качестве значения setValue, одинаковы как в Metal, так и в Swift. SCNVector4 - это структура из четырех 64-битных чисел с плавающей запятой (CGFloats), тогда как float4 Металла - это структура из четырех 32-битных чисел с плавающей запятой. Документация, похоже, указывает, что вы можете передать SCNVector как NSValue, но у меня никогда не получалось, чтобы он работал.

В вашем быстром коде я бы создал структуру, содержащую униформу, которую вы хотите передать. По структуре vector_float4 не так много документации, но она соответствует структуре Metal float4 в том смысле, что это четыре 32-битных числа с плавающей запятой.

struct Uniforms {
    var color:vector_float4
}

Передайте это в функцию setValue как NSData.

let myColor = vector_float4(0,1,0,1)
var myUniforms = Uniforms(color:myColor)
var myData = NSData(bytes:&myUniforms, length:sizeof(Uniforms))
cube.geometry?.setValue(myData, forKey: "uniforms")

Я не уверен, что вам нужны SCNTransaction вызовы, они мне не нужны в прошлом, и они могут быть дорогостоящими с точки зрения производительности.

обновить

После просмотра кода Рами кажется, что существует проблема с setValue и SCNPrograms при применении к геометрии. Я не могу сказать вам почему, но установка пользовательского шейдера для материала, похоже, исправляет это, например;

func makeShaders()
{
    let program = SCNProgram()
    program.vertexFunctionName = "myVertex"
    program.fragmentFunctionName = "myFragment"
    //cube.geometry?.program = program
    cube.geometry?.firstMaterial?.program = program

    var uniforms = Uniforms(color: vector_float4(0.0,1.0,0.0,1.0))
    let uniformsData = NSData(bytes: &uniforms, length: sizeof(Uniforms))
    //cube.geometry?.setValue(uniformsData, forKey: "uniforms")
    cube.geometry?.firstMaterial?.setValue(uniformsData, forKey: "uniforms")
}
person lock    schedule 02.04.2016
comment
Я все еще получаю ту же ошибку, я не знаю, что не так с моим кодом. Я создал репозиторий на github и добавил ссылку на свой вопрос. - person Ramy Al Zuhouri; 03.04.2016
comment
Я не думаю, что с вашим кодом @RamyAlZuhouri что-то не так, смотрите мое обновление выше. Похоже на ошибку SceneKit, наверное, стоит заполнить радар. - person lock; 04.04.2016