Author Topic: WIP 3D Engine (Update : v0.07 screenie preview) [v0.06]  (Read 108839 times)

0 Members and 1 Guest are viewing this topic.

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17422
  • Karma: 499
  • evil/good
    • View Profile
    • My Homepage
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #40 on: August 28, 2008 »
:)

3D clipping means that you will have to chop up some triangles, it's different to just simple clipping to the viewport, you need to be able to calculate where your triangles intersect the view frustrum and possibly split them into more triangles.

For example consider this triangle;
Code: [Select]
|\
|  \
|    \
|      \
|        \
|          \
|_______\

and it intersects  the view frustrum;

Code: [Select]
  |\
_|_\_______________
  |    \
  |      \
  |        \
  |          \
  |_______\

Can be chopped up like this;


Code: [Select]
 
___________________
  |   / \
  | /     \
  |_____\

The part of the triangle that is outside the viwe area is discarded and two triangles are computed, includin new uv co-ordinates.

Not as hard as it sounds, a clue is you need to work out where the edges of the triangle intersect the clipping planes so that you can chop up the triangle :)

If you need more detailed help, ask away :)
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #41 on: August 29, 2008 »
aah okay now I got it, thanks ^^ I didn't understand the fact that I have to "create" new triangles when the current triangle have a part clipped.

Okay, so now I got it, i'll work on it. I still didn't coded the perspective correct mapping (I had a few tries but I didn't interpolate 1/z,u/z and v/z in a good way).

Anyway, I won't be at home for a week so I won't be able to work on it but once i'll get back, correct texture mapping and 3D clipping will be the first things i'll work on. And then, working on reducing the single>integer conversions. And then, maybe mip mapping :D

Still, while I were trying the perspective correct texture mapping, I reorganized a bit the code. So, a little update before the big stuff :

- It supports any number of lights (Add_Light, Set_Light)
- The projection/Z-buffer now recoded with a comprehensible Z-axis handling (It was needed for the 3d clipping and the correct texture mapping)
- New handling of shader calc and filling with user-friendly subs (Set_shader(), Set_Texture()) : if no texture is assigned to an object, it will automatically be rendered with the selected shader)

Thanks for your explanations everyone and see ya in a week or so !

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17422
  • Karma: 499
  • evil/good
    • View Profile
    • My Homepage
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #42 on: August 29, 2008 »
It's cool that you continue to work on this :) It's been a nice topic so far, hopefully we'll see you implimenting clipping and mip mapping soon.

You will definately need to clip by chopping up triangles because you'll need to clip the triangles according to their depth as well as the x,y position :)
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #43 on: August 29, 2008 »
Quote
If x>0 and x<xRes and y>0 and y<yRes then putPixel
If I had 2 tris filling the screen, that would mean I did this test 640x480 times with every single pixel passing he test, but if I knew the two tris were on screen before I tried drawing them I could remove all these 4 checks from every pixel.  That would be a massive speed up!  The chopping up might sound complicated, but it's worth wroking it out.

Jim
PS. btw, you want
Quote
If x>=0 and x<xRes and y>=0 and y<yRes then putPixel
otherwise you won't be able to plot anything on the first scanline or the left column of pixels.
Challenge Trophies Won:

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #44 on: September 07, 2008 »
Hey :) I'm back :D

Well, I wanted to post a perspective correct mapping to celebrate the thing but nothing to do, I tried at least 4 or 5 times to rewrite the sub, it doesn't work...

With the advices provided here and the documentation on the internet, I understood that I should interpolate u/z and v/z (and 1/z but since I already know Z from the Z-Buffer calc, I also tried to use it instead of 1/z), and then multiply by the current Z to get the good uv coords. But erm.. It doesn't work >< It makes the program to crash (I guess the uv coords are too large for the texture ptr). Here is the code used in the subs, I hope it's readable :

