Render buffershader with negative values

Dear community,

I am setting up a small glsl project using Threejs to make image distortions based on mouse movement. Whenever the mouse moves left or right it is the point to update the uvmap of the image with the corresponding negative or possitive red and green values.

I’m using the setup for feedback from this (p5.js Web Editor) p5.js.

But then instead of video input I’m first rendering a little blurred circle to a canvas with the corresponding red and green values.

The issue I’m facing is that I can not find a way to render negative red and green values in my output buffertexture (used as rendertarget like in the example above).

Which means that my cursos will only displace my final image to the right and up, instead of also having the possibillity to move it down and left.

cheers!!!

Sjoes

Here is some of the code:

setup for the bufershader

  bufferTextureSetup(){
    this.textureA = new THREE.WebGLRenderTarget(
        this.width, this.height,{
          minFilter: THREE.LinearFilter,
          maxFilter: THREE.LinearFilter,
          format: THREE.RGBAFormat
        })
    this.textureB = new THREE.WebGLRenderTarget(
        this.width, this.height,{
            minFilter: THREE.LinearFilter,
            maxFilter: THREE.LinearFilter,
            format: THREE.RGBAFormat
        })
    this.bufferMaterial = new THREE.ShaderMaterial({
        extensions: {
            derivatives: "#extension GL_OES_standard_derivatives : enable"
            },
        side: THREE.DoubleSide,
        uniforms: {
            ubufferTexture: { value: this.textureA.texture},
            ures : { type : 'v2', value: new THREE.Vector2(this.width, this.height)},
            videoTexture: { value: new THREE.TextureLoader().load(ocean)},
            uTexture2: {value: null},
            uValue: {type : 'v2', value : new THREE.Vector2(0,0)},
            time: {type: "f", value: Math.random() * Math.PI * 2 + Math.PI },
            // refresh: {value: new THREE.Vector2(0.95, 0.99)}
        },
        vertexShader: vertex,
        fragmentShader: frag
    });

    // var buffer = this.bufferMaterial;
    // document.body.onkeyup = function(e, buffer) {
    //   if (e.key == " " ||
    //       e.code == "Space" ||      
    //       e.keyCode == 32      
    //   ) {
    //     buffer.uniforms.refresh.x = 0.9;
    //     buffer.uniforms.refresh.y = 0.5;
    //   }
    // }

    this.bufferPlane = new THREE.PlaneGeometry(window.innerWidth, window.innerHeight);
    this.bufferObject = new THREE.Mesh(this.bufferPlane, this.bufferMaterial)
    this.bufferScene.add(this.bufferObject);
  }

setup for the mousetracking:

  trackMousePos(){
    if(Math.abs(this.mouse.x - this.prevmouse.x)<1 &&
    Math.abs(this.mouse.y - this.prevmouse.y) <1){
      this.m.color.r = 0;
      this.m.color.g = 0;
    } else{
      this.circle_color.x = this.mouse.x - this.prevmouse.x;
      this.circle_color.y = this.mouse.y - this.prevmouse.y;
      // let x = Math.sign(this.mouse.x - this.prevmouse.x);
      // let y = Math.sign(this.mouse.y - this.prevmouse.y);
      this.bufferMaterial.uniforms.uValue.x = Math.sign(this.mouse.x - this.prevmouse.x); 
      this.bufferMaterial.uniforms.uValue.y = Math.sign(this.mouse.y - this.prevmouse.y);
      // console.log(this.bufferMaterial.uniforms.uValue.x, this.bufferMaterial.uniforms.uValue.y);


     // giving the blur circle the red and green colors here.

      this.m.color.r = Math.abs(0.1*(this.mouse.x - this.prevmouse.x));//this.circle_color.x;
      this.m.color.g = Math.abs(0.1*(this.mouse.y - this.prevmouse.y));//this.circle_color.y;




      this.setNewWave(this.mouse.x, this.mouse.y, this.currentWave);
      this.currentWave = (this.currentWave +1)%this.max;
      // console.log(this.currentWave);
    }
    this.prevmouse.x = this.mouse.x;
    this.prevmouse.y = this.mouse.y;
  }

the buffer fragmentshader experiment:

uniform vec2 ures;//The width and height of our screen
uniform sampler2D ubufferTexture;//Our input texture
uniform sampler2D videoTexture;
uniform vec2 uValue;
uniform sampler2D uTexture2;
uniform float time;
// uniform vec2 refresh;

void main() {

	vec2 st = gl_FragCoord.xy / ures;
	vec2 uv = st - vec2(0.5);
	// uv *= 0.995;
	uv += vec2(0.5);
	// uv *= vec2(0.5);
	// uv = uv*2.0 - 1.0;

	//vec4 sum = texture2D(ubufferTexture, uv);
	vec4 src = texture2D(videoTexture, uv);

	src.r = src.r + 0.5*uv.x;
	src.g = src.g + 0.5*uv.y;

	// uv *= 0.99;
	// uv += 0.005;
	vec4 sum = texture2D(ubufferTexture, uv);

	// sum.rgb = mix(sum.rbg, src.rgb, 0.01);

	// sum -= 0.5;
	// sum += 0.5;
	// src -= 0.5;


	// uv.xy = uv.xy + sum.xy;

	// uv.x = 2.0*src.r + uv.x;
	// uv.y = 2.0*src.g + uv.y;

	// sum = 0.5*sum + 0.5;

	sum.r = src.r + sum.r;
	sum.g = src.g + sum.g;

	// sum *= 0.5;



	// uv += 4.0*sum.xy;

	// uv *= 0.125;


	// uv.xy = sum.xy + uv.xy;
	// uv *= 0.5;

	// sum *= 1.01;

	// vec4 color = vec4(uv.xy, 1.0, 1.0);

	gl_FragColor = sum;
}

and the final shader.

Here the uniform uDisplacement gets the rendered output of the buffermaterial/bufferscene.

uniform float time;
uniform float progress;
uniform sampler2D uTexture;
uniform sampler2D uPrevTexture;
uniform sampler2D uDisplacement;
uniform vec4 resolution;
varying vec2 vUv;
varying vec3 vPosition;
float PI = 3.141592653589793238;

void main()	{

	vec2 newUV = (vUv - vec2(0.5))*resolution.zw + vec2(0.5);

	vec4 displace = texture2D(uDisplacement, vUv);

	displace *= 0.5;

	// displace = (displace - 0.5) * 2.0;

	vec4 color = texture2D(uTexture, vUv+displace.xy);

	// vec2 newUV = (vUv - vec2(0.5))*resolution.zw + vec2(0.5);
	gl_FragColor = vec4(displace.xy, 0.0, 1.0);
}

I’m not sure I understand the question, but if the input data is float number x in the range [0,1], so there are no negative values, and you need range [-1,1], could you remap x = 2*x-1 and make it [-1,1]?

So, the midpoint 0.5 is the zero, 1 remains 1, and 0 becomes -1.

I assume that the problem is that the negative values don’t come past the rendering of the framebuffer.
This ignores all negative values.

Either that or the output of fragcolor clamps the negative values to 0.

Now, I happily hacked my way through using the blue and alpha channels possitives to later, in the second shader subtract them from the uv’s. This works! So I got what I need.

Though I’m still very curious if there is a way to properly pass negative values out of a shaders fragcolor, or rendering negative values in a rendertarget of THREEjs (I do assume this is the problem, since I’m pretty sure it maps all values between 255 and 0.

curious!