Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pixel shader to project a texture to an arbitary quadrilateral

Just need to figure out a way, using Pixel Shader, to project a texture to an arbitary user-defined quadrilateral.

Will be accepting coordinates of the four sides of a quadrilateral:

/// <defaultValue>0,0</defaultValue>
float2 TopLeft : register(c0);

/// <defaultValue>1,0</defaultValue>
float2 TopRight : register(c1);

/// <defaultValue>0,1</defaultValue>
float2 BottomLeft : register(c2);

/// <defaultValue>1,1</defaultValue>
float2 BottomRight : register(c3);

Tried couple of interpolation algorithm, but couldn't manage to get it right.

Is there any sample you guys think which I might be able to modify to get the desired result?

like image 809
Trainee4Life Avatar asked Nov 04 '22 14:11

Trainee4Life


2 Answers

The issue here is that all modern 3D graphics hardware rasterizes triangles, not quadrilaterals. So if you ask Direct3D or OpenGL to render a quad, the API will internally split the quad into two triangles. This is not usually a problem since all modern rendering is perspective-correct, so the viewer should not be able to tell the difference between one quad and two triangles - the interpolation will be seamless.

The correct way to ask the API to perform this interpolation is to pass it the texture coordinates as per-vertex data, which the API/hardware will interpolate across each pixel. Your pixel shader will then have access to this per-pixel texture coordinate. I assume that when you use the term 'project' you mean simply mapping a rectangular texture onto a quad, and you are not referring to texture projection (which is like a spotlight shining a texture onto surfaces).

The bottom line here is that passing the quad's texture coordinates to the pixel shader is the wrong approach (unless you have some special reason why this is required).

like image 96
voidstar69 Avatar answered Nov 14 '22 21:11

voidstar69


There's a nice paper here describing your options (or this .ppt). Basically you need to define some barycentric coordinates across the quad, then interpolate fragment values as BC-weighted sums of the given vertex values.

Sorry, don't know of any code; the lack of direct support for quads on modern triangle-oriented HW (see voidstar69's answer) means they've rather gone out of fashion.

like image 24
timday Avatar answered Nov 14 '22 22:11

timday