Code: [Select]
Sub TSLine(ByVal x1 as integer,ByVal x2 as integer, y as integer,ByVal U1 as single,ByVal V1 as single,ByVal U2 as single,ByVal V2 as single,ByVal z1 as integer,ByVal z2 as integer,byval Texture as TextureT, r1 as integer,r2 as integer,g1 as integer,g2 as integer,b1 as integer,b2 as integer,_z1 as single,_z2 as single)
   
    dim as single dR,dG,dB
    dim as single R,g,b
   
    dim as single sr1,sr2,sg1,sg2,sb1,sb2
   
    dim as single dU,dV,dZ,U,V
    dim as single Uu1,Vv1,Uu2,Vv2
   
    dim as integer itx1,itx2,zz1,zz2
    Dim as single CurZ,xDiv,Cur_Z,_zz1,_zz2,d_Z
   
    if x1<x2 then
        zz1 = z1
        zz2 = z2
       
        _zz1 = _z1
        _zz2 = _z2
       
        itx1 = x1
        itx2 = x2
       
        Uu1 = u1
        Uu2 = u2
        Vv1 = v1
        Vv2 = v2
       
        sr1 = r1
        sr2 = r2
        sg1 = g1
        sg2 = g2
        sb1 = b1
        sb2 = b2
    else
        zz1 = z2
        zz2 = z1
       
        _zz1 = _z2
        _zz2 = _z1
       
        itx1 = x2
        itx2 = x1
       
        Uu1 = u2
        Uu2 = u1
        Vv1 = v2
        Vv2 = v1
       
        sr1 = r2
        sr2 = r1
        sg1 = g2
        sg2 = g1
        sb1 = b2
        sb2 = b1
    end if
   
    'Uu1 *= Texture.Size.x
    'Uu2 *= Texture.Size.x
    'Vv1 *= Texture.Size.y
    'Vv2 *= Texture.Size.y
   
    xDiv = 1/(itx2 - itx1)
   
    dR = xDiv * (sr2 - sr1)
    dG = xDiv * (sg2 - sg1)
    dB = xDiv * (sb2 - sb1)
   
    dZ = xDiv * (zz2 - zz1)
    d_Z = xDiv * (_zz2 - _zz1)
   
    dU = xDiv * (Uu2 - Uu1)
    dV = xDiv * (Vv2 - Vv1)
   
    CurZ = zz1
    Cur_Z = _zz1
   
    U = Uu1
    V = Vv1
   
    r = sr1
    g = sg1
    b = sb1
   
    dim as single ValU,ValV
    dim as integer it
    Dim as integer CurTex,Cr,Cg,Cb
   
   
    it = y*xRes + itx1
   
    for i as integer = itx1 to itx2-1

        if y>=0 and y<yRes and i>=0 and i<xRes then
           
            If (FOV - (-Camera.pos.z + CurZ))>0 then
               
                If Curz < ZBuffer(it) then
                   
                    ZBuffer(it) = CurZ
                   
                    'ValU = U*CurZ   '' (U/Z)*Z
                    'ValV = V*CurZ   '' (V/Z)*Z
                   
                    ValU = U/Cur_Z  '' (U/Z)/(1/Z)
                    ValV = V/Cur_Z  '' (V/Z)/(1/Z)
                   
                    CurTex = Texture.GFX[int(ValU*Texture.Size.x)+Texture.Size.x*int(ValV*Texture.Size.y)]
                   
                    Cb = ((CurTex and 255))*b*0.003921  '' 1/255
                    Cg = ((CurTex shr 8) and 255)*g*0.003921
                    Cr = ((CurTex shr 16) and 255)*r*0.003921
                   
                    ScrPtr[it] = rgb(Cr,Cg,Cb)
                   
                end if
            end if
       
        end if
       
        it+=1
       
        U += dU
        V += dV
       
        Cur_Z += d_Z
       
        r += dR
        g += dG
        b += dB
       
        curZ += dZ
       
    Next
   
End Sub
   
