Почему необходимо установить точность для фрагментарного шейдера?
Я изучаю 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 не требует поддержки высокоточных типов с плавающей запятой в стадии шейдера фрагментов.
Язык фрагмента не имеет классификатора точности по умолчанию для типов с плавающей точкой. Следовательно, для 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 для вершинного шейдера, без точности по умолчанию для шейдера фрагментов.
Я думаю, что ключевая часть в этом: "Соглашения нет" . Похоже, они хотели определить точность по умолчанию, но разные продавцы не могли договориться о том, что это должно быть, и они были настолько заторможены, что в итоге они не определяли ее вообще.