Jump to content


Texture Swimming


  • You cannot reply to this topic
10 replies to this topic

#1 dega512

    Valued Member

  • Members
  • PipPipPip
  • 108 posts

Posted 08 April 2006 - 07:00 PM

I have just written a sofware rasterizer and I have an interesting problem. When I rotate polygons with textures on them, the texture appears to swim up and down. This is what I do in my triangle filler:

* I use gradients on all the edges (for x, z, u and v).
* I then call my texture hline function (which again uses a gradient for z change). At each pixel I calculate the texel by:

tz1 = 1.0f / z;            // tz1 is a temorary value

tz2 = 1.0f / tz1;         // tz2 is another temporary value

ut = (u * tz1) * tz2;   // ut is transformed u

vt = (v * tz1) * tz2;   // vt is transformed v

Texel t = Texture.GetTexel(ut, vt);

How do I get rid of this swimming?

Thanks,
-dega

This is my actual code (java):

// LGL is a prefix I use so I know its a graphics class

// LGL_Vertex3D is vertex data which contains a vector names Position

//     which has (x, y, z) along with transformed (sx, sy, sz)

// LGL_Color is just floats A, R, G, B (0.0f - 1.0f), it has ToInt() that returns

//     the color as an integer

// LGL_Texture is just a 2D array of LGL_Color objects

// buffer is an array of integers representing pixels

// sw is an integer representing screen width

// sh is an integer representing screen height

// visibleZ is a method for the zbuffer (is visible, if so set the new z value)

// (Note: the verticies are sorted by increasing y value)


/* inside LGL_Texture */

public LGL_Color GetTexel(float u, float v)

{

	// fWidth is texture width as a float, Width is it as an integer

	// the same goes for fHeight and Height

	return this.Texels[((int)(u * this.fWidth)) % this.Width][((int)(v * this.fHeight)) % this.Height];

}

/* end */


/* inside rasterizer code */

private void drawTextured(LGL_Vertex3D a, LGL_Vertex3D b, LGL_Vertex3D c, LGL_Texture tex)

{

	int y = -1;

	int dest;

	

	// y positions of each vertex

	float ay = (float)Math.ceil(a.Position.sy);

	float by = (float)Math.ceil(b.Position.sy);

	float cy = (float)Math.ceil(c.Position.sy);

	

	// calculate gradients

	float ftmp = 1.0f / (cy - ay);

	float lg = (c.Position.sx - a.Position.sx) * ftmp;

	float hg = 0.0f;

	float lzg =(c.Position.sz - a.Position.sz) * ftmp;

	float hzg = 0.0f;

	float lx = a.Position.sx;

	float lz = a.Position.sz;

	float hx = 0.0f;

	float hz = 0.0f;

	

	float lug = (c.u - a.u) * ftmp;

	float lvg = (c.v - a.v) * ftmp;

	float hug = 0.0f;

	float hvg = 0.0f;

	

	float lu = a.u;

	float lv = a.v;

	float hu = 0.0f;

	float hv = 0.0f;

	

	boolean step = false;

	

	if (ay != by)

	{

		// calculate more gradients for the other side

		ftmp = 1.0f / (by - ay);

		hg = (b.Position.sx - a.Position.sx) * ftmp;

		hzg = (b.Position.sz - a.Position.sz) * ftmp;

		hug = (b.u - a.u) * ftmp;

		hvg = (b.v - a.v) * ftmp;

		hx = lx;

		hz = lz;

		hu = lu;

		hv = lv;

		

		y = (int)ay;

		dest = (int)by;

		

		for (; y < dest; y++)

		{

			if (y >= 0)

			{

				if (y >= this.sh)

					break;

				

				thline(lx, lz, lu, lv, hx, hz, hu, hv, y, tex);

			}

			

			lx += lg;

			lz += lzg;

			lu += lug;

			lv += lvg;

			hx += hg;

			hz += hzg;

			hu += hug;

			hv += hvg;

		}

	}

	else

	{

		y = (int)ay;

		

		thline(a.Position.sx, a.Position.sz, a.u, a.v, b.Position.sx, b.Position.sz, b.u, b.v, y, tex);

		y++;

		step = true;  // we are on the next line

	}

	

	// repeat for lower half...	

	if (cy != by)

	{

		ftmp = 1.0f / (cy - by);

		hx = b.Position.sx;

		hz = b.Position.sz;

		hu = b.u;

		hv = b.v;

		hg = (c.Position.sx - b.Position.sx) * ftmp;

		hzg = (c.Position.sz - b.Position.sz) * ftmp;

		hug = (c.u - b.u) * ftmp;

		hvg = (c.v - b.v) * ftmp;

		

		if (step)

		{

			lx += lg;

			lz += lzg;

			lu += lug;

			lv += lvg;

			hx += hg;

			hz += hzg;

			hu += hug;

			hv += hvg;

		}

		

		dest = (int)cy;

		

		for (; y <= dest; y++)

		{

			if (y >= 0)

			{

				if (y >= this.sh)

					break;

					

				thline(lx, lz, lu, lv, hx, hz, hu, hv, y, tex);

			}

			

			lx += lg;

			lz += lzg;

			lu += lug;

			lv += lvg;

			hx += hg;

			hz += hzg;

			hu += hug;

			hv += hvg;

		}

	}

	else

		thline(c.Position.sx, c.Position.sz, c.u, c.v, b.Position.sx, b.Position.sz, b.u, b.v, (int)cy, tex);

}


private void thline(float x1, float z1, float lu, float lv, float x2, float z2, float ru, float rv, int y, LGL_Texture tex)

{

	float ftmp;

	

	// switch if needed

	if (x2 < x1)

	{

		ftmp = x2;

		x2 = x1;

		x1 = ftmp;

		

		ftmp = ru;

		ru = lu;

		lu = ftmp;

		

		ftmp = rv;

		rv = lv;

		lv = ftmp;

		

		ftmp = z2;

		z2 = z1;

		z1 = ftmp;

	}

	

	float tz1 = 0.0f;

	float tz2 = 0.0f;

	float ut = 0.0f;

	float vt = 0.0f;

		

	int lx = (int)Math.ceil(x1);

	int rx = (int)Math.ceil(x2);

	

	if (rx < 0 || lx >= this.sw)

		return;

	

	// gradients

	ftmp = 1.0f / (float)(rx - lx);

	float zg = (z2 - z1) * ftmp;

	float ug = (ru - lu) * ftmp;

	float vg = (rv - lv) * ftmp;

	int off = y * this.sw;

	

	// draw the textured hline

	while (lx <= rx)

	{

		if (lx >= 0)

		{

			if (lx >= this.sw)

				break;

			

			if (visibleZ(lx, y, z1))

			{

				tz1 = 1.0f / z1;

				tz2 = 1.0f / tz1;

				ut = (lu * tz1) * tz2;

				vt = (lv * tz1) * tz2;

				

				this.buffer.Pixels[off + lx] = tex.GetTexel(ut, vt).ToInt();

			}

		}

		

		lx++;

		z1 += zg;

		lu += ug;

		lv += vg;

	}

}


#2 jirzynek

    New Member

  • Members
  • PipPip
  • 15 posts

Posted 08 April 2006 - 08:31 PM

Hi!

I thing that your problem lies in sub texel accuracy (you don't have it, am I right?).

please read http://www.devmaster...read.php?t=5617
there you will find some useful links - find and read them

regards
jirzynek
int i = 0;
(+ - + - + - + ++--++--++--++--++--++--++--------++++++i);

#3 dega512

    Valued Member

  • Members
  • PipPipPip
  • 108 posts

Posted 08 April 2006 - 09:10 PM

I looked up sub texel/sub pixel and it said to do the following:

float difference = (yPos) - (int)(yPos);  // for edges, then do this with x for hline

...

x += xgradient * difference;

u += ugradient * difference;

v += vgradient * difference;

Is this true, because when I did it things really got messy.

#4 dega512

    Valued Member

  • Members
  • PipPipPip
  • 108 posts

Posted 08 April 2006 - 09:50 PM

Woops, forgot to say that no I don't have it:sad:

#5 dega512

    Valued Member

  • Members
  • PipPipPip
  • 108 posts

Posted 08 April 2006 - 11:35 PM

Here are some images so you can see what it is doing:

No Rotation:

Posted Image


Rotation:

Posted Image

#6 Reedbeta

    DevMaster Staff

  • Administrators
  • 4979 posts
  • LocationBellevue, WA

Posted 09 April 2006 - 07:17 AM

It looks to me like you're not doing perspective-correct texture mapping. You should know that an affine transformation (i.e. 2D linear transformation plus translation) is not sufficient to map textures to the screen - you need a full projective transformation to make it look right.
reedbeta.com - developer blog, OpenGL demos, and other projects

#7 stonemonkey

    New Member

  • Members
  • Pip
  • 3 posts

Posted 09 April 2006 - 08:31 AM

For perspective correct texturing you should be doing the division for each vertex first before the triangle routine,

for each vertex:
tz1=1.0/z
tu=u*tz1
tv=v*tz1

then interpolate those values across the tri and for each pixel you do the reverse

inside scanline:
z=1.0/tz1_interpolated
u=tu_interpolated*z
v=tv_interpolated*z

#8 jirzynek

    New Member

  • Members
  • PipPip
  • 15 posts

Posted 09 April 2006 - 08:37 AM

I think that you have some mistakes in delta calculations, checkit.

I'am using pure affine texture mapping in my project with sub pixel and subtexel accuracy and it looks fine, of course with perpsective correction it would look better but mobile devices are too limited..
int i = 0;
(+ - + - + - + ++--++--++--++--++--++--++--------++++++i);

#9 dega512

    Valued Member

  • Members
  • PipPipPip
  • 108 posts

Posted 09 April 2006 - 03:57 PM

Thanks everyone for your help, I finally have perspective correct texture mapping!!!!!

(Thanks especially to stonemonkey because what you said fixed my problem!)

#10 mysticman

    Member

  • Members
  • PipPip
  • 95 posts

Posted 10 April 2006 - 11:12 PM

Does Reedbeta seem me that he has made the idea?!?!? or no? then thanks also to him!:lol:

#11 dega512

    Valued Member

  • Members
  • PipPipPip
  • 108 posts

Posted 11 April 2006 - 12:00 AM

Thanks to all, and to all a good rest of the day!!!





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users