Sub Texture_Map_Shaded(ByVal Triangle as TriangleT, _
                       ByVal Texture as TextureT)      '' UV's saved in the Triangle.Vertex Type
   
   
    '' Sorting Y values
    if Triangle.Vertex(1).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(1),Triangle.Vertex(0)
    end if
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(0).Pos2d.y then
        swap Triangle.Vertex(2),Triangle.Vertex(0)
    end if
   
    if Triangle.Vertex(2).Pos2d.y < Triangle.Vertex(1).Pos2d.y then
        swap Triangle.Vertex(2),Triangle.Vertex(1)
    end if
   
    dim as integer dx1,dy1,dx2,dy2,dx3,dy3
    dim as single Slope1,Slope2,Slope3, dYDiv
   
    dim as single dU1,dU2,dU3,dV1,dV2,dV3
    dim as single USlope1,USlope2,USlope3
    dim as single VSlope1,VSlope2,VSlope3
   
    Dim as integer dz1,dz2,dz3,d_z1,d_z2,d_z3
    Dim as single zSlope1,zSlope2,zSlope3
    Dim as single _zSlope1,_zSlope2,_zSlope3
   
    dim as integer dr1,dg1,db1,dr2,dg2,db2,dr3,dg3,db3
    dim as single RSlope1, GSlope1,BSlope1
    dim as single RSlope2, GSlope2,BSlope2
    dim as single RSlope3, GSlope3,BSlope3
   
    '' interpolate 0 to 1 (pos + color)
   
    dZ1 = Triangle.Vertex(1).pos3d.z - Triangle.Vertex(0).pos3d.z
    d_z1 = 1/(Triangle.Vertex(1).pos3d.z+Triangle.Parent_Center.z) - 1/(Triangle.Vertex(0).pos3d.z+Triangle.Parent_Center.z)
   
    dX1 = Triangle.Vertex(1).pos2d.x - Triangle.Vertex(0).pos2d.x
    dY1 = Triangle.Vertex(1).pos2d.y - Triangle.Vertex(0).pos2d.y
   
    dU1 = Triangle.Vertex(1).U/(Triangle.Vertex(1).pos3d.z+Triangle.Parent_Center.z) - Triangle.Vertex(0).U/(Triangle.Vertex(0).pos3d.z+Triangle.Parent_Center.z)
    dV1 = Triangle.Vertex(1).V/(Triangle.Vertex(1).pos3d.z+Triangle.Parent_Center.z) - Triangle.Vertex(0).V/(Triangle.Vertex(0).pos3d.z+Triangle.Parent_Center.z)
   
    dr1 = Triangle.Vertex(1).color.r - Triangle.Vertex(0).color.r
    dg1 = Triangle.Vertex(1).color.g - Triangle.Vertex(0).color.g
    db1 = Triangle.Vertex(1).color.b - Triangle.Vertex(0).color.b
   
    if dY1 <> 0 then
       
        dYDiv = 1/dY1
       
        zSlope1 = dZ1 * dYDiv
        _zSlope1 = d_Z1 * dYDiv
       
        Slope1 = dX1 * dYDiv
       
        USlope1 = dU1 * dYDiv
        VSlope1 = dV1 * dYDiv
       
        RSlope1 = dR1 * dYDiv
        GSlope1 = dG1 * dYDiv
        BSlope1 = dB1 * dYDiv
       
    else
       
        zSlope1 = 0
        _zSlope1 = 0
       
        Slope1 = 0
       
        USlope1 = 0
        VSlope1 = 0
       
        RSlope1 = 0
        GSlope1 = 0
        BSlope1 = 0
    End if
   
   
    '' interpolate 1 to 2
   
    dZ2 = Triangle.Vertex(2).pos3d.z - Triangle.Vertex(1).pos3d.z
    d_Z2 = 1/(Triangle.Vertex(2).pos3d.z+Triangle.Parent_Center.z) - 1/(Triangle.Vertex(1).pos3d.z+Triangle.Parent_Center.z)
   
    dX2 = Triangle.Vertex(2).pos2d.x - Triangle.Vertex(1).pos2d.x
    dY2 = Triangle.Vertex(2).pos2d.y - Triangle.Vertex(1).pos2d.y
   
    dU2 = Triangle.Vertex(2).U/(Triangle.Vertex(2).pos3d.z+Triangle.Parent_Center.z) - Triangle.Vertex(1).U/(Triangle.Vertex(1).pos3d.z+Triangle.Parent_Center.z)
    dV2 = Triangle.Vertex(2).V/(Triangle.Vertex(2).pos3d.z+Triangle.Parent_Center.z) - Triangle.Vertex(1).V/(Triangle.Vertex(1).pos3d.z+Triangle.Parent_Center.z)

    dr2 = Triangle.Vertex(2).color.r - Triangle.Vertex(1).color.r
    dg2 = Triangle.Vertex(2).color.g - Triangle.Vertex(1).color.g
    db2 = Triangle.Vertex(2).color.b - Triangle.Vertex(1).color.b

    if dY2 <> 0 then
       
        dYDiv = 1/dY2
       
        zSlope2 = dZ2 * dYDiv
        _zSlope2 = d_Z2 * dYDiv
       
        Slope2 = dX2 * dYDiv
       
        USlope2 = dU2 * dYDiv
        VSlope2 = dV2 * dYDiv
       
        RSlope2 = dR2 * dYDiv
        GSlope2 = dG2 * dYDiv
        BSlope2 = dB2 * dYDiv
       
    else
       
        zSlope2 = 0
        _zSlope2 = 0
       
        Slope2 = 0
       
        USlope2 = 0
        VSlope2 = 0
       
        RSlope2 = 0
        GSlope2 = 0
        BSlope2 = 0
    End if
   
   
    '' interpolate 0 to 2
   
    dZ3 = Triangle.Vertex(0).pos3d.z - Triangle.Vertex(2).pos3d.z
    d_Z3 = 1/(Triangle.Vertex(0).pos3d.z+Triangle.Parent_Center.z) - 1/(Triangle.Vertex(2).pos3d.z+Triangle.Parent_Center.z)
   
    dX3 = Triangle.Vertex(0).pos2d.x - Triangle.Vertex(2).pos2d.x
    dY3 = Triangle.Vertex(0).pos2d.y - Triangle.Vertex(2).pos2d.y
   
    dU3 = Triangle.Vertex(0).U/(Triangle.Vertex(0).pos3d.z+Triangle.Parent_Center.z) - Triangle.Vertex(2).U/(Triangle.Vertex(2).pos3d.z+Triangle.Parent_Center.z)
    dV3 = Triangle.Vertex(0).V/(Triangle.Vertex(0).pos3d.z+Triangle.Parent_Center.z) - Triangle.Vertex(2).V/(Triangle.Vertex(2).pos3d.z+Triangle.Parent_Center.z)

    dr3 = Triangle.Vertex(0).color.r - Triangle.Vertex(2).color.r
    dg3 = Triangle.Vertex(0).color.g - Triangle.Vertex(2).color.g
    db3 = Triangle.Vertex(0).color.b - Triangle.Vertex(2).color.b

    if dY3 <> 0 then
       
        dYDiv = 1/dY3
       
        zSlope3 = dZ3 * dYDiv
        _zSlope3 = d_Z3 * dYDiv
       
        Slope3 = dX3 * dYDiv
       
        USlope3 = dU3 * dYDiv
        VSlope3 = dV3 * dYDiv
       
        RSlope3 = dR3 * dYDiv
        GSlope3 = dG3 * dYDiv
        BSlope3 = dB3 * dYDiv
       
    else
       
        zSlope3 = 0
        _zSlope3 = 0
       
        Slope3 = 0
       
        USlope3 = 0
        VSlope3 = 0
       
        RSlope3 = 0
        GSlope3 = 0
        BSlope3 = 0
       
    End if
   
   
    '' Drawing
   
    '' Top
   
    dim as single CurX1=Triangle.Vertex(0).pos2d.x, CurX2=Triangle.Vertex(0).pos2d.x
    dim as single CurU1, CurU2,_
                  CurV1, CurV2
   
    dim as single CurR1=Triangle.Vertex(0).Color.r,_
                   CurG1=Triangle.Vertex(0).Color.g,_
                   CurB1=Triangle.Vertex(0).Color.b,_
                   CurR2=Triangle.Vertex(0).Color.r,_
                   CurG2=Triangle.Vertex(0).Color.g,_
                   CurB2=Triangle.Vertex(0).Color.b
   
    dim as single CurZ1=Triangle.Vertex(0).pos3d.z, CurZ2=Triangle.Vertex(0).pos3d.z
    dim as single Cur_Z1, Cur_Z2
   
    CurZ1 += Triangle.Parent_Center.z
    CurZ2 += Triangle.Parent_Center.z
   
    CurU1 = Triangle.Vertex(0).U/CurZ1
    CurV1 = Triangle.Vertex(0).V/CurZ1
    CurU2 = Triangle.Vertex(0).U/CurZ1
    CurV2 = Triangle.Vertex(0).V/CurZ1
   
    Cur_Z1 = 1/CurZ1
    Cur_Z2 = 1/CurZ2
   
    'BufferIter = Triangle.Vertex(0).pos2d.y * xRes
   
    For y as integer = Triangle.Vertex(0).pos2d.y to Triangle.Vertex(1).pos2d.y-1
       
        TSLine(CurX1,CurX2,y,CurU1,CurV1,CurU2,CurV2, CurZ1, CurZ2, Texture,CurR1,CurR2,CurG1,CurG2,CurB1,CurB2,Cur_Z1,Cur_Z2)
       
        CurZ1 += zSlope1
        CurZ2 += zSlope3
       
        Cur_Z1 += _zSlope1
        Cur_Z2 += _zSlope3
       
        CurU1 += USlope1
        CurU2 += USlope3
        CurV1 += VSlope1
        CurV2 += VSlope3
       
        CurX1 += Slope1
        CurX2 += Slope3
       
        CurR1 += RSlope1
        CurR2 += RSlope3
        CurG1 += GSlope1
        CurG2 += GSlope3
        CurB1 += BSlope1
        CurB2 += BSlope3
       
        'BufferIter += xRes
       
    Next
   
    '' down
   
    CurZ1 = Triangle.Vertex(1).pos3d.z+Triangle.Parent_Center.z
    Cur_Z1 = 1/CurZ1
   
    CurU1 = Triangle.Vertex(1).U/CurZ1
    CurV1 = Triangle.Vertex(1).V/CurZ1
   
    CurX1 = Triangle.Vertex(1).pos2d.x
   
    CurR1 = Triangle.Vertex(1).color.r
    Curg1 = Triangle.Vertex(1).color.g
    Curb1 = Triangle.Vertex(1).color.b
   
    For y as integer = Triangle.Vertex(1).pos2d.y to Triangle.Vertex(2).pos2d.y-1
       
        TSLine(CurX1,CurX2,y,CurU1,CurV1,CurU2,CurV2, CurZ1, CurZ2, Texture,CurR1,CurR2,CurG1,CurG2,CurB1,CurB2,Cur_Z1,Cur_Z2)
       
        CurZ1 += zSlope2
        CurZ2 += zSlope3
       
        Cur_Z1 += _zSlope2
        Cur_Z2 += _zSlope3
       
        CurX1 += Slope2
        CurX2 += Slope3
       
        CurU1 += USlope2
        CurU2 += USlope3
        CurV1 += VSlope2
        CurV2 += VSlope3
       
        CurR1 += RSlope2
        CurR2 += RSlope3
        CurG1 += GSlope2
        CurG2 += GSlope3
        CurB1 += BSlope2
        CurB2 += BSlope3
       
    Next
   
