Неточная точность шейдера на Android по сравнению с webgl

Я пытаюсь сделать симплексный шум на Android на основе этого примера:

https://github.com/ashima/webgl-noise/blob/master/src/noise2D.glsl

После преобразования кода и его компиляции на устройстве я понял, что закономерность далеко не случайна. Я разбил код на самую основную часть, в которой я все еще вижу большую разницу между десктопом (я тестировал их на http://glslsandbox.com/e) и мобильных устройств, и у меня есть это.

#ifdef GL_ES
precision mediump float;
#endif

#extension GL_OES_standard_derivatives : enable

uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;

float u_time = time;
vec2 u_resolution = resolution;

vec3 mod289(vec3 x) { 
    vec3 t = x * 0.00346020761;
    t = floor(t);
    t = t * 289.0;

    return x - t;

    //return x - floor(x * (1.0 / 289.0)) * 289.0; 
}

vec3 permute(vec3 x) { 
    vec3 t = x * 34.0;
    t = t + 1.0;
    t = t * x;
    return mod289(t);

    //return mod289(((x*34.0)+1.0)*x); 
}


void main( void ) {

    vec2 p = vec2( (gl_FragCoord.xy / u_resolution.xx - 0.5) * 2.0);

    vec3 value = permute( p.xyx * 10000.0 + u_time * 0.1);

    gl_FragColor = vec4(value, 1.0);
    //gl_FragColor = vec4(p + 1.0, 0.0, 1.0);
}

Цель разделения их на строки заключается в том, что я уже сталкивался с подобными ошибками ранее. Фрагментный шейдер GLSL ES дает очень разные результаты на разных устройствах. устройства

На устройстве этот код (#ifdef и #extension удалены, а юниформ-переменные установлены правильно) создает белый экран. (Проверено на нескольких устройствах с использованием #version 300 es, а также с использованием более старой версии шейдера, всегда один и тот же результат.)

Эта ошибка вызвана неточностью floor()?

Или есть способ генерировать симплексный шум без этих функций mod289? (2D-шум работал нормально)


person andras    schedule 14.12.2016    source источник


Ответы (1)


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

Если вы установите precision highp float, это будет работать лучше? Это вызовет вычисление с плавающей запятой fp32.

Однако обратите внимание, что не все мобильные устройства поддерживают highp — он стал обязательным только в OpenGL ES 3.x и выше, поэтому некоторые графические процессоры OpenGL ES 2.x поддерживают только вычисления fp16.

(На каком устройстве вы работаете?)

person solidpixel    schedule 14.12.2016
comment
Я тестировал highp только на нижнем устройстве, это ARM Mali-400 MP2 (двухъядерный). Лучший с Adreno 305, который поддерживает es 3.0, также поддерживает highp, что решило мою проблему. Обратите внимание, что для всех, у кого есть эта проблема, вы можете проверить поддержку точности: es-2-0-for-iphone-ipod-touch-ipad" title="какова точность highp поплавков в glsl es 2 0 для iphone ipod touch ipad"> stackoverflow.com/questions/4414041/ glGetShaderPrecisionFormat возвращает нули, если highp не поддерживается. - person andras; 14.12.2016
comment
Серия Mali-400 предназначена только для OpenGL ES 2.x и не поддерживает fp32, поэтому в этом случае вы просто получите fp16. - person solidpixel; 15.12.2016