Почему мне нужно определить значение точности в шейдерах webgl?

Я пытаюсь получить этот учебник для работы, но я столкнулся с двумя проблемами, одним из которых является следующее.

Когда я запускаю код как есть, я получаю ошибку в шейдере фрагментов, говорящий: THREE.WebGLShader: gl.getShaderInfoLog() ERROR: 0:2: '' : No precision specified for (float). Так что я сделал, указав точность для каждого float/vector, который я определяю так varying highp vec3 vNormal. Это устраняет ошибку, но я не понимаю почему? Я не могу найти другого примера, в котором значения точности добавляются к объявлениям переменных. Может ли кто-нибудь объяснить, почему это происходит? Это имеет какое-то отношение к моему браузеру (Chrome 38)?

Ответ 1

Ответ Джесси правилен тем, что большинство фрагментарных шейдеров устанавливают точность по умолчанию в верхней части кода шейдера фрагмента.

Однако вы используете Three.js RawShaderMaterial, который не добавляет никаких встроенных форматов, атрибутов и объявлений точности. Поэтому вы должны сами определить его.

С другой стороны, учебник, с которым вы связались, использует для этого материал Three.js ShaderMaterial, поэтому у Three.js автоматически будет объявлено объявление точности.

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

Vertex Shader

varying vec3 vNormal;

void main() {
    vNormal = normal;
    gl_Position = projectionMatrix *
                modelViewMatrix *
                vec4(position,1.0);
}

Фрагментный шейдер

varying vec3 vNormal;

void main() {
    vec3 light = vec3(0.5, 0.2, 1.0);

    // ensure it normalized
    light = normalize(light);

    // calculate the dot product of
    // the light to the vertex normal
    float dProd = max(0.0, dot(vNormal, light));

    // feed into our frag colour
    gl_FragColor = vec4(dProd, // R
                        dProd, // G
                        dProd, // B
                        1.0);  // A
}

Обновить материал

// create the sphere material
var shaderMaterial = new THREE.ShaderMaterial({
    vertexShader:   document.getElementById('vertex-shader').innerHTML,
    fragmentShader: document.getElementById('fragment-shader').innerHTML
});

Здесь - скрипт вашего кода без деклараций точности.

Ответ 2

В шейдерах фрагментов WebGL отсутствует точность по умолчанию. (Высокая точность по умолчанию используется для вершинных шейдеров.) Самое простое решение - добавить

precision highp float;

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

precision mediump float;

будет предпочтительнее для производительности. Я не советую lowp; хорошее мобильное оборудование сегодня даже не поддерживает его, и делает эквивалент typedeffing lowp для mediump.