End Sub

Can you see what's wrong in there ?
In the code, variables like _z or d_z or Cur_Z means 1/z (respectively  1/z, d(1/z) and Current1/Z) and I kept the name U and V to contain U/z and V/z.

Thanks in advance :)


(update in code)
« Last Edit: September 07, 2008 by Hezad »

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17422
  • Karma: 499
  • evil/good
    • View Profile
    • My Homepage
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #45 on: September 07, 2008 »
You have almost certainly answered your own question, because you are not interpolating 1/z, but instead using your own z-buffer calculation and then multiplying that by a factor to use in your equation, then it' more than likely trying to fetch texels from way outside your texture map.

I sat down to read through the source, I am sorry, it's blurry to me with a lot of similar variables that I can't seem to keep track of easily. Anyway..

My advice to you would be to stick to interpolating 1/z.

In a nutshell, you should be doing something similar to this;

Interpolate U/Z, interpolate V/Z and interpolate 1/Z

To get your texels;

((U/Z) / (1/Z)) * Z = U
((V/Z) / (1/Z)) * Z = V

Something like that. It's been a long time since I did it, but I think that's about right.

It's not the fastest way of doing this but you should probably get it working this way first.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #46 on: September 07, 2008 »
Some notes:
Code: [Select]
    if x1<x2 then
        zz1 = z1
        zz2 = z2
       
        _zz1 = _z1
        _zz2 = _z2
       
        itx1 = x1
        itx2 = x2
       
        Uu1 = u1
        Uu2 = u2
        Vv1 = v1
        Vv2 = v2
       
        sr1 = r1
        sr2 = r2
        sg1 = g1
        sg2 = g2
        sb1 = b1
        sb2 = b2
    else
        zz1 = z2
        zz2 = z1
       
        _zz1 = _z2
        _zz2 = _z1
       
        itx1 = x2
        itx2 = x1
       
        Uu1 = u2
        Uu2 = u1
        Vv1 = v2
        Vv2 = v1
       
        sr1 = r2
        sr2 = r1
        sg1 = g2
        sg2 = g1
        sb1 = b2
        sb2 = b1
    end if
