Текстурный массив в металле - PullRequest
0 голосов
/ 17 января 2019
fragment half4 fragmen_shader_test(WaterColorCloudOut params[[stage_in]],
                                                         texture2d<float , access::sample>cloud1 [[texture(0)]],
                                                         texture2d<half, access::sample> cloud2 [[texture(1)]],
                                                         texture2d<half, access::sample> cloud3 [[texture(2)]]
                                                         )
{
    constexpr sampler defaultSampler;
    float4 color1;

    if(params.index == 0){
        color1= float4(cloud1.sample(defaultSampler, float2(params.textureCoordinates)))  * params.color ;
    }
    else if(params.index == 1){
        color1= float4(cloud2.sample(defaultSampler, float2(params.textureCoordinates)))  * params.color ;
    } else{
        color1= float4(cloud3.sample(defaultSampler, float2(params.textureCoordinates)))  * params.color ;
    }

 return half4(color1);
}

Здесь я использую три текстуры из-за условия If-else, производительность падает со временем. Я чувствую, если я отправляю массив текстур в шейдер, нет необходимости выполнять оператор if else. В CPU у меня три MTLTexture. Как я могу связать три текстуры с массивом и передать его шейдеру.

На стороне процессора я создал три текстуры и создал массив MTLTexture

 var textureArray:[MTLTexture] = [] 

Затем я добавляю текстуру к этому массиву. В MTLRenderCommandEncoder

let myRange: CountableRange = 0..<2
commandEncoder.setFragmentTextures(textureArray, range: myRange)

В шейдере

texture2d_array<float ,  access::sample> texture [[ texture(0) ]]

При сэмплировании в шейдере

float4 color = texture.sample(defaultSampler, float2(params.textureCoordinates),0) * float4(1,0,0,1.0);

Я сейчас так делаю, но не могу получить правильный вывод текстуры

1 Ответ

0 голосов
/ 17 января 2019

Вам не нужно менять код приложения. Поскольку вы используете последовательные индексы текстур, вы можете просто заменить три отдельных параметра одним параметром массива текстур, привязанным к индексу 0, и привязки свяжут элементы массива с текстурами, которые вы предоставили из кода приложения.

Другими словами, если вы объявляете массив текстур с размером 3 и привязанным к индексу текстуры 0, элементы массива берутся из индексов текстуры 0, 1 и 2.


Обновление для вашего отредактированного вопроса:

Вы путаете массив из текстур (также называемый массивом текстур) и текстуру массива. Терминология запутанно тонкая.

  • Текстура массива - это отдельная текстура с несколькими 2D-плоскостями. Все плоскости имеют одинаковый размер и формат пикселей. Число плоскостей в текстуре не нужно знать во время компиляции шейдера.
  • Массив текстур - это массив независимых текстур, которые могут иметь разные размеры или форматы пикселей. Длина массива является константой времени компиляции.

Вы использовали texture2d_array<...>. Это текстура массива.

Для массива текстур или массив текстур, вы должны использовать array<texture2d<float, access::sample>, 3> clouds [[texture(0)]].

Для выборки из текстуры в массиве вы сначала индексируете массив, а затем вызываете функцию текстуры для этого элемента:

float4 color = clouds[params.index].sample(defaultSampler, float2(params.textureCoordinates)) * float4(1,0,0,1.0);
...