Стандартные производные от фрагментного шейдера (dFdx, dFdy), не работают корректно в Android 4.4
Я использую шейдер фрагментов, который использует функции dFdy dFdx для вычисления нормали
лицо для просмотра в плоском виде. Этот шейдер работает нормально в gles 2.0 и 3.0. Необъяснимо, шейдер не работает на Андроид 4.4 ( KitKat - gles3.0 ).
(решено!!.. отдельные производные для каждого компонента решают задачу).
Чтобы проверить ошибку, я подготовил следующие шейдеры:
//Vertex Shader
#version 300 es
precision highp float;
precision highp int;
uniform mat4 PMatrix; //Projection Matrix (varies according to camera)
uniform mat4 MVMatrix; //Model View Matrix (no change)
in vec3 vPosition;
out vec3 vPos;
main()
{
gl_Position=PMatrix * MVMatrix * vec4(vPosition.xyz,1.0);
vPos = (MVMatrix * vec4(vPosition.xyz,1.0)).xyz;
}
// Fragment shader
#version 300 es
#extension GL_OES_standard_derivatives : enable
precision highp float;
precision highp int;
in vec3 vPos;
main()
{
// don't run correctly
// vec3 fdx = dFdx(vPos);
// vec3 fdy = dFdy(vPos);
// ***Solved!*** this run correctly in KitKat
vec3 fdx = vec3(dFdx(vPos.x),dFdx(vPos.y),dFdx(vPos.z));
vec3 fdy = vec3(dFdy(vPos.x),dFdy(vPos.y),dFdy(vPos.z));
vec3 N = normalize(cross(fdx,fdy));
fragColor = vec4(N,1.0);
}
Рисование Куба, В Android
Анализ каждого производного отдельно:
1.- fragColor=vec4(normalize( fdx ), 1.0); цвета постоянно меняются (неправильно)
2.- fragColor=vec4(normalize( fdy ), 1.0); цвета остаются квазистабильными (квази-ОК)
Ошибка в реализации этих функций в Android 4.4?
Мы делаем что-то не так?
3 ответов:
Отдельные производные в каждом компоненте решают задачу в KitKat:
// Replace vec3 fdx = dFdx(vPos) by: vec3 fdx = vec3(dFdx(vPos.x),dFdx(vPos.y),dFdx(vPos.z)); // Replace vec3 fdy = dFdy(vPos) by: vec3 fdy = vec3(dFdy(vPos.x),dFdy(vPos.y),dFdy(vPos.z));
Вы сказали, что изначально это был шейдер GLES2, и вы используете
highpв шейдере фрагментов безоговорочно? Это катастрофа, ожидающая своего часа, потому что реализации GLES2 не требуются для поддержкиhighpв шейдерах фрагментов. Аналогичным образом, поддержка дляdFdx (...),dFdy (...)иfwidth (...)является необязательным.Необходимо проверить наличие
GL_OES_standard_derivativesиGL_FRAGMENT_PRECISION_HIGHв реализации GLES2 этого фрагмента шейдера.С этой целью вы можете рассмотреть подсказку точности для производных:
GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES(GLES2, если расширение поддерживается)GL_FRAGMENT_SHADER_DERIVATIVE_HINT(GLES3)
Я видел подобные вещи на некоторых настольных компьютерах AMD.
Где dFdy( .xyz) отлично работал на NVIDIA / intel, мне пришлось сделать дериват для каждого компонента, чтобы получить его правильно для некоторых карт AMD.
Comments