better use a vertexstructure and just swap the pointers.
you don't even have to care about this if all polygons are defined in equal orientation and backface-culling is used to remove all polygons not facing the viewer (so the orientation of x1/x2 will never change).

Code: [Select]
    xDiv = 1/(itx2 - itx1)
   
    dR = xDiv * (sr2 - sr1)
    dG = xDiv * (sg2 - sg1)
    dB = xDiv * (sb2 - sb1)
   
    dZ = xDiv * (zz2 - zz1)
these gradients across your polygon are linear, this means they are the same for every scanline.
just calculate them once for the longest scanline (biggest deltax: highest precision).
this also means you just have to keep track of u,v,z of the left side of your polygon.

Code: [Select]
if y>=0 and y<yResyou don't have to do this for every pixel of a scanline.
check this before you enter the inner loop.

Code: [Select]
if i>=0 and i<xRes thendon't do this for every pixel either.
instead just test how many pixels are "out" on the left side and update u,v,z (eg. deltaU*pixelsToSkip).
the pixels on the right can just be skipped.
when you interpolating x along your polygon edges, the starting "x" for each scanline is actually a floating-point value.
you should take this into account and update the starting u,v,z of each scanline by a fraction of your deltas (how much is missing from the actual floating-point "x" to the rounded integer-pixel-position).
this is necessary for "y", too and can incorporate clipping on the x/y-axes for free.

