Как работает смешивание с шейдерами фрагментов GLSL ES в WebGL?

#colors #glsl #webgl #alphablending #compositing

#Цвет #glsl #webgl #перевод букв #компоновка

Вопрос:

Я пытаюсь получить простой эффект для отображения с помощью WebGL. Естественно, это означает, что я использую язык шейдеров фрагментов, определенный в спецификации GLSL ES 1.0.

Код, с которым я работаю, в значительной степени скопирован из других источников. Он устанавливает квадрат и использует шейдеры фрагментов и вершин для определения цветов пикселей. Следующий код просто отобразит белый квадрат.

 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
  

Однако, если я изменю альфа-компонент на 1.0 , то вместо него будет отображаться черный квадрат.

 gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); // displays a black square
  

Я предполагаю, что цвет, который выводится шейдером фрагментов, должен быть объединен с каким-либо предыдущим цветом. Как мне убедиться, что в качестве отображаемого цвета фактически выбран только последний цвет (независимо от его альфа-значения)?

Или, возможно, у меня неправильный порядок. Возможно, существует более поздняя фаза, которая заключается в объединении с цветом из шейдера фрагментов для получения белого цвета. В любом случае, я знаю, что происходит какое-то смешивание, потому что, когда я меняю альфа-значение на 0.5, я получаю серый квадрат. Я просто хочу знать, откуда берется белый цвет? И как мне избавиться от этого?

Насколько я могу судить, проблема не связана с функцией смешивания. Код находится на GitHub здесь. Попробуйте это в Google Chrome или Firefox.

Комментарии:

1. @rockerest. Спасибо за дополнительные теги.

Ответ №1:

Белый цвет не получается ни при каких операциях смешивания WebGL. Это происходит потому, что элементы canvas DOM объединены с веб-страницей, на которой они находятся. Установка цвета фона элемента canvas DOM на черный устраняет проблему. Об этом явлении было написано здесь. Однако наиболее окончательный ответ содержится в спецификации WebGL. Поведение компоновки может быть определено путем установки различных атрибутов WebGLContextAttributes объекта. Цитирую спецификацию:

Необязательный объект WebGLContextAttributes может использоваться для изменения того, определены буферы или нет. Его также можно использовать для определения, будет ли цветовой буфер включать альфа-канал. Если задан, альфа-канал используется редактором HTML-компоновщика для объединения цветового буфера с остальной частью страницы.

Таким образом, альтернативным решением, которое не требует установки фона холста на черный, является запрос контекста WebGL со следующим кодом Javascript

 gl = canvas.getContext("experimental-webgl", { alpha: false } );
  

Комментарии:

1. Отлично! 1 за сохранение и детализацию этого. По иронии судьбы, в настоящее время я использую 2D canvas alpha для создания наложения для 3D canvas, но почему-то мне не приходило в голову, что альфа на 3D canvas также будет взаимодействовать с элементом DOM позади.

Ответ №2:

Было бы полезно, если бы вы опубликовали код, но очень похоже, что вы смешиваете цвет фрагмента с белым фоном.

Возможным виновником может быть некоторый код инициализации WebGL, который выглядит как:

     gl.clearColor(1.0, 1.0, 1.0, 1.0);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.enable(gl.BLEND);
  

который инициализирует прозрачный цвет цветового буфера белым и включает альфа-смешивание.

Итак, чтобы избавиться от вашей проблемы, просто не включайте смешивание. Другими словами, потеряйте gl.enable(gl.BLEND); инструкцию.

Обновление: Теперь, когда вы опубликовали свой код, похоже, ваша проблема противоположна тому, что я предполагал. Предполагая, что вы хотите, чтобы черный фон отображался в соответствии с установленным вами альфа-значением, вам следует заменить ваш gl.disable(gl.BLEND) на

     gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.enable(gl.BLEND);
  

Комментарии:

1. Я поддержал этот ответ, поскольку он пока лучший. Но, похоже, проблема не в этом. Я разместил свой код на GitHub здесь . Большая часть кода даже не моя, но вы можете видеть, что я отключил смешивание, и у меня все еще возникает проблема. Просто откройте test.html в Google Chrome, чтобы увидеть проблему.

2. @Sean Нет, ответ rockerest на данный момент лучший, поскольку он точно объясняет, что происходит!

3. @brainjam. Я попытался добавить эти две строки, и я получаю еще более темный серый квадрат, который заставляет меня думать, что происходит два смешивания. Мой главный вопрос заключается в том, «откуда берется белый». Нигде в коде я не указываю, что что-либо должно быть белым.

4. @Sean, на этом этапе вы смешиваете на черном фоне. В уравнении смешивания больше не должно быть белого цвета. Похоже, что когда смешивание не включено (что было ранее), по умолчанию используется смешивание с белым цветом. Но теперь, когда вы включили смешивание, оно должно быть «истинным» на фоне. Попробуйте поиграть с инструкцией clearColor() и используйте цвета, отличные от (0.0,0.0, 0.0), и посмотрите, как работает смешивание. Надеюсь, это поможет. Я предполагаю, что если вы используете alpha, вы действительно хотите, чтобы произошло некоторое смешивание.

5. @brainjam. Я выяснил, в чем была проблема. Большое вам спасибо за то, что подтолкнули меня к поиску окончательного ответа.

Ответ №3:

Я ничего не знаю об этой теме (glsl, webgl и т.д.), Но вы сказали, alpha что заставляет меня думать, что это значение RGBA. Итак, a 0.0, 0.0, 0.0, 0.0 черный, с альфа-покрытием 0.0. Другими словами, полностью прозрачно.

0.0, 0.0, 0.0, 1.0 черный с альфа-покрытием 1.0. Другими словами, полностью непрозрачный. Похоже, что результат на 100% правильный.

Позвольте мне уточнить, на всякий случай, если вышесказанное было непонятным (мне это показалось запутанным).

Последнее число просто влияет на прозрачность цвета, первые три числа влияют на красный, зеленый и синий соответственно.

Я не уверен в их максимальных / минимальных значениях, но в веб-браузерах (моя область знаний) цвета варьируются от 0 до 255. Где 0 — это ни один из этих цветов, а 255 — весь этот цвет.

Итак, в вашем случае вы запрашиваете квадрат с 0 красными, 0 зелеными и 0 синими (который является просто черным). Однако, когда вы устанавливаете прозрачность (альфа-канал) равной нулю, он отображается белым (или, что более вероятно, прозрачным, и все, что за ним, является белым). Когда вы устанавливаете альфа-прозрачность на .5, она становится черной (как и должно быть 0,0,0), но видна только половина. Когда вы устанавливаете альфа-прозрачность на 1.0, получается полностью непрозрачный черный квадрат.

Имеет смысл?

Комментарии:

1. Спасибо за очень четкое объяснение, но, к сожалению, я уже знаком с основами RGBA. Это очень конкретный вопрос о том, как работает графический конвейер в программе WebGL, использующей GLSL. Я понимаю, что я устанавливаю альфа-канал моего цвета равным 0.0, что означает, что если он будет смешан с каким-либо другим цветом, это ничего не даст. Я просто хочу знать, с чем это смешивается в моей программе WebGL. Я просто не знаю!

2. @Sean Это, вероятно, смешивается с вашим белым фоном. И я предполагаю, что конвейер WebGL работает точно так же, как конвейер desktop GL (возможно, с некоторыми ограничениями, но они не будут применяться к вашему случаю).

3. @Christian Rau. Вы были правы, он был смешан с белым фоном. Когда я впервые прочитал ваш комментарий, я не понял, что вы имели в виду фон холста.

4. Отклоните ответ, в котором успешно перечисляется проблема («прозрачный, и то, что за ним, белое»), и более года спустя. Я часто поражаюсь людям.