Почему необходимо установить точность для фрагментарного шейдера?

Я изучаю WebGL. Следующие шейдеры работают нормально:

// vertex.shader
// precision mediump float;
attribute vec4 a_Position;
attribute float a_PointSize;

void main(){
  gl_Position = a_Position;
  gl_PointSize = a_PointSize;
}

и

// fragment.shader
precision mediump float;
uniform vec4 u_FragColor;

void main(){
  gl_FragColor = u_FragColor;
}

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

Я читал этот раньше, но мне это не помогло.

Ответ 1

Нет точности по умолчанию для типов fp в шейдерах фрагментов в OpenGL ES 2.0.

В вершинных шейдерах, если вы явно не задали точность по умолчанию для типов с плавающей запятой, по умолчанию она имеет значение highp. Однако, если шейдер фрагмента по умолчанию был равен highp, это вызовет проблемы, поскольку OpenGL ES 2.0 не требует поддержки высокоточных типов с плавающей запятой в стадии шейдера фрагментов.

OpenGL ES Shading Language - 4. Переменные и типы - pp. 35-36

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

4.5.4 Доступные квалификаторы точности

Встроенный макрос GL_FRAGMENT_PRECISION_HIGH определяется как один для систем, поддерживающих точность highp в языке фрагментов

     

#define GL_FRAGMENT_PRECISION_HIGH 1

     

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

Ответ 2

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

Я всегда думал, что это было странно, что не было дефолта. Все остальное имеет точность по умолчанию. Значение по умолчанию не может быть highp, так как это не гарантируется в наличии в шейдерах фрагментов. Но я не вижу веских причин, по которым он не может быть mediump по умолчанию. mediump является значением по умолчанию для int, и это может быть так же хорошо для float.

Объяснение становится достаточно понятным в разделе 10 ( "Проблемы" ) спецификации. В этом разделе содержатся различные вопросы, которые были открыты во время обсуждения спецификации, и затем был дан ответ. Часто бывает некоторое объяснение с рассуждением, почему был выбран ответ.

В частности, "10.3 Precision Qualifiers" справляются с этим. Один из вопросов и ответов (стр. 85):

Должна ли быть точность по умолчанию? Было бы целесообразно указать точность вершин по умолчанию как highp, как то, что указано в настоящее время. Не существует соглашения о том, какой должна быть точность по умолчанию для стороны фрагмента.

РАЗРЕШЕНИЕ: highp для вершинного шейдера, без точности по умолчанию для шейдера фрагментов.

Я думаю, что ключевая часть в этом: "Соглашения нет" . Похоже, они хотели определить точность по умолчанию, но разные продавцы не могли договориться о том, что это должно быть, и они были настолько заторможены, что в итоге они не определяли ее вообще.