Мой код скомпилировался без ошибок, но не работал, пока я не добавил vec3 перед скобками. Содержимое было компонентами vec3, поэтому я бы предположил, что GLSL обрабатывает его как вектор или выдает мне ошибку, если не может, но просто принял его. Сообщение об ошибке (не может преобразовать из float в highp 3-компонентный вектор float) появляется только в том случае, если я удаляю «-vec3 (0.)».
Итак, в чем смысл just (...) в GLSL и почему он молча принимается при вычитании vec3?
Примеры:
//this works:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy/iResolution.xy;
vec3 col = vec3(uv.x, uv.y, 0.)-vec3(0.);
fragColor = vec4(vec3(col), 1.);
}
.
//this doesn't:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy/iResolution.xy;
vec3 col = (uv.x, uv.y, 0.)-vec3(0.);
fragColor = vec4(vec3(col), 1.);
}
.
//this gives the helpful error message
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy/iResolution.xy;
vec3 col = (uv.x, uv.y, 0.);
fragColor = vec4(vec3(col), 1.);
}
Это относится не только к GLSL, но и ко многим языкам в стиле C.
vec3
является конструктором, такое выражение, как vec3(1,2,3)
, передает аргументы 1
2
и 3
, разделенные запятой, в функцию-конструктор, которая, в свою очередь, создает вектор с тремя компонентами, инициализированными заданными параметрами, и возвращает его.
В случае (1,2,3)
запятая действует не как разделитель, а как оператор, превращая его в список инструкций, в которых результат последней инструкции распространяется наружу, в данном конкретном случае 3
. Если бы вы написали (1,2,3) + 5
, результат был бы 8
. Вы можете прочитать больше об операторе запятой и некоторых распространенных случаях использования на википедия.
Теперь идет конкретная часть GLSL:
(1.,2.,3.)-vec3(0)
приводит к 3.-vec3(0)
, поскольку GLSL полностью посвящен векторной математике, это допустимая векторно-скалярная операция, в результате чего скалярная операция применяется к отдельным компонентам вектора. в этом случае это то же самое, что написать vec3(3.-0.,3.-0.,3.-0.)
. Другим примером может быть 5.*vec3(2,3,4)
, что приводит к vec3(2*5,3*5,4*5)
=> vec3(10,15,20)
. Это не приведение типов, поскольку скалярные операции над векторами определены как таковые, точно так же, как преобразование вектора матрицей не требует приведения одного к другому.
Теперь я понимаю, поэтому скаляр + вектор определяется как сложение компонентов в спецификации GLSL khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.3.30.pdf на странице 56 (связанный вопрос: stackoverflow.com/questions/14753158/glsl-вектор-плюс-скаляр)
Спасибо, не могли бы вы уточнить «Список инструкций» - разве инструкции не должны заканчиваться точкой с запятой? Эти списки широко используются? И во-вторых: не является ли 3.-vec3(0) неявным приведением типа float к vec3 - я думал, что GLSLES не поддерживает неявные преобразования типов.