【问题标题】:Alpha channel fade animationAlpha 通道淡入淡出动画
【发布时间】:2019-01-10 21:27:04
【问题描述】:

我对着色器很陌生,我一直在尝试创建一个着色器,可以对纹理进行 alpha 渲染,我已经接近了,但我很确定有更好的方法。

这就是我要远远的https://codepen.io/tkmoney/pen/REYrpV

varying vec2 vUv;
        precision highp float;
        precision highp int;
        uniform sampler2D texture;
        uniform float mask_position;
        uniform float fade_size;


        void main(void) {
            float mask_starting_point = (0.0 - fade_size);
            float mask_ending_point = (1.0 - fade_size);

            vec4 orig_color = texture2D(texture, vUv);

            vec4 color = texture2D(texture, vUv);

            float mask_p = smoothstep(mask_starting_point, mask_ending_point, mask_position);

            //color.a *= (distance(vUv.x, split_center_point));

            vec2 p = vUv;

             if (p.x > (mask_p)){
                 color.a = 0.0;
             }else{
                color.a *= (smoothstep(mask_position, (mask_position - fade_size), p.x ));
              }



            gl_FragColor = color;
        }

如您所见,淡入并没有完全显示整个图像。任何有关解决此问题的更好方法的见解都会很棒。谢谢!

【问题讨论】:

  • 你可以使用 mix,比如: color = mix( vec4( 0 ), color, time );或者,让它像这样重复: color = mix( vec4( 0 ), color, sin( time ) );其中时间是来自加载后经过的时间的统一。

标签: glsl shader fragment-shader


【解决方案1】:

您要做的是使mask_position 左侧的区域可见,但您想隐藏右侧的区域。这可以通过step实现:

color.a *= 1.0 - step(fade_size, p);

如果你想从可见区域平滑过渡到不可见区域,那么你必须使用smoothstep。褪色开始在mask_position之前一定量,在mask_position之后一定量结束:

float start_p = mask_position-fade_size;
float end_p   = mask_position+fade_size;
color.a *= 1.0 - smoothstep(start_p, end_p, vUv.x);

这将导致图像的开头和结尾永远不会完全淡入。为了弥补这一点,必须将 [vUV.x] 从范围 [0.0, 1.0] 映射到范围 [fade_size, 1.0-fade_size]。这可以通过mix 轻松计算:

float p = vUv.x * (1.0-2.0*fade_size) + fade_size;
color.a *= 1.0 - smoothstep(start_p, end_p, p;

如果最终剔除器的 alpha 通道低于一个微小的阈值,则可以丢弃该片段:

if ( color.a < 0.01 )
      discard;

最终着色器:

varying vec2 vUv;
precision highp float;
precision highp int;
uniform sampler2D texture;
uniform float mask_position;
uniform float fade_size;

void main(void) {
    vec4 color = texture2D(texture, vUv);

    float start_p = mask_position-fade_size;
    float end_p   = mask_position+fade_size;
    float p       = mix(fade_size, 1.0-fade_size, vUv.x);

    color.a *= 1.0 - smoothstep(start_p, end_p, p);
    if ( color.a < 0.01 )
        discard;

    gl_FragColor = color;
}

看例子:

var container;
var camera, scene, renderer;
var uniforms;

init();
animate();

function init() {
    container = document.getElementById( 'container' );

    camera = new THREE.Camera();
    camera.position.z = 1;

    scene = new THREE.Scene();

    var geometry = new THREE.PlaneBufferGeometry( 2, 2 );

    var texture = new THREE.TextureLoader().load( 'https://raw.githubusercontent.com/Rabbid76/graphics-snippets/master/resource/texture/background.jpg' );

    uniforms = {
        u_time: { type: "f", value: 1.0 },
        u_resolution: { type: "v2", value: new THREE.Vector2() },
        u_mouse: { type: "v2", value: new THREE.Vector2() },
        texture: {type: 't', value: texture},
        fade_size: { type: 'f', value: 0.2 },
        mask_position: { type: 'f', value: 0 }
    };

    var material = new THREE.ShaderMaterial( {
        uniforms: uniforms,
        vertexShader: document.getElementById( 'vertexShader' ).textContent,
        fragmentShader: document.getElementById( 'fragmentShader' ).textContent
    } );

    var mesh = new THREE.Mesh( geometry, material );
    scene.add( mesh );

    renderer = new THREE.WebGLRenderer( {alpha : true} );
    renderer.setClearColor(0xffffff, 0.0);
    renderer.setPixelRatio( window.devicePixelRatio );

    container.appendChild( renderer.domElement );

    onWindowResize();
    window.addEventListener( 'resize', onWindowResize, false );

    document.onmousemove = function(e){
    uniforms.u_mouse.value.x = e.pageX
    uniforms.u_mouse.value.y = e.pageY
    }
}

function onWindowResize( event ) {
    renderer.setSize( window.innerWidth, window.innerHeight );
    uniforms.u_resolution.value.x = renderer.domElement.width;
    uniforms.u_resolution.value.y = renderer.domElement.height;
}

function animate() {
    requestAnimationFrame( animate );
    render();
}

var mask_step = 0.01;
var mask_val = 0.0;
function render() {
    if ( mask_val >= 1.0) { mask_val = 1.0; mask_step = -0.01; }
    else if ( mask_val <= -0.0) { mask_val = 0.0; mask_step = 0.01; }
    mask_val += mask_step;
    uniforms.mask_position.value = mask_val;
    uniforms.u_time.value += 0.05;
    renderer.render( scene, camera );
}
<script id="vertexShader" type="x-shader/x-vertex">
void main() {
    gl_Position = vec4( position, 1.0 );
}
</script>

<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec2      u_resolution;
uniform float     u_time;
uniform sampler2D texture;
uniform float     fade_size;
uniform float     mask_position;

void main() {
    vec2 vUv = gl_FragCoord.xy/u_resolution.xy;
    
    vec4 color = texture2D(texture, vUv);
                
    float start_p = mask_position-fade_size;
    float end_p   = mask_position+fade_size;
    float p       = mix(fade_size, 1.0-fade_size, vUv.x);
    color.rgba *= 1.0 - smoothstep(start_p, end_p, p);
    if ( color.a < 0.01 )
          discard;

    gl_FragColor = color;
}
</script>

<div id="container"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/100/three.min.js"></script>

【讨论】:

    猜你喜欢
    • 2011-03-18
    • 2011-03-28
    • 1970-01-01
    • 2014-01-20
    • 2012-12-18
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多