Коротко: шейдер не работает, но если в конец шейдера добавить glFragColor.a += 0.001 то он внезапно работает (почти) правильно.
Причём вот так не работает:
uniform vec3 u_color; ... float a = ...; vec4 v = vec4( u_color, a + 0.0001 ); gl_FragColor = v;
А так - работает:
vec4 v = vec4( u_color, a ); gl_FragColor = v; gl_FragColor.a += 0.0001;
Но это не все проблемы.
upd.: Вторая проблема уже решена, в коде где-то был вызов glDrawArrays с параметром count=0, из-за этого устройство Эппл немножко тупит. Убрал вызов, глюки прекратились. О второй проблеме:
При первом запуске рисуемый меш мелькает в разных частях экрана (цвет правильный, но в позициях вершин как будто мусор), в процессе работы рисуется другой меш (корректно), а потом снова первый (теперь уже корректно). И проблемы исчезает. Выглядит как что-то нециниализированное, но нет, всё инициализировано.
Стабильно воспроизводится только на айфоне и айпаде. ПК и разные Андроиды работают без проблем. Без += 0.0001 вообще ничего не отрисовывается, как будто полная прозрачность.
Ошибок и предупреждений при компиляции шейдера нет.
glGetError() пустой.
#version 100, пробовал и без версии.
Вот как такое ловить?
Полный код шейдеров. VS:
#ifdef GL_ES
precision mediump float;
#endif
uniform mat4 u_proj;
uniform vec4 u_pos_modif;
attribute vec4 a_pos;
attribute vec4 a_uv;
varying vec4 v_uv;
void main() {
gl_Position = ( a_pos + vec4(u_pos_modif.x, u_pos_modif.y, 0.0, 0.0) );
gl_Position = u_proj * gl_Position;
gl_Position = gl_Position * vec4( u_pos_modif.z, u_pos_modif.z, 1.0, 1.0 ); /* scale */
v_uv = a_uv;
}FS:
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D u_sampler;
varying vec4 v_uv;
uniform vec4 u_pos_modif;
uniform vec3 u_color;
void main() {
float a = texture2D(u_sampler, v_uv.st ).r * u_pos_modif.a;
vec4 v = vec4( u_color, a );
gl_FragColor = v;
gl_FragColor.a += 0.0001;
}впиши в outcolor.a единицу вот и все.
сдается что у тебя там ноль на выходе
barnes
Там не ноль, там данные с текстуры. Данные правильные, т.к. прибавление 0.0001 их почти не изменяет, а визуально видно, что они корректные.
я думаю стоит искать ошибку не в шейдере
вот вот, в альфу явно что-то не то падает
По поводу второй проблемы (мусор на экране) - обнаружил, что где-то вызывается glDrawArrays() с count=0. Если этот вызов убрать, то мусор пропадает. Можно сделать предварительный вывод, что именно glDrawArrays() с count=0 вызывает эти проблемы.
А странное поведение шейдера победить еще не удалось.
> вот вот, в альфу явно что-то не то падает
Как в неё может попадать не то, если прибавления 0.0001 я вижу правильную картинку? Ну, то есть, возможно где-то сработала неправильная оптимизация и без последней строчки в альфу каким-то образом попадает ноль. Вопрос - каким.
Роман Шувалов
используй glBlendFunc(GL_ONE, GL_ZERO), чтобы посмотреть, какой цвет действительно выдаёт шейдер, не учитывая блендинг.
Suslik
Попробовал. Цвет правильный (вижу тот, что указан в u_color).
Как будто "оптимизация" устанавливает альфу в 0.
А теперь почувствуйте силу магии.
Не работает:
gl_FragColor = vec4( u_color, a );
Не работает:
gl_FragColor = vec4( u_color, a + 0.0 );
Работает:
gl_FragColor = vec4( u_color, a ) + vec4(0.0, 0.0, 0.0, 0.0);
(?!)
По поводу проблемы вроде ничего сразу на ум не приходит, а вот организация данных у тебя стремная.
Во первых: зачем ты хранишь альфу в u_pos_modif, а не в u_color? Тогда можно было бы сделать вот так:
gl_FragColor = u_color; gl_FragColor.w *= texture2D(u_sampler, v_uv.st).x;
Во вторых, сделай v_uv vec2, зачем тебе еще и swizzle делать, если zw не используется (плюс, при mediump может немного медленнее работать, чем при highp).
Попробуй засунуть шейдер в PVRShaderEditor, и посмотреть во что превращается шейдер в разных вариантах.
Sergio
> Во первых: зачем ты хранишь альфу в u_pos_modif,
Потому что цвет выставляется 1 раз перед вызовом нескольких DrawCall'ов, а альфа вместе с другими компонентами pos_modif выставляется для каждого DrawCall'а индивидуально. Но в шейдере, конечно, было бы удобнее делать как ты сказал. Но тогда оба юниформ-вектора придется перед каждым DrawCall'ом устанавливать, с одними и теми же RGB компонентами каждый раз.
Sergio
> Во вторых, сделай v_uv vec2,
Да, это я уже заметил и сделал. Свиззла больше нет. ZW когда-то использовались для отладки, поэтому и был изначально vec4.
Sergio
> плюс, при mediump может немного медленнее работать, чем при highp
Серьезно? Я как-то проводил испытания. lowp тормозучий как слон. Разницу между mediump и highp точно не помню, но, кажется, highp работала медленнее на некоторых устройствах. Могу ошибаться. Возможна ли ситуация, чтобы highp работало медленнее, чем mediump? Речь сейчас не только про айфоны.
Роман Шувалов
> Возможна ли ситуация, чтобы highp работало медленнее, чем mediump? Речь сейчас
> не только про айфоны.
Да, возможно. Но swizzle на нем всегда работает быстрее
> засунуть шейдер в PVRShaderEditor
Я смотрю он для винды и с собственным компилятором, от него будет толк?
Уже прочитал
Supports PowerVR Series5, Series5XT and Series6 offline GLSL ES compilers
Посмотрим-с.
Коду, кстати, уже много лет, он был использован в нескольких проектах, в т.ч. в конкурсных. И тут внезапно на iOS вот такая хрень.
> Да, возможно. Но swizzle на нем всегда работает быстрее
Тогда от греха подальше избавлюсь от swizzle и оставлю mediump.
Не передаешь ли ты в альфу какой-нибудь nan или inf?
Тема в архиве.