Code: [Select]
If (FOV - (-Camera.pos.z + CurZ))>0 thenif this is some approach of z-clipping, drop it. it doesn't work.
you must perform z-clipping before doing perspective division.
when z gets near 0 (and even flips sign right afterwards) your 2d-coordinates break.

Code: [Select]
ValU = U/Cur_Z
ValV = V/Cur_Z
this won't result in useful framerates because division is expensive.
instead calculate 1/z (and respective u,v) every 8 or 16 pixels and interpolate linearly between two pairs of perspective correct u,v. if you manage the latter with integer-precision only, you can get the division for free (fpu and cpu run in parallel), but you'll probably need some assembly here.
You can even interpolate u,v bi-linearly (across scanlines, for eaxmple between 4 points of a 8x8-grid):
on an average you just need to calculate two (depending on deltax) additional u,v on a scanline and can skip perspective divide for the next 7 scanlines.
If you want to look deeper into how certain division-algorithms work, you can even approximate the next 1/z (since deltaz is usually small) by a single successive iteration and using the previous result as a starting point.

Code: [Select]
Cb = ((CurTex and 255))*b*0.003921  '' 1/255
Cg = ((CurTex shr 8) and 255)*g*0.003921
Cr = ((CurTex shr 16) and 255)*r*0.003921
as jim pointed out already, the float-to-integer conversion is expensive, too (and the precision is not necessary).
keep the interpolated r,g,b as integers with some additional fixed-point-precision (for example multiply all values by 2^16):
Code: [Select]
Cb = ((CurTex and 255) * (b shr 16) shr 8(but this is essentially what they invented mmx for)
                   
Code: [Select]
CurTex = Texture.GFX[int(ValU*Texture.Size.x)+Texture.Size.x*int(ValV*Texture.Size.y)]Same here (interpolate in integers). You can also try to make your textures' width a power of two, so you can replace the multiply by a shift.

Quote
use the cross-product equation to determine if the points are clockwise or counter clockwise
Rotating the vertices and doing a cross product calc is cheap [...]
The cross-product of the rotated vertices of a triangle gives you the transformed normal-vector of the face.
you can compare it to the view-vector (by a dot-product) to see if it's facing in the same direction.
In camera-space the view-vector is simply (0,0,1) so you just have to look at the sign of the z-component of your (transformed) face-normal (which you can get by just a single dot-product).
« Last Edit: September 08, 2008 by hellfire »
Challenge Trophies Won:

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #47 on: September 08, 2008 »
Hey :)

