Author Topic: Perspectively corrected texture mapping (software rendered)[BB2D]  (Read 10407 times)

0 Members and 1 Guest are viewing this topic.

Offline Devils Child

  • C= 64
  • **
  • Posts: 66
  • Karma: 2
    • View Profile
hi!
i moved here from ezboard!

as you see in the pic below, the textures are drawn linear, and not perspectively correct. i read in the old ezboard forum a thread about how it works. anyway, i just dont get it! how is it working?
==> http://p205.ezboard.com/very-fast-3d-duel-screen-demo/fyabasicprogrammingfrm25.showMessage?topicID=23.topic



download: http://www.dc.freecoder-portal.de/upload/files/Devils%20Child/VirtualGL.zip
i know there are some other helpful threads, but they didnt help me yet at all. what i need is someone, who can help me or implement the perspective correction :)
i would really appreceate that

bye
« Last Edit: July 21, 2007 by Shockwave »

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
heh i remember trying to figuare this out it was driving me nuts i got it to work in blitz here.

http://p205.ezboard.com/fyabasicprogrammingfrm22.showMessageRange?topicID=164.topic&start=21&stop=21

but if you dont get that i could give it go at incorporating it in you engine.

great stuff btw!
Challenge Trophies Won:

Offline Devils Child

  • C= 64
  • **
  • Posts: 66
  • Karma: 2
    • View Profile
i saw this thread, downloaded the source code and looked at it. it still is driving me nuts.
i really appreceate your help, and i would be happy if you could do that for me.
thank you :)

however, that is what i've done for the community: http://www.devil-engines.net

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
ohh very nice stuff there Devils Child i knew you knew your stuff when i looked at the source to the affine mapper :)

ill post up hopefully a working perspective correct mapper in a little while for you ill also comment it as much as possible too ;)

anywho welcome to the forum were a good bunch hope you stick around.
Challenge Trophies Won:

Offline Tetra

  • DBF Aficionado
  • ******
  • Posts: 2532
  • Karma: 83
  • Pirate Monkey!
    • View Profile
Hello Devils Child,

Welcome to the new forum :)

Great job on a nice looking Blitz software 3D engine  :clap:

Perspective correct was a trickey one, and had me scratching my head for a long while. But, the funny thing is its actually a lot simpler to implement than it seems. I'll try and explain it as best I can.

i'll try to work with an example and hopefully I wont overcomplicate it :)
Assume i'm working on the following triangle: -


          v0
          /\
        /    \
      /_______\
   v2           v1


Its all to do with how you interpolate your U V coordinates.
The z value of each vertex in the triangle need to be divided into 1.0
You then use these new values rather than the z values in you calculation.
Also, before you interpolate the U V values, you need to multiply them by the new z values.

So say I was working on interpolating edge v0->v1 I would do something along the lines of: -

pc0z = 1.0 / v0.z
pc1z = 1.0 / v1.z

pc0U = v0.u * pc0z
pc0V = v0.v * pc0z

pc1U = v1.u * pc1z
pc1V = v1.v * pc1z


::Edit:: ( adding the final step that I forgot :) )

Now feed them into your normal triangle renderer.

pc0z instead of v0.z
pc1z instead of v1.z
pc0U instead of v0.u
pc0V instead of v0.v
pc1U instead of v1.u
pc1V instead of v1.v


Then finally at each pixel drawn to the screen in your triangle renderer, divide the interpolated z value into the interpolated U V values to get the final texture coordinates.

U = pixelU / pixelZ
V = pixelV / pixelZ

::End Edit::

Thats basically it, all you are doing is calculating a new value for each, z and u v values for each vertex, then using the new values in your routine.

An extra bonus of using PC is that if your using a Z-Buffer, by using the pc0z and pc1z instead of v0.z and v1.z for that buffer you just perspective corrected your Z-Buffer, transforming it into a W-Buffer  :mince:

Hope that hepls somewhat. What I suggest you do is try to implement it into your triangle routine and see what it looks like. If you find you still cant make it work then post the new code here and well see where it goes wrong :)
« Last Edit: June 26, 2007 by Tetra »
Challenge Trophies Won:

Offline Devils Child

  • C= 64
  • **
  • Posts: 66
  • Karma: 2
    • View Profile
at first, i like to thank nino for his offer of modifying my code and tetra for his good explination!

