I'm trying to draw a quad in 2D (in SharpDX, but that is basically XNA). But texture correction is not working, and I'm getting only an affine textured quad.
I'm using BasicEffect
to render it.
BasicTextureEffect = new BasicEffect(Device)
{
Alpha = 1.0f,
TextureEnabled = true,
LightingEnabled = false,
VertexColorEnabled = true,
Projection = Matrix.OrthoOffCenterLH(0.0f, ScreenWidth, ScreenHeight, 0.0f, 0.0f, 1.0f),
};
It is an 2D isometric game. I have pseudo-3D coordinates in isometric world (it's a shadow on the ground) converted to screen space, and then rendered using DrawQuad
.
Do I need to set-up view (or projection?) somehow, to real 3D (emulate the isometric camera), and then draw this quad in 3D coordinates instead? How eventually? Or is there a way to correct this in 2D?
Update:
I've uploaded the actual partial screen-shot (Figure A), for you to see it's almost the same. (I cut it a bit, but it goes all to the corner)
Figure A Figure B
Update 2:
I can confirm now, that plain SharpDX (XNA) BasicEffect
does this with just plain UW mapping (4 corners of a square), and plain DrawQuad
. I've temporarily changed it to include center point, and I do draw 4 triangles instead of 2 (Figure B), this reduces effect to minimum, but it's still there. It still needs to be solved, because I won't be using it only on shadow.
Answer
I've changed the shader according to the article suggested by Seth Battin. Now it performs perspectively correct quad texturing. Phew, bacon delivered:
For the future generations that may never happen. The input is in a form of the line vertexes A1/A2, B1/B2 that creates diagonals (rather then sequential vertexes):
public static Vector3 DrawPerspectiveCorrectQuad(VertexWithPerspective v1, VertexWithPerspective v2, VertexWithPerspective v3, VertexWithPerspective v4)
{
// detects intersection of two diagonal lines
Single divisor = (v4.Position.Y - v3.Position.Y) * (v2.Position.X - v1.Position.X) - (v4.Position.X - v3.Position.X) * (v2.Position.Y - v1.Position.Y);
Single ua = ((v4.Position.X - v3.Position.X) * (v1.Position.Y - v3.Position.Y) - (v4.Position.Y - v3.Position.Y) * (v1.Position.X - v3.Position.X)) / divisor;
Single ub = ((v2.Position.X - v1.Position.X) * (v1.Position.Y - v3.Position.Y) - (v2.Position.Y - v1.Position.Y) * (v1.Position.X - v3.Position.X)) / divisor;
// calculates the intersection point
Single centerX = v1.Position.X + ua * (v2.Position.X - v1.Position.X);
Single centerY = v1.Position.Y + ub * (v2.Position.Y - v1.Position.Y);
Vector3 center = new Vector3(centerX, centerY, 0.5f);
// determines distances to center for all vertexes
Single d1 = (v1.Position - center).Length();
Single d2 = (v2.Position - center).Length();
Single d3 = (v3.Position - center).Length();
Single d4 = (v4.Position - center).Length();
// calculates quotients used as w component in uvw texture mapping
v1.TextureCoordinate *= Single.IsNaN(d2) || d2 == 0.0f ? 1.0f : (d1 + d2)/d2;
v2.TextureCoordinate *= Single.IsNaN(d1) || d1 == 0.0f ? 1.0f : (d2 + d1)/d1;
v3.TextureCoordinate *= Single.IsNaN(d4) || d4 == 0.0f ? 1.0f : (d3 + d4)/d4;
v4.TextureCoordinate *= Single.IsNaN(d3) || d3 == 0.0f ? 1.0f : (d4 + d3)/d3;
// this is just PrimitiveBatch
// where VertexWithPerspective is basically VertexPositionTextureColor
// with Vector3 (uvw) instead of Vector2 (uv) for texture coordinates
// note: you need to create VertexWithPerspective yourself (decompilation ftw)
PerspectivePrimitives.DrawQuad(v1, v3, v2, v4);
}
No comments:
Post a Comment