Сглаживание в фрагментном шейдере Three js

Я пишу небольшой шейдер, который генерирует конический градиент в Three.js. Все работает хорошо. Я удалил полосы, добавив немного шума, поэтому в целом градиент выглядит хорошо. У меня только проблема в том, что на краю двух градиентных цветов я получаю некрасивое сглаживание. См. Изображение

проблема с псевдонимом

Затем я попытался сгладить края в моем фрагментном шейдере, который работает хорошо, но не внутри градиента.

лучше

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

В общем, я не являюсь экспертом в написании шейдеров или three.js, так что, возможно, у вас есть какой-то вклад, чтобы решить эту проблему элегантным способом.

Спасибо за вашу помощь, вот скрипка и код шейдера фрагментации.

Пример скрипта JS

<script id="fragmentShader" type="x-shader/x-fragment">
        uniform vec4 colour1;
        uniform vec4 colour2;
        uniform sampler2D texture;
        varying vec3 vUv;

        void main() {
            precision highp float;

            //get Angle for textureCoordinate
            float angleDeg = atan(vUv.y - 0.5,vUv.x - 0.5) * 180.0 / 3.147;
            if (angleDeg < 0.0){
                angleDeg = angleDeg+360.0 ;
            }

            //Generate Gradient
            float lerpValue = angleDeg/360.0;
            vec4 colour = mix(colour1,colour2,lerpValue);

            //My approach to smooth the edge works well on the outside but
            //not on the inside
            if(lerpValue>0.9995){
                float smoot = 1.0-lerpValue;
                smoot = smoot*2000.00;
                vec4 lerpColor = mix(colour1,colour2,0.9995);
                colour = mix(colour1,lerpColor,smoot);

            }
            ///done with gradient 

            //apply noise from noise texture to eliminate banding
            vec2 textureCoord = vUv.xy;
            vec4 noise = texture2D(texture,textureCoord.xy);
            colour.xyz += mix(-0.05, 0.05, noise.x);
            gl_FragColor = colour;

        }
    </script>

person Robi_h    schedule 03.05.2017    source источник
comment
Убранная скрипка: jsfiddle.net/vabz67L5/2   -  person WestLangley    schedule 03.05.2017


Ответы (1)


Во-первых, вам нужен более точный способ вычисления сглаживания. Уравнение, поддерживающее любое значение lerpLimit (ваше магическое значение 0,9995)

    //Generate Gradient
    float lerpValue = angleDeg/360.0;

    float lerpLimit = 0.9995;
    float invDiff = lerpLimit/(1.0-lerpLimit);

    if(lerpValue>lerpLimit){
      lerpValue = invDiff - lerpValue*invDiff;
    }

    vec4 colour = mix(colour1,colour2,lerpValue);

    //My approach to smooth the edge works well on the outside but
    //not on the inside
    // ....

Теперь вы можете модулировать lerpLimit на основе расстояния пиксель / центр, чтобы иметь градиент сглаживания постоянной толщины.

    //Generate Gradient
    float lerpValue = angleDeg/360.0;

    // the constant thickness of the antialias gradient
    // along the seam
    float limit = .02;

    float lerpLimit = 1.0 - limit / (6.283185*length(vUv.xy - 0.5));

    // avoid negative limit at the center 
    lerpLimit = max( lerpLimit, 0.0 );

    float invDiff = lerpLimit/(1.0-lerpLimit);

    if(lerpValue>lerpLimit){
      lerpValue = invDiff - lerpValue*invDiff;
            }

    vec4 colour = mix(colour1,colour2,lerpValue);

    //My approach to smooth the edge works well on the outside but
person pleup    schedule 03.05.2017
comment
Привет, действительно хорошее решение. Я работал над увеличением длины, но так и не получил нужного результата. Спасибо за решение и хорошее объяснение! - person Robi_h; 03.05.2017