Как оживить этот простой шейдер - PullRequest
1 голос
/ 21 июня 2019

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

Чего я хочу добиться: я хочу анимировать эти два цвета.Я хочу, чтобы верхний оранжевый цвет переводился в нижний, а затем возвращался в верх, а нижний красный цвет переводился в верхний, а затем возвращался в нижний.(Для имитации эффекта заката и восхода)

Спасибо!

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

vec3 colorA = vec3(0.905,0.045,0.045);
vec3 colorB = vec3(0.995,0.705,0.051);

void main() {
    vec2 st = gl_FragCoord.xy/u_resolution.xy;

    vec3 pct = vec3(st.y);

    vec3 color = vec3(0.0);

    color = mix(colorA, colorB, pct);

    gl_FragColor = vec4(color,1);
}

enter image description here

Ответы [ 2 ]

1 голос
/ 21 июня 2019

Самый простой способ сделать это - добавить смещение к st.y. Смещение должно быть в диапазоне [-1,0, 1,0]. Это может быть достигнуто с помощью sin. Аргумент sin должен зависеть от u_time.
Обратите внимание: sin вычисляет синусоидальную функцию угла в радианах, поэтому аргумент должен быть масштабирован до 2,0 * PI (~ 2.0*3.1415). Результат должен быть зафиксирован (clamp) в диапазоне [0,0, 1,0].

например:.

float interval = 2000.0; // 2000 milliseconds = 2 seconds
float p = clamp(st.y + sin(2.0*3.1415 * u_time / interval), 0.0, 1.0);

vec3 pct = vec3(p); 

Обратите внимание, что пример работает в случае, когда u_time является значением в миллисекундах. Если u_time будет значением в секундах, то вам нужно увеличить интервал на * 1000.0 '(например, 2.0 вместо 2000.0).

var container, camera, scene, renderer, 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 );

    uniforms = {
        u_time: { type: "f", value: 1.0 },
        u_resolution: { type: "v2", value: new THREE.Vector2() },
        u_mouse: { type: "v2", value: new THREE.Vector2() }
    };

    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();
    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(delta_ms) {
    requestAnimationFrame( animate );
    render(delta_ms);
}

function render(delta_ms) {
    uniforms.u_time.value = delta_ms;
    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">
#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

vec3 colorA = vec3(0.905,0.045,0.045);
vec3 colorB = vec3(0.995,0.705,0.051);

void main() {
    vec2 st = gl_FragCoord.xy/u_resolution.xy;

    float interval = 2000.0; // 2000 milliseconds = 2 seconds
    float p = clamp(st.y + sin(2.0*3.1415 * u_time / interval), 0.0, 1.0);

    vec3 pct = vec3(p);

    vec3 color = vec3(0.0);

    color = mix(colorA, colorB, pct);

    gl_FragColor = vec4(color,1);
}
</script>

<div id="container"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/104/three.min.js"></script>
1 голос
/ 21 июня 2019

Нечто подобное, с дополнительным смешением цветов по sin функции времени:

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

vec3 colorA = vec3(0.905,0.045,0.045);
vec3 colorB = vec3(0.995,0.705,0.051);

void main() {
    vec2 st = gl_FragCoord.xy/u_resolution.xy;

    float sinF = sin(u_time) * 0.5 + 0.5;

    vec3 colorTop = mix(colorA, colorB, sinF);
    vec3 colorBottom = mix(colorB, colorA, sinF);

    vec3 pct = vec3(st.y);

    vec3 color = vec3(0.0);

    color = mix(colorTop, colorBottom, pct);

    gl_FragColor = vec4(color,1);
}
...