Цвет с использованием альфа-смешивания различен на разных телефонах Android с OpenGL-ES - PullRequest
1 голос
/ 04 июня 2019

У меня проблема с Android с OpenGL ES 3.1. Я написал приложение, которое показывает жидкость, падающую с верхней части экрана. Эта жидкость состоит из множества прозрачных частиц, но цвет с использованием альфа-смешения по-другому отображается на другом телефоне.

Цвет каждой капли определяется следующим образом:

private int particleColor = Color.argb(50, 0, 172, 231);

Каждый цвет частиц хранится в буфере:

private ByteBuffer colorBuffer = ByteBuffer.allocateDirect(MAX_PARTICLES * PARTICLE_COLOR_COUNT).order(ByteOrder.nativeOrder());

И этот буфер передается объекту OpenGL для рисования:

/**
* Binds the data to OpenGL.
* @param program as the program used for the binding.
* @param positionBuffer as the position buffer.
* @param colorBuffer as the color buffer.
*/
public void bindData(LiquidShaderProgram program, ByteBuffer positionBuffer, ByteBuffer colorBuffer){

glVertexAttribPointer(program.getPositionAttributeLocation(), POSITION_COMPONENT_COUNT, GL_FLOAT, false, POSITION_COMPONENT_COUNT * OpenGLUtils.BYTE_PER_FLOAT, positionBuffer);

glEnableVertexAttribArray(program.getPositionAttributeLocation());
glVertexAttribPointer(program.getColorAttributeLocation(), COLOR_COMPONENT_COUNT, GL_UNSIGNED_BYTE, true, COLOR_COMPONENT_COUNT, colorBuffer);

glEnableVertexAttribArray(program.getColorAttributeLocation());
}

Визуализация прекращается при вызове этой функции:

/**
* Render the liquid.
* @param particleCount as the particle count.
*/
public void draw(int particleCount) {
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glDrawArrays(GL_POINTS, 0, particleCount);
  glDisable(GL_BLEND);
}

Фрагмент шейдера просто нарисуйте цвет, который он получает:

precision mediump float;

varying vec4 v_Color;

void main() {
  if (length(gl_PointCoord - vec2(0.5)) > 0.5) {
    discard;
  } else {
    gl_FragColor = v_Color;
  }
}

Очень хорошо работает на одном телефоне (Nexus 5X): Correct rendering

Но на другом телефоне (Galaxy S10), с точно таким же кодом, цвет не тот же: Incorrect rendering

Кто-нибудь имеет представление о способе решения этой проблемы? Я хотел бы также отобразить правильный цвет на втором телефоне.

1 Ответ

0 голосов
/ 05 июня 2019

Я, наконец, понял проблему и нашел решение, прочитав много документации и просматривая веб-страницы в течение многих часов.

Похоже, в Android предварительное умножение альфа-канала управляется платформой, в то время как OpenGL и нативный код должны управлять им вручную (я до сих пор не понимаю, почему это работало правильно на некоторых телефонах, а не на других телефонах). Но после изменения функции наложения и выполнения предварительного умножения альфа в фрагментном шейдере проблема была исправлена.

Правильная функция наложения следующая:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

Используя эту функцию, убедитесь, что цвета одинаковы на всех телефонах, но этого недостаточно, потому что цвета не правильные. Чтобы сделать его идеальным, в шейдерном фрагменте необходимо выполнить предварительное умножение альфа:

gl_FragColor = vec4(v_Color.x * v_Color.w, v_Color.y * v_Color.w, v_Color.z * v_Color.w, v_Color.w);

После этого я смог отобразить правильные цвета на всех телефонах.

Это мое понимание проблемы и решение, которое я нашел. Если у кого-то есть лучшее объяснение, я был бы рад услышать это, иначе я надеюсь, что это кому-то поможет.

...