Shockwave : Well, sorry for the blurry source ^^ Concerning the 1/z interpolation, the point is I also tried it :/ and several times ! But I don't know, maybe I just have to start again this sub..

hellfire : Thanks for all those useful advises/optimizations, I note them all for a future optimization session :p (for now I'm stuck with the perspective correct mapping stuff).
Just a note concerning the number of divisions in the sub : It's just a thing to test the texture mapping ; once it'll work, i'll reduce them drastically :)

Thanks ! I continue my peregrinations in the world of texture mapping :p



edit : Well, I started again the Sub coding but even if I payed attention to the u/z,v/z and 1/z interpolation, there's nothing to do, the result is .. Well let's say it's still not what I was expecting :p Here is a zip with the code and the compiled stuff. So after some reflexion, here is my thoughts :

- Maybe there's a problem with the world origin (Z origin is almost on the cubes line in what you can see in the exe), I guess signs are inverting somewhere ..
- I'm interpolating u/z,v/z and 1/z exactly like I was interpolating u,v, and z (excepted the fact that calculations are based on u/z,v/z and 1/z instead of u,v and z of course) and maybe I shouldn't, I don't know.

Anyway, I'm still on it and I can't wait to start optimizing and to code the clipping with the view frustum :)

edit-edit : In the exe, you can see the floor is rotating, it's totally normal :p it's here to test the mapping.
« Last Edit: September 08, 2008 by Hezad »

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #48 on: September 08, 2008 »
Code review looks OK, all except this bit
Code: [Select]
    CurZ1 += Triangle.Parent_Center.z
    CurZ2 += Triangle.Parent_Center.z
which I don't understand at all.  You need to make sure the z you have divided everything by is the z you use when you interpolate.

Code: [Select]
                ValU = (U_z/Cur_Z) '' ((U/Z)/(1/Z))
                ValV = (V_z/Cur_Z) '' ((V/Z)/(1/Z))
Good optimization, but you can still do
Code: [Select]
ooz = 1/z
ValU = U_z * ooz
ValV = V_z * ooz

Jim

Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17422
  • Karma: 499
  • evil/good
    • View Profile
    • My Homepage
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #49 on: September 09, 2008 »
Seems like you're nearly there :) Keep going!
Shockwave ^ Codigos
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #50 on: September 09, 2008 »
A bit offtopic but might be handy if you start using meshes with more polygons:
You don't need O(n^2) for calculating per-vertex-normals.
Here's a short snippet from a C++ source:
Code: [Select]
// set vertex-normals to 0
for (i = 0; i < numVertices; i++)
  vertices[i].normal.set(0.0, 0.0, 0.0);

for (i = 0; i < numTriangles; i++)
{
  // 3 indices of triangle i into the vertex array
  int idx1= face[i][0];
  int idx2= face[i][1];
  int idx3= face[i][2];

  // get coordinates
  const Vector& v1= vertices[ idx1 ].pos;
  const Vector& v2= vertices[ idx2 ].pos;
  const Vector& v3= vertices[ idx3 ].pos;

  // calculate normal vector
  Vector n= (v2-v1) % (v3-v1)  // cross product

  // add face-normal to all adjacent vertices
  vertices[idx1].normal+= n;
  vertices[idx2].normal+= n;
  vertices[idx3].normal+= n;

  // store the face normal
  faceNormals[i]= n.normalize();
}

// normalize the vertex-normals
for (i = 0; i < numVertices; i++)
  vertices[i].normal.normalize();
« Last Edit: September 10, 2008 by hellfire »
Challenge Trophies Won:

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #51 on: September 09, 2008 »
Code review looks OK, all except this bit
Code: [Select]
    CurZ1 += Triangle.Parent_Center.z
    CurZ2 += Triangle.Parent_Center.z
which I don't understand at all.  You need to make sure the z you have divided everything by is the z you use when you interpolate.


well in fact when I start my interpolation calcs, I use :
Code: [Select]
dZ2 = Triangle.Vertex(2).pos3d.z - Triangle.Vertex(1).pos3d.z
Even if I was using
Code: [Select]
dZ2 = (Triangle.Vertex(2).pos3d.z+TriangleCenter) - (Triangle.Vertex(1).pos3d.z+TriangleCenter)it'd be the same result.

But I have to start interpolation on the good Z value by adding the objectCenter to it : each object vertex have their coordinates in object Space (Origin = object Center)

I tested to add triangleCenter to the vertices before calculating slopes but it's worse :S But strangely (or not?), for the 1/z interpolation, if I use 1/(z+objCenter), it doesn't work at all


Quote
Code: [Select]
                ValU = (U_z/Cur_Z) '' ((U/Z)/(1/Z))
                ValV = (V_z/Cur_Z) '' ((V/Z)/(1/Z))
Good optimization, but you can still do
Code: [Select]
ooz = 1/z
ValU = U_z * ooz
ValV = V_z * ooz

ah yeah, didn't noticed this one :p thanks


Shockwave : I'm still on it !  ;D


hellfire : ah cool :)  as far as I can understand, it calculates the normal on a vertex only 1 time instead of NbAdjacentTriangles times ?

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #52 on: September 09, 2008 »
I just compiled your source, added a texture and it looks fine.
What's the problem?...
Challenge Trophies Won:

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #53 on: September 09, 2008 »
o_O well, Its way better looking for you, it's strange. Anyway, look on the cubes side, we can see a non-well-textured triangle :S

Still, I can't understand why your floor's good looking while mine is completely distorted in the middle...  you only changed your texture ? Same Size ?

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #54 on: September 10, 2008 »
When I compile and run it on a different pc, the floor is black.
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #55 on: September 10, 2008 »
My guess to that, division by 0 somewhere, or division overflow.

Jim


Challenge Trophies Won:

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #56 on: September 10, 2008 »
- division by zero is really probable ! But since it wasn't making my computer to crash, I though the compiler was handling this. But as I see, it really depends about the computer .. grah :S

- division overflow ?

Thanks for the feedback, step by step, i'm sure i'll find where the bug comes from :)

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #57 on: September 10, 2008 »
YEEEEEYYYYYY !!!

Well I got something I think :D
I added an arbitrary number while dividing by Z :

Code: [Select]
_z1 = 1/(Triangle.Vertex(0).pos3d.z+triangle.parent_center.z+1000)
_z2 = 1/(Triangle.Vertex(1).pos3d.z+triangle.parent_center.z+1000)
_z3 = 1/(Triangle.Vertex(2).pos3d.z+triangle.parent_center.z+1000)

Since you spoke about division by 0, I expected it to be in the middle of the plane (its origin) so I added a number (here, 1000) to the divisor and it seems to work for me. The perspective mapping is still not perfect though :/ Anyway, it's way better :D

Here is a screen and a zip(code+exe+textures)



edit : Anyway, it's not a good solution since I could have large objects but far from the observer, And for those objects, I'd need to change the +1000 to a bigger value (it's a totally arbitrary number).. So in fact, i'm just moving the problem here .. I need to find a solution really resolving the problem :/
« Last Edit: September 10, 2008 by Hezad »

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #58 on: September 10, 2008 »
Well done!

"z=0" should be at the position of the camera.
anything that's behind it will be clipped anyway and your problem is solved.
Challenge Trophies Won:

Offline Hezad

  • Sponsor
  • Pentium
  • *******
  • Posts: 613
  • Karma: 44
  • I believe .. in Patrick.
    • View Profile
    • Hezad.com Web hosting
Re: Gouraud Filling (Update : Gouraud Shaded Textures)
« Reply #59 on: September 10, 2008 »
yeah I though about it but my projection equation is :

Code: [Select]
zDiv = 1/(ZOOM + obj.Triangle(i).Vertex(j).ViewPos.z)

obj.Triangle(i).Vertex(j).pos2d.x = xRes*.5 + FOV * obj.Triangle(i).Vertex(j).ViewPos.x * zDiv
obj.Triangle(i).Vertex(j).pos2d.y = yRes*.5 - FOV * obj.Triangle(i).Vertex(j).ViewPos.y * zDiv

Do you think I can get out the ZOOM term without any distortion in some big objects ?

(Well, I just tested, And geting off the zoom term is way better in fact, FOV is much more effective)

A last question about the mapping though : Did you notice there are still some texture deformations when the triangles are close ? Is it normal (an effect I can't avoid) or is there still something not working here ?

thanks again !