Резюме: я получаю замедление FPS, как только я пытаюсь тонировать спрайты (то есть: умножить текстуру на цвет в фрагментном шейдере)
Подробности:
Аппаратное обеспечение: iPod touch 4
Я рисую 700 спрайтов на экране, используя glDrawArrays. И да, я собираю все это в один розыгрыш. Ниже показана структура данных Vertex:
struct Vertex {
float Position[2];
float Color[4];
float Texture[2];
};
Да, я посылаю цвет каждой вершине, потому что мне нужно выборочно окрашивать некоторые спрайты, но не другие. Вот фрагментный шейдер, который я использую:
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;
void main(void)
{
gl_FragColor = texture2D( TextureSampler, TexCoord );
}
До сих пор он работает БОЛЬШОЙ, давая мне полный 60 FPS !!!
НО
Как только я изменю фрагментный шейдер на следующий (чтобы разрешить тонирование):
varying lowp vec4 DestinationColor;
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;
void main(void)
{
gl_FragColor = texture2D( TextureSampler, TexCoord ) * DestinationColor;
}
Используя следующую 64x64 png текстуру, содержащую альфа-канал, рендеринг с glEnable (GL_BLEND):
Производительность падает до 47 FPS только из-за этого единственного изменения {просто умножением на ОДИН вектор}} (FPS измеряется с использованием инструментов xcode и детектива OpenGL). Есть идеи, что происходит?
Спасибо.
Редактировать:
Я также попытался удалить цвет каждого атрибута вершины:
struct Vertex {
float Position[2];
float Texture[2];
};
И модифицируем фрагмент шейдера следующим образом:
precision lowp float;
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;
void main(void)
{
gl_FragColor = texture2D( TextureSampler, TexCoord ) * vec4(1.0,0.0,0.0,1.0);
}
Он работает на скорости 52 FPS для 700 спрайтов (усиление всего 5 FPS). Так что это не интерполяция, кажется, что умножение очень дорого. Только это ОДНО умножение?
Ответы:
Я не думаю , что проблема производительности происходит на умножении, а на интерполяцию из ваших
DestinationColor
через треугольники, между вершиной и фрагментарными шейдерами. У вас есть четыреfloat
секунды для интерполяции между вершинами дерева, для каждого фрагмента для каждого спрайта.Для 700 спрайтов размером 64x64 пикселя это 11468800 дополнительных операций на кадр, которые вы запрашиваете для графического процессора. Вполне возможно, что вам будет не хватать некоторых vsyncs, и, следовательно, падение до 40-ти кадровых FPS.
Если вы хотите, чтобы у каждой вершины был свой цвет, чтобы вы могли иметь градиенты для каждого спрайта, вам не повезло. Есть также некоторые другие уловки, которые вы можете попробовать, но я думаю, что это не так.
Поскольку то, что вы, похоже, делаете, это подкрашивание каждого спрайта, вы можете понизить свой уровень
DestinationColor
до auniform
, использовать его непосредственно в фрагментном шейдере и изменять его для каждого вызова. Таким образом, никакой интерполяции не будет. Вы потеряете всю партию, но, возможно, сможете немного дозировать, если отсортируете их по цвету.источник