Affine shader rendering causing visual artifacts

I’m using the image from a second camera as a texture.
To compensate for affine mapping (like this):

I’ve added the following line to the render shader:
gl_Position /= gl_Position.w;

which “works” giving this:

but the texture disappears and I get this visual artifact when the texture is almost outside the camera’s view

instead of this

Anyone have any idea what’s happening and how to fix it (I’m all out of ideas)?

TIA

For completeness:
Vertex shader:

attribute vec3 aPosition;
attribute vec2 aCorners;
attribute vec2 aUv0;

uniform mat4 matrix_model;
uniform mat4 matrix_viewProjection;

varying vec2 vCorners;
varying vec2 vUv0;

uniform float height;
uniform float width;

void main(void) {
    vUv0 = aUv0 / vec2(width, height);
    vCorners = aCorners;
    gl_Position = matrix_viewProjection * matrix_model * vec4(aPosition, 1.0);
    gl_Position /= gl_Position.w;
}

Frag shader

precision highp float;

uniform sampler2D uColorBuffer;

uniform float height;
uniform float width;

varying vec2 vUv0;
varying vec2 vCorners;

void main() {
    vec2 UVs = vec2(vUv0.x, 1. - vUv0.y);
    gl_FragColor = texture2D(uColorBuffer, UVs);
}

Hi @CarlBateman,

I haven’t done something similar before, but it may be the case when doing the perspective division by .w in the vertex shader, when some of the vertices are off screen are clipped incorrectly.

If it’s possible, store the w component in a varying and do the division in the fragment shader?

vec2 affineUV = vUv0 / vClipW;

Hope it helps.

you can also try sampling your texture using texture2DProj

1 Like

@Leonidas Sadly not

@mvaligursky
Alas
Failed to compile fragment shader:
ERROR: 0:16: 'texture2DProj' : no matching overloaded function found

I strongly suspect the error is on the JavaScript side.
I calculate the on-screen co-ordinates like so:

let toWorldTransform = this.entity.getWorldTransform();
let pos = new pc.Vec3(positions[i], positions[i + 1], positions[i + 2]);
let worldPosition = toWorldTransform.transformPoint(pos);
let screenPosition = camera.worldToScreen(worldPosition);

But one pair of co-ordinates (the right-most) switch sign
Correct

-7280069.912593271,  3877427.9896068643
-7280069.912593273, -3678760.1932197637
     231.346458528,     1078.7000162930
     231.346458528,      -79.3996963762

Wrong

10884949.03334061, -5795229.547305286
10884949.03334061,  5500072.461739768
     231.09154364,     1078.829860845
     231.09154364,      -79.463184058

After extensive testing, the problem is definitely not on the JavaScript side.

So, yeah, not a clue what’s going on. :cry: