В чем разница между vec3(1.,1.,1.) и (1.,1.,1.)

Мой код скомпилировался без ошибок, но не работал, пока я не добавил vec3 перед скобками. Содержимое было компонентами vec3, поэтому я бы предположил, что GLSL обрабатывает его как вектор или выдает мне ошибку, если не может, но просто принял его. Сообщение об ошибке (невозможно преобразовать из 3-компонентного вектора с плавающей точкой в ​​highp 3-компонентный вектор с плавающей запятой) появляется только в том случае, если я удаляю "-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.);
}

person Bradzzv    schedule 10.04.2019    source источник


Ответы (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). Это не приведение типов, поскольку скалярные операции над векторами определены как таковые, точно так же, как преобразование вектора матрицей не требует приведения одного к другому.

person LJᛃ    schedule 12.04.2019
comment
Спасибо, не могли бы вы уточнить список инструкций - разве инструкции не должны заканчиваться точкой с запятой? Эти списки широко используются? И во-вторых: не является ли 3.-vec3(0) неявным приведением типа float к vec3 - я думал, что GLSLES не поддерживает неявные преобразования типов. - person Bradzzv; 13.04.2019
comment
Теперь я понимаю, поэтому скаляр + вектор определяется как сложение компонентов в спецификации GLSL khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.3.30.pdf на странице 56 (связанный вопрос: stackoverflow.com/questions/14753158/glsl-vector-plus-scalar) - person Bradzzv; 14.04.2019