7
\$\begingroup\$

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.

enter image description here

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 AFigure B
            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.

\$\endgroup\$
  • \$\begingroup\$ why texture perspective correction not working ? \$\endgroup\$ – concept3d Dec 29 '13 at 17:21
  • \$\begingroup\$ I really don't know. The effect (on already barely visible shadow) was noticed only by accident, when I changed it to checkerboard texture. It isn't pronounced at all, but it's definitely recognizable as affine. You can't ask me question that I'm basically asking. Why is it not working IS the question? :) \$\endgroup\$ – SmartK8 Dec 29 '13 at 18:06
  • \$\begingroup\$ Similar to this question from SO: stackoverflow.com/questions/15242507/… \$\endgroup\$ – Seth Battin Dec 29 '13 at 18:36
  • \$\begingroup\$ I actually read that, but I wasn't able to conclude what to do in DirectX, it seems OpenGL specific as is the solution presented. \$\endgroup\$ – SmartK8 Dec 29 '13 at 18:38
  • 3
    \$\begingroup\$ Indeed, did you find Nathan Reed's article about it? reedbeta.com/blog/2012/05/26/quadrilateral-interpolation-part-1 \$\endgroup\$ – Seth Battin Dec 29 '13 at 18:45
7
\$\begingroup\$

I've changed the shader according to the article suggested by Seth Battin. Now it performs perspectively correct quad texturing. Phew, bacon delivered:

enter image description here

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<VertexWithPerspective>
    // 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);
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.