this is my code (not working)
if you zoom in, you might see that there is no real difference at all :(

hm. what is it, that i just dont get it?
Quote
Const vglShlUV = 12
Const vglShlUV2 = 1024 Shl vglShlUV
Const vglShlBuffer = 65536

Type vglTexture
   Field w, h, texel[1025 ^ 2]
End Type
Global vglViewportX, vglViewportY, vglViewportW, vglViewportH
Global vglClipNear#, vglClipFar#
Global vglWireframeFill, vglWireframeWire, vglWireframeWireColor

Global vglTrisRendered

Global vglMat_aa#, vglMat_ab#, vglMat_ac#
Global vglMat_ba#, vglMat_bb#, vglMat_bc#
Global vglMat_ca#, vglMat_cb#, vglMat_cc#
Global vglMat_da#, vglMat_db#, vglMat_dc#
Global vglVert1x#, vglVert1y#, vglVert1z#, vglVert1u#, vglVert1v#
Global vglVert2x#, vglVert2y#, vglVert2z#, vglVert2u#, vglVert2v#
Global vglVert3x#, vglVert3y#, vglVert3z#, vglVert3u#, vglVert3v#
Global vglTex.vglTexture, vglTexMaskColor
Dim vglBuffer(-1, -1)

Function vglInit()
vglSetViewport(0, 0, GraphicsWidth(), GraphicsHeight())
vglSetClippingPlane(1, 1000)
vglSetWireframe(True, False)
Dim vglBuffer(GraphicsWidth(), GraphicsHeight())
End Function

Function vglFree()
Delete Each vglTexture
End Function

Function vglMatrixIdentity()
vglMat_aa# = 1: vglMat_ab# = 0: vglMat_ac# = 0
vglMat_ba# = 0: vglMat_bb# = 1: vglMat_bc# = 0
vglMat_ca# = 0: vglMat_cb# = 0: vglMat_cc# = 1
vglMat_da# = 0: vglMat_db# = 0: vglMat_dc# = 0
End Function

Function vglMatrixTranslate(x#, y#, z#)
vglMat_da# = vglMat_da# + x#
vglMat_db# = vglMat_db# + y#
vglMat_dc# = vglMat_dc# + z#
End Function

Function vglMatrixRotate(x#, y#, z#)
If x# <> 0 Then
   vglMat2_ab# = vglMat_ab#
   vglMat2_bb# = vglMat_bb#
   vglMat2_cb# = vglMat_cb#
   vglMat2_db# = vglMat_db#
   vglMat_ab# = vglMat_ab# * Cos(x#) + vglMat_ac# * -Sin(x#)
   vglMat_ac# = vglMat2_ab# * Sin(x#) + vglMat_ac# * Cos(x#)
   vglMat_bb# = vglMat_bb# * Cos(x#) + vglMat_bc# * -Sin(x#)
   vglMat_bc# = vglMat2_bb# * Sin(x#) + vglMat_bc# * Cos(x#)
   vglMat_cb# = vglMat_cb# * Cos(x#) + vglMat_cc# * -Sin(x#)
   vglMat_cc# = vglMat2_cb# * Sin(x#) + vglMat_cc# * Cos(x#)
   vglMat_db# = vglMat_db# * Cos(x#) + vglMat_dc# * -Sin(x#)
   vglMat_dc# = vglMat2_db# * Sin(x#) + vglMat_dc# * Cos(x#)
EndIf
If y# <> 0 Then
   vglMat2_aa# = vglMat_aa#
   vglMat2_ba# = vglMat_ba#
   vglMat2_ca# = vglMat_ca#
   vglMat2_da# = vglMat_da#
   vglMat_aa# = vglMat_aa# * Cos(y#) + vglMat_ac# * Sin(y#)
   vglMat_ac# = vglMat2_aa# * -Sin(y#) + vglMat_ac# * Cos(y#)
   vglMat_ba# = vglMat_ba# * Cos(y#) + vglMat_bc# * Sin(y#)
   vglMat_bc# = vglMat2_ba# * -Sin(y#) + vglMat_bc# * Cos(y#)
   vglMat_ca# = vglMat_ca# * Cos(y#) + vglMat_cc# * Sin(y#)
   vglMat_cc# = vglMat2_ca# * -Sin(y#) + vglMat_cc# * Cos(y#)
   vglMat_da# = vglMat_da# * Cos(y#) + vglMat_dc# * Sin(y#)
   vglMat_dc# = vglMat2_da# * -Sin(y#) + vglMat_dc# * Cos(y#)
EndIf
If z# <> 0 Then
   vglMat2_aa# = vglMat_aa#
   vglMat2_ba# = vglMat_ba#
   vglMat2_ca# = vglMat_ca#
   vglMat2_da# = vglMat_da#
   vglMat_aa# = vglMat_aa# * Cos(z#) + vglMat_ab# * -Sin(z#)
   vglMat_ab# = vglMat2_aa# * Sin(z#) + vglMat_ab# * Cos(z#)
   vglMat_ba# = vglMat_ba# * Cos(z#) + vglMat_bb# * -Sin(z#)
   vglMat_bb# = vglMat2_ba# * Sin(z#) + vglMat_bb# * Cos(z#)
   vglMat_ca# = vglMat_ca# * Cos(z#) + vglMat_cb# * -Sin(z#)
   vglMat_cb# = vglMat2_ca# * Sin(z#) + vglMat_cb# * Cos(z#)
   vglMat_da# = vglMat_da# * Cos(z#) + vglMat_db# * -Sin(z#)
   vglMat_db# = vglMat2_da# * Sin(z#) + vglMat_db# * Cos(z#)
EndIf
End Function

Function vglMatrixScale(x#, y#, z#)
vglMat_aa# = vglMat_aa# * x#
vglMat_ab# = vglMat_ab# * y#
vglMat_ac# = vglMat_ac# * z#
vglMat_ba# = vglMat_ba# * x#
vglMat_bb# = vglMat_bb# * y#
vglMat_bc# = vglMat_bc# * z#
vglMat_ca# = vglMat_ca# * x#
vglMat_cb# = vglMat_cb# * y#
vglMat_cc# = vglMat_cc# * z#
vglMat_da# = vglMat_da# * x#
vglMat_db# = vglMat_db# * y#
vglMat_dc# = vglMat_dc# * z#
End Function

Function vglLoadTexture(path$)
t.vglTexture = New vglTexture
img = LoadImage(path$)
w = ImageWidth(img)
h = ImageHeight(img)
LockBuffer ImageBuffer(img)
t\w = w
t\h = h
For x = 0 To t\w - 1
   For y = 0 To t\h - 1
      t\texel[x * h + y] = ReadPixelFast(x, y, ImageBuffer(img))
   Next
Next
UnlockBuffer ImageBuffer(img)
FreeImage img
Return Handle(t)
End Function

Function vglClearBuffer()
zfar = vglClipFar# * vglShlBuffer
For x = 0 To vglViewportW
   For y = 0 To vglViewportH
      vglBuffer(x, y) = zfar
   Next
Next
vglTrisRendered = 0
End Function

Function vglBeginDraw()
LockBuffer()
End Function

Function vglEndDraw()
UnlockBuffer()
Viewport 0, 0, GraphicsWidth(), GraphicsHeight()
End Function

Function vglSetTexture(tex, mask_color = -1)
vglTex = Object.vglTexture(tex)
vglTexMaskColor = mask_color
End Function

Function vglSetViewport(x, y, w, h)
If x < 0 Then x = 0
If y < 0 Then y = 0
If x + w > GraphicsWidth() Then w = GraphicsWidth() - x
If y + h > GraphicsHeight() Then h = GraphicsHeight() - y
Viewport x, y, w, h
vglViewportX = x
vglViewportY = y
vglViewportW = w
vglViewportH = h
End Function

Function vglSetClippingPlane(near#, far#)
vglClipNear# = near#
vglClipFar# = far#
End Function

Function vglSetWireframe(fill, wire, wirecol = $FFFFFF)
vglWireframeFill = fill
vglWireframeWire = wire
vglWireframeWireColor = wirecol
End Function

Function vglVertex1(x#, y#, z#, u# = 0, v# = 0)
vglVert1x# = x#
vglVert1y# = y#
vglVert1z# = z#
vglVert1u# = u#
vglVert1v# = v#
End Function

Function vglVertex2(x#, y#, z#, u# = 0, v# = 0)
vglVert2x# = x#
vglVert2y# = y#
vglVert2z# = z#
vglVert2u# = u#
vglVert2v# = v#
End Function

Function vglVertex3(x#, y#, z#, u# = 0, v# = 0)
vglVert3x# = x#
vglVert3y# = y#
vglVert3z# = z#
vglVert3u# = u#
vglVert3v# = v#
End Function

Function vglTriangle()
p1x# = vglMat_aa# * vglVert1x# + vglMat_ba# * vglVert1y# + vglMat_ca# * vglVert1z# + vglMat_da#
p1y# = vglMat_ab# * vglVert1x# + vglMat_bb# * vglVert1y# + vglMat_cb# * vglVert1z# + vglMat_db#
p1z# = vglMat_ac# * vglVert1x# + vglMat_bc# * vglVert1y# + vglMat_cc# * vglVert1z# + vglMat_dc#
p2x# = vglMat_aa# * vglVert2x# + vglMat_ba# * vglVert2y# + vglMat_ca# * vglVert2z# + vglMat_da#
p2y# = vglMat_ab# * vglVert2x# + vglMat_bb# * vglVert2y# + vglMat_cb# * vglVert2z# + vglMat_db#
p2z# = vglMat_ac# * vglVert2x# + vglMat_bc# * vglVert2y# + vglMat_cc# * vglVert2z# + vglMat_dc#
p3x# = vglMat_aa# * vglVert3x# + vglMat_ba# * vglVert3y# + vglMat_ca# * vglVert3z# + vglMat_da#
p3y# = vglMat_ab# * vglVert3x# + vglMat_bb# * vglVert3y# + vglMat_cb# * vglVert3z# + vglMat_db#
p3z# = vglMat_ac# * vglVert3x# + vglMat_bc# * vglVert3y# + vglMat_cc# * vglVert3z# + vglMat_dc#
If vgliCull(p1x#, p1y#, p1z#, p2x#, p2y#, p2z#, p3x#, p3y#, p3z#) Then Return
p1u = (vglVert1u# * vglTex\w) Shl vglShlUV
p1v = (vglVert1v# * vglTex\h) Shl vglShlUV
p2u = (vglVert2u# * vglTex\w) Shl vglShlUV
p2v = (vglVert2v# * vglTex\h) Shl vglShlUV
p3u = (vglVert3u# * vglTex\w) Shl vglShlUV
p3v = (vglVert3v# * vglTex\h) Shl vglShlUV
p1c = (p1z# < vglClipNear#)
p2c = (p2z# < vglClipNear#)
p3c = (p3z# < vglClipNear#)
If p1c = False And p2c = False And p3c = False Then
   vgliRenderTriangle(p1x#, p1y#, p1z#, p1u, p1v, p2x#, p2y#, p2z#, p2u, p2v, p3x#, p3y#, p3z#, p3u, p3v)
ElseIf p1c And p2c And p3c Then
   Return
Else
   p12x# = vgliIntpf(vglClipNear#, p1z#, p2z#, p1x#, p2x#)
   p12y# = vgliIntpf(vglClipNear#, p1z#, p2z#, p1y#, p2y#)
   p12u = vgliIntpf(vglClipNear#, p1z#, p2z#, p1u, p2u)
   p12v = vgliIntpf(vglClipNear#, p1z#, p2z#, p1v, p2v)
   p12z# = vglClipNear#
   p23x# = vgliIntpf(vglClipNear#, p2z#, p3z#, p2x#, p3x#)
   p23y# = vgliIntpf(vglClipNear#, p2z#, p3z#, p2y#, p3y#)
   p23u = vgliIntpf(vglClipNear#, p2z#, p3z#, p2u, p3u)
   p23v = vgliIntpf(vglClipNear#, p2z#, p3z#, p2v, p3v)
   p23z# = vglClipNear#
   p13x# = vgliIntpf(vglClipNear#, p1z#, p3z#, p1x#, p3x#)
   p13y# = vgliIntpf(vglClipNear#, p1z#, p3z#, p1y#, p3y#)
   p13u = vgliIntpf(vglClipNear#, p1z#, p3z#, p1u, p3u)
   p13v = vgliIntpf(vglClipNear#, p1z#, p3z#, p1v, p3v)
   p13z# = vglClipNear#
   If p1c And p2c = False And p3c = False Then
      vgliRenderTriangle(p3x#, p3y#, p3z#, p3u, p3v, p13x#, p13y#, p13z#, p13u, p13v, p2x#, p2y#, p2z#, p2u, p2v)
      vgliRenderTriangle(p12x#, p12y#, p12z#, p12u, p12v, p2x#, p2y#, p2z#, p2u, p2v, p13x#, p13y#, p13z#, p13u, p13v)
      Return
   ElseIf p2c And p1c = False And p3c = False Then
      vgliRenderTriangle(p1x#, p1y#, p1z#, p1u, p1v, p12x#, p12y#, p12z#, p12u, p12v, p23x#, p23y#, p23z#, p23u, p23v)
      vgliRenderTriangle(p3x#, p3y#, p3z#, p3u, p3v, p1x#, p1y#, p1z#, p1u, p1v, p23x#, p23y#, p23z#, p23u, p23v)
      Return
   ElseIf p3c And p1c = False And p2c = False Then
      vgliRenderTriangle(p13x#, p13y#, p13z#, p13u, p13v, p1x#, p1y#, p1z#, p1u, p1v, p23x#, p23y#, p23z#, p23u, p23v)
      vgliRenderTriangle(p1x#, p1y#, p1z#, p1u, p1v, p2x#, p2y#, p2z#, p2u, p2v, p23x#, p23y#, p23z#, p23u, p23v)
      Return
   ElseIf p1c And p2c Then
      vgliRenderTriangle(p3x#, p3y#, p3z#, p3u, p3v, p13x#, p13y#, p13z#, p13u, p13v, p23x#, p23y#, p23z#, p23u, p23v)
   ElseIf p2c And p3c Then
      vgliRenderTriangle(p1x#, p1y#, p1z#, p1u, p1v, p12x#, p12y#, p12z#, p12u, p12v, p13x#, p13y#, p13z#, p13u, p13v)
   ElseIf p3c And p1c Then
      vgliRenderTriangle(p2x#, p2y#, p2z#, p2u, p2v, p23x#, p23y#, p23z#, p23u, p23v, p12x#, p12y#, p12z#, p12u, p12v)
   EndIf
EndIf
End Function

Function vgliRenderTriangle(p1x#, p1y#, p1z#, p1u, p1v, p2x#, p2y#, p2z#, p2u, p2v, p3x#, p3y#, p3z#, p3u, p3v)
If p1z# > vglClipFar# And p2z# > vglClipFar# And p3z# > vglClipFar# Then Return
views = (vglViewportW + vglViewportH) / 2
vieww2 = vglViewPortW / 2
viewh2 = vglViewPortH / 2
p1px = p1x# * views / p1z# + vieww2
p1py = -p1y# * views / p1z# + viewh2
p2px = p2x# * views / p2z# + vieww2
p2py = -p2y# * views / p2z# + viewh2
p3px = p3x# * views / p3z# + vieww2
p3py = -p3y# * views / p3z# + viewh2
p1z# = p1z# * vglShlBuffer
p2z# = p2z# * vglShlBuffer
p3z# = p3z# * vglShlBuffer
vglTrisRendered = vglTrisRendered + 1
If vglWireframeFill Then vgliFillTri(p1px, p1py, p1z#, p1u, p1v, p2px, p2py, p2z#, p2u, p2v, p3px, p3py, p3z#, p3u, p3v)
If vglWireframeWire Then
   Color (vglWireframeWireColor And $FF0000) / $10000, (vglWireframeWireColor And $FF00) / $100, vglWireframeWireColor And $FF
   Line vglViewPortX + p1px, vglViewPortY + p1py, vglViewPortX + p2px, vglViewPortY + p2py
   Line vglViewPortX + p2px, vglViewPortY + p2py, vglViewPortX + p3px, vglViewPortY + p3py
   Line vglViewPortX + p3px, vglViewPortY + p3py, vglViewPortX + p1px, vglViewPortY + p1py
EndIf
End Function

Function vgliFillTri(p1x, p1y, p1d, p1u, p1v, p2x, p2y, p2d, p2u, p2v, p3x, p3y, p3d, p3u, p3v)
If p1y > p2y Then
   ptx = p1x
   pty = p1y
   ptd = p1d
   ptu = p1u
   ptv = p1v
   p1x = p2x
   p1y = p2y
   p1d = p2d
   p1u = p2u
   p1v = p2v
   p2x = ptx
   p2y = pty
   p2d = ptd
   p2u = ptu
   p2v = ptv
EndIf
If p2y > p3y Then
   ptx = p2x
   pty = p2y
   ptd = p2d
   ptu = p2u
   ptv = p2v
   p2x = p3x
   p2y = p3y
   p2d = p3d
   p2u = p3u
   p2v = p3v
   p3x = ptx
   p3y = pty
   p3d = ptd
   p3u = ptu
   p3v = ptv
   If p1y > p2y Then
      ptx = p1x
      pty = p1y
      ptd = p1d
      ptu = p1u
      ptv = p1v
      p1x = p2x
      p1y = p2y
      p1d = p2d
      p1u = p2u
      p1v = p2v
      p2x = ptx
      p2y = pty
      p2d = ptd
      p2u = ptu
      p2v = ptv
   EndIf
EndIf
pc1 = 65536.0 / p1d
pc2 = 65536.0 / p2d
pc3 = 65536.0 / p3d
p1u = p1u * pc1
p1v = p1v * pc1
p2u = p2u * pc2
p2v = p2v * pc2
p3u = p3u * pc3
p3v = p3v * pc3
If p1y <> p2y Then
   For y = p1y To p2y
      If y => 0 Then
         If y => vglViewportH Then Exit
         x1 = vgliIntp(y, p1y, p3y, p1x, p3x)
         d1 = vgliIntp(y, p1y, p3y, p1d, p3d)
         u1 = vgliIntp(y, p1y, p3y, p1u, p3u)
         v1 = vgliIntp(y, p1y, p3y, p1v, p3v)
         x2 = vgliIntp(y, p1y, p2y, p1x, p2x)
         d2 = vgliIntp(y, p1y, p2y, p1d, p2d)
         u2 = vgliIntp(y, p1y, p2y, p1u, p2u)
         v2 = vgliIntp(y, p1y, p2y, p1v, p2v)
         vgliFillTriLine(x1, d1, u1, v1, x2, d2, u2, v2, y)
      EndIf
   Next
EndIf
If p2y <> p3y Then
   For y = p2y To p3y
      If y => 0 Then
         If y => vglViewportH Then Exit
         x1 = vgliIntp(y, p1y, p3y, p1x, p3x)
         d1 = vgliIntp(y, p1y, p3y, p1d, p3d)
         u1 = vgliIntp(y, p1y, p3y, p1u, p3u)
         v1 = vgliIntp(y, p1y, p3y, p1v, p3v)
         x2 = vgliIntp(y, p2y, p3y, p2x, p3x)
         d2 = vgliIntp(y, p2y, p3y, p2d, p3d)
         u2 = vgliIntp(y, p2y, p3y, p2u, p3u)
         v2 = vgliIntp(y, p2y, p3y, p2v, p3v)
         vgliFillTriLine(x1, d1, u1, v1, x2, d2, u2, v2, y)
      EndIf
   Next
EndIf
End Function

Function vgliFillTriLine(p1x, p1d, p1u, p1v, p2x, p2d, p2u, p2v, y)
If p1x = p2x Then Return
If p1x > p2x Then
   tx = p1x
   td = p1d
   tu = p1u
   tv = p1v
   p1x = p2x
   p1d = p2d
   p1u = p2u
   p1v = p2v
   p2x = tx
   p2d = td
   p2u = tu
   p2v = tv
EndIf
If p2x <= 0 Or p1x => vglViewportW Then Return
id = (p2d - p1d) / (p2x - p1x)
iu = (p2u - p1u) / (p2x - p1x)
iv = (p2v - p1v) / (p2x - p1x)
d = p1d
tw = vglTex\w Shl vglShlUV
th = vglTex\h Shl vglShlUV
u = (p1u + vglShlUV2) Mod tw
v = (p1v + vglShlUV2) Mod th
tex.vglTexture = vglTex
For x = p1x To p2x
   If x => vglViewportW Then Exit
   d = d + id
   u = u + iu
   v = v + iv
   If u > tw Then u = 0
   If v > th Then v = 0
   If u < 0 Then u = tw
   If v < 0 Then v = th
   If x => 0 Then
      If d < vglBuffer(x, y) Then
         vglBuffer(x, y) = d
         rgb = tex\texel[(v Shr vglShlUV) * tex\h + (u Shr vglShlUV)]
         If rgb <> vglTexMaskColor - 16777216 Then
            WritePixelFast x + vglViewportX, y + vglViewportY, rgb
         EndIf
      EndIf
   EndIf
Next
End Function

Function vglGetTrisRendered()
Return vglTrisRendered
End Function


Function vgliCull(p1x#, p1y#, p1z#, p2x#, p2y#, p2z#, p3x#, p3y#, p3z#)
e1x# = p3x# - p2x#
e1y# = p3y# - p2y#
e1z# = p3z# - p2z#
e2x# = p2x# - p1x#
e2y# = p2y# - p1y#
e2z# = p2z# - p1z#
nx# = p1x# * (e1y# * e2z# - e1z# * e2y#)
ny# = p1y# * (e1z# * e2x# - e1x# * e2z#)
nz# = p1z# * (e1x# * e2y# - e1y# * e2x#)
Return nx# + ny# + nz# < 0
End Function

Function vgliIntpf#(value#, vMin#, vMax#, retMin#, retMax#)
Return retMin# + (value# - vMin#) * (retMax# - retMin#) / (vMax# - vMin#)
End Function

Function vgliIntp(value, vMin, vMax, retMin, retMax)
Return retMin + (value - vMin) * (retMax - retMin) / (vMax - vMin)
End Function

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
thats almost it!

but you must revert back from the 1.0/z like so in the scanline function.
Code: [Select]
Function vgliFillTriLine(p1x, p1d, p1u, p1v, p2x, p2d, p2u, p2v, y, tex.vglTexture)
If p1x = p2x Then Return
If p1x > p2x Then
tx = p1x
td = p1d
tu = p1u
tv = p1v
p1x = p2x
p1d = p2d
p1u = p2u
p1v = p2v
p2x = tx
p2d = td
p2u = tu
p2v = tv
EndIf
If p2x < 0 Then Return
id = (p2d - p1d) / (p2x - p1x)
iu = (p2u - p1u) / (p2x - p1x)
iv = (p2v - p1v) / (p2x - p1x)
d = p1d
tw = tex\w Shl vglShlUV
th = tex\h Shl vglShlUV
u = (p1u + vglShlUV2) Mod tw
v = (p1v + vglShlUV2) Mod th
y2 = y + vglViewportY
For x = p1x To p2x
If x => vglViewportW Then Exit
d = d + id
u = u + iu
v = v + iv
If u > tw Then u = 0
If v > th Then v = 0
If u < 0 Then u = tw
If v < 0 Then v = th
If x => 0 Then
If d < vglBuffer(x, y) Then
vglBuffer(x, y) = d
w = vglShlBuffer/d
s# = u * w
t# = v * w
WritePixelFast x + vglViewportX, y2, tex\texel[(s Shr vglShlUV) * tex\h + (t Shr vglShlUV)]
EndIf
EndIf
Next
End Function

now thats about all there is too it but it doesnt work atm becuse of the fixed point math i think the problem is something todo with yousing diffrent scales for the z and the uv`s do you have a float vesrion cause it would be easier to get going on that then convert it back to fixed point
Challenge Trophies Won:

Offline Devils Child

  • C= 64
  • **
  • Posts: 66
  • Karma: 2
    • View Profile
hm, this looks like that:


also i cant believe that it is so easy...
i'll post a float version here in a few minutes.

edit: here is the code using floats instead of shl-integers
http://www.dc.freecoder-portal.de/upload/files/Devils%20Child/VirtualGL_using_floats.zip (482 KB)

by trying to implement your function into that it looks like that:



another question: you have only modifyed the scan() function and not the filltri() function!?
do we have to change the filltri() function as well, or only the scan() function?
« Last Edit: June 25, 2007 by Devils Child »

Offline Tetra

  • DBF Aficionado
  • ******
  • Posts: 2532
  • Karma: 83
  • Pirate Monkey!
    • View Profile
I'm affraid I have very little experience with int based engine. I think the problem is to do with that.

All I can suggest is if you make a new copy of your VirtualGL and convert it to use floats instead of ints with the u,v and z variables, get that working then convert it into the int based system.

What i'm getting from that new code is a gray car, wich means all the uv are 0 thats caused by

pc1 = 65536.0 / p1d
pc2 = 65536.0 / p2d
pc3 = 65536.0 / p3d

pc1 to pc3 will be 0  because the values are mostly less than 0.5 so change to

pc1# = 65536.0 / p1d
pc2# = 65536.0 / p2d
pc3# = 65536.0 / p3d

but now the texture is fairly distorted.


And finally I missed out the final step as ninno pointed out :)
Challenge Trophies Won:

Offline Devils Child

  • C= 64
  • **
  • Posts: 66
  • Karma: 2
    • View Profile
that's what i'm saying. i have edited my post above while you were writing this.

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
yeah you had the filltri routine correct you need to have the filltri part as tetra said and the scanline part like i said im just fiddling with it right now :)
Challenge Trophies Won:

Offline Tetra

  • DBF Aficionado
  • ******
  • Posts: 2532
  • Karma: 83
  • Pirate Monkey!
    • View Profile
the problem was that you were sending the wrong z values to vgliIntpf functions.

Also the final u v values need to be divided by z or d as you have it.

i've put in the pc code and it seems to be working a charm now. I've had to invert your zbuffer and zbuffer check so that it works with pc mapping.

Have fun :)
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
hehe you bet me to it tetra, one thing to add is that i think this scanline function *might* be a little bit quicker as it only does if checks and a single divide on pixels drawn.

Code: [Select]
Function vgliFillTriLine(p1x, p1d#, p1u#, p1v#, p2x, p2d#, p2u#, p2v#, y)
If p1x = p2x Then Return
If p1x > p2x Then
tx = p1x
td# = p1d
tu# = p1u
tv# = p1v
p1x = p2x
p1d = p2d
p1u = p2u
p1v = p2v
p2x = tx
p2d = td
p2u = tu
p2v = tv
EndIf
If p2x <= 0 Or p1x => vglViewportW Then Return

xlen# = (p2x - p1x)

id# = (p2d - p1d) / xlen#
iu# = (p2u - p1u) / xlen#
iv# = (p2v - p1v) / xlen#

d# = p1d

tw = vglTex\w
th = vglTex\h
u# = p1u;(p1u + vglShlUV2) Mod tw
v# = p1v;(p1v + vglShlUV2) Mod th
tex.vglTexture = vglTex
For x = p1x To p2x
If x => vglViewportW Then Exit
d = d + id
u = u + iu
v = v + iv
   
If x => 0 Then
If d > vglBuffer(x, y) Then
vglBuffer(x, y) = d
w# = 1.0/d
s# = u * w
t# = v * w

If s > tw Then s = 0
If t > th Then t = 0
If s < 0 Then s = tw
If t < 0 Then t = th

rgb = tex\texel[ Int( t ) * tex\h + Int( s ) ]

If rgb <> vglTexMaskColor - 16777216 Then
WritePixelFast x + vglViewportX, y + vglViewportY, rgb
EndIf
EndIf
EndIf

Next
End Function
Challenge Trophies Won:

Offline Devils Child

  • C= 64
  • **
  • Posts: 66
  • Karma: 2
    • View Profile
your scanline function just gets me a black screen. and if i disable z-buffering, it lookes like that:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
did you use tetras code and just replace the scanline function in his uploded version as it works fine here.
Challenge Trophies Won:

Offline Devils Child

  • C= 64
  • **
  • Posts: 66
  • Karma: 2
    • View Profile
oh my....
i just have discovered that you (tetra) have attached a file to your post!!!
and it's working without any glitch!!!
oh thank you sooo much guys!  :updance:
i really appreceate that!
i'll show up the virtualGL lib or even a software renderer as soon as i got it finished!!
bye :):)

« Last Edit: June 25, 2007 by Devils Child »

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17412
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
What an interesting first thread :)

You are most welcome here Devils Child  :hi:

Once you have an understanding of this perspective correct routine you should convert it to C++ or Freebasic (we can help) to render at 4* the resolution with the same speed and  a tenth of the file size :D
Shockwave ^ Codigos
Challenge Trophies Won:

Offline DruggedBunny

  • ZX 81
  • *
  • Posts: 8
  • Karma: 2
    • View Profile
This is *brilliant*. Nice work!

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
ive been thinking and as cool as this is you can speed this up a bit devils child.

from here.
Code: [Select]
If p1y <> p2y Then
For y = p1y To p2y
If y => 0 Then
If y => vglViewportH Then Exit
x1 = vgliIntpf(y, p1y, p3y, p1x, p3x)
;d1# = vgliIntpf(y, p1y, p3y, p1d, p3d)
d1# = vgliIntpf(y, p1y, p3y, pc1, pc3)
u1# = vgliIntpf(y, p1y, p3y, p1u, p3u)
v1# = vgliIntpf(y, p1y, p3y, p1v, p3v)
x2 = vgliIntpf(y, p1y, p2y, p1x, p2x)
;d2# = vgliIntpf(y, p1y, p2y, p1d, p2d)
d2# = vgliIntpf(y, p1y, p2y, pc1, pc2)
u2# = vgliIntpf(y, p1y, p2y, p1u, p2u)
v2# = vgliIntpf(y, p1y, p2y, p1v, p2v)
vgliFillTriLine(x1, d1, u1, v1, x2, d2, u2, v2, y)
EndIf
Next
EndIf
If p2y <> p3y Then
For y = p2y To p3y
If y => 0 Then
If y => vglViewportH Then Exit
x1 = vgliIntpf(y, p1y, p3y, p1x, p3x)
;d1# = vgliIntpf(y, p1y, p3y, p1d, p3d)
d1# = vgliIntpf(y, p1y, p3y, pc1, pc3)
u1# = vgliIntpf(y, p1y, p3y, p1u, p3u)
v1# = vgliIntpf(y, p1y, p3y, p1v, p3v)
x2 = vgliIntpf(y, p2y, p3y, p2x, p3x)
;d2# = vgliIntpf(y, p2y, p3y, p2d, p3d)
d2# = vgliIntpf(y, p2y, p3y, pc2, pc3)
u2# = vgliIntpf(y, p2y, p3y, p2u, p3u)
v2# = vgliIntpf(y, p2y, p3y, p2v, p3v)
vgliFillTriLine(x1, d1, u1, v1, x2, d2, u2, v2, y)
EndIf
Next
EndIf

there is far more divides in there than there needs to be ideally you dont need any you can do this with just adds ie
for x2 you add a fractional amount for each y scanline by running it through this function

Code: [Select]
Function vgliIntp(value, vMin, vMax, retMin, retMax)
Return retMin + (value - vMin) * (retMax - retMin) / (vMax - vMin)
End Function

but if you had to precompute the fractional amount before the for loop then you might have something like this before the for loop

Code: [Select]
PrecomputedXFraction = ( X1 - X2 ) / (Y1 - Y2)
X2 = p2x

and in the for loop you would just do
Code: [Select]
x2 = x2 + PrecomputedXFraction

and the same can be done for all the others does that make sense, if you have a look at my renderer you will see thats what i do.
« Last Edit: June 26, 2007 by ninogenio »
Challenge Trophies Won:

Offline Devils Child

  • C= 64
  • **
  • Posts: 66
  • Karma: 2
    • View Profile
thats a good idea nino. i had this idea before, but there were these matrices issues i had to solve. now that they are working, i will convert UV and Depth back to integers.
then i will replace that interpolation function by real maths :)