WIP 3D Engine [v0.06] (v0.07 preview screenie)

User projects written in or related to FreeBASIC.
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Post by Hezad »

wolstar > thanks :P

Syn9 > Well, in fact a totally free camera is planned :D But the infinite floor stuff is interesting, do you have any link about it ?
D.J.Peters
Posts: 8642
Joined: May 28, 2005 3:28
Contact:

Post by D.J.Peters »

For an infinity ground you need a good and fast FILTER
here one example without a FILTER.

Joshy

Code: Select all

const ScreenWidth = 640
const ScreenHeight= 480

type VECTOR3D
  as single x,y,z
  as single w
end type

type PLANE_t
  as VECTOR3D Position
  as VECTOR3D Normale
  as VECTOR3D A
  as VECTOR3D B
  as single   MaxWidth,NP,DN
  as single   al,be,ga
end type

dim shared Plane   as PLANE_t
dim shared Texture as integer ptr

' 2x2 pixel in this case
sub CreateTexture()
  if Texture<>0 then return
  Texture=callocate(2*2*4)
  Texture[0]=&HFFFFFF
  Texture[2]=&HFFFFFF
end sub

sub VecRotate( _
          byref RetVec as VECTOR3D, _
                SrcVec as VECTOR3D, _
                a      as single, _
                b      as single, _
                g      as single)
  a*=atn(1)/45
  b*=atn(1)/45
  g*=atn(1)/45
  dim as single cox = Cos(a), coy = Cos(b), coz = Cos(g)
  dim as single six = Sin(a), siy = Sin(b), siz = Sin(g)

  dim as single Y = SrcVec.Y * cox - SrcVec.Z * six
  dim as single Z = SrcVec.Y * six + SrcVec.Z * cox
  dim as single X = SrcVec.X * coy +        Z * siy
         RetVec.Z =-SrcVec.X * siy +        Z * coy
         RetVec.X =        X * coz -        Y * siz
         RetVec.Y =        X * siz +        Y * coz
end sub

const MiddleWidth = ScreenWidth *0.5
const MiddleHeight= ScreenHeight*0.5
const ScaleInv    = 1/ScreenWidth

Function ShowPoint(X as integer, _
                   Y as integer) as integer
  dim as VECTOR3D ODES=any,HitP=any
  dim as single  L=any ' length of ray if hits
  dim as integer u=any,v=any ' texture coords
  ' shot a ray thrue every pixel
  With ODES
    .X = (X-MiddleWidth ) * ScaleInv
    .Y = (MiddleHeight-Y) * ScaleInv
    .Z = 1
  End With
  With Plane
    ' dot = ray * plane normale
    .DN=ODes.x*.Normale.x _
       +ODes.y*.Normale.y _
       +       .Normale.z ' rey.destination.z is = 1
    if .DN=0 then return &H5555CC
    L= .NP/.DN ' parallel or far away
    if (L<1) or (L>.MaxWidth) then return &H5555CC
    
    ' get ray hitpont
    HitP.x=ODes.x*L-.Position.x
    HitP.y=ODes.y*L-.Position.y
    HitP.z=       L-.Position.z
    ' rotate it back in camera space
    VecRotate HitP,HitP,-.al,-.be,-.ga
    
    ' optional get texture coords
    u=abs(HitP.x/.MaxWidth)*128
    v=abs(Hitp.z/.MaxWidth)*128
    ' texture is in this case 2x2
    u and=1:v and=1':u shl=1
  end with
  return texture[u+v]
End Function

sub Render
  dim as integer ptr lpScreen
  lpScreen=screenptr
  For y as integer=0 to ScreenHeight-1
    For X as integer=0 to ScreenWidth-1
      *lpScreen=ShowPoint(x,y)
      lpScreen+=1
    next
  next
end sub




'
' main
'
dim as single w
dim as double t1,t2
dim as integer frames,fps
ScreenRes ScreenWidth,ScreenHeight,24,,1
CreateTexture
Plane.MaxWidth=ScreenWidth*4

t1=timer
while inkey<>chr(27)
  With Plane
    .Normale.x=0:.Normale.y=1:.Normale.z=0
    .A.x      =0:.A.y      =0:.A.z      =1
    .B.x      =1:.B.y      =0:.B.z      =0
    VecRotate .Normale,.Normale,.al,.be,.ga
    VecRotate .A      ,.A      ,.al,.be,.ga
    VecRotate .B      ,.B      ,.al,.be,.ga
    .NP=.Normale.x*.Position.x _
       +.Normale.y*.Position.y _
       +.Normale.z*.Position.z
    screenlock:cls
    Render
    locate 1,1:print fps
    screenunlock
    ' camera
    .Position.y=sin(w*3)*300-350
    .al=sin(w*2.0)*1
    .be=cos(w    )*360
    .ga=sin(w*0.5)*5
    w+=0.005:if w>(atn(1)*8)  then w=0
  end with
  frames+=1
  if frames=100 then
    t2=timer
    fps=frames/(t2-t1)
    t1=t2:frames=0
  end if
wend
end
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Post by Hezad »

MESSAGE FOR MODERATORS :
thanks for the change :)




D.J. Peter > Thanks for the code :) Since Mip-mapping and filtering are on my todo list, your code will be really useful :) thanks, I'll "analyze" it.




Engine News :

Before starting optimizations, I wanted to modularize and reorganize a bit my code to help comprehension. So here are the news :

- Modularization : code broken into smaller header files (Engine.bi, DataTypes.bi, Materials.bi)
- Texture BMP loader
- Backface Culling
- /!\ New material Type to handle .. well, materials :p
+ Effective way (I hope) to create/edit materials in code
- Texture tiling routine
- Changed textures of the example for realistic ones


An example of material editing :


Code:

Code: Select all

Dim as ObjectT MyObject

MyObject.GenerateCube(x0,y0,z0,SideSize)

Dim as TextureT CubeTex

CubeTex.LoadBMP "Texture_Cube.bmp"


Dim as MaterialT CubeMaterial

CubeMaterial.Edit
    
    Mat_Shader GOURAUD_SHADER
    
    Mat_Texture CubeTex,tileX,tileY

    Mat_Diffuse r,g,b

    Mat_ambient r,g,b

CubeMaterial.End_Edit

MyObject.Assign_Material CubeMaterial

Image
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Post by Hezad »

Hey :)

I just wondered something ... Couldn't I win some FPS by running subs in different threads ?

eg : the different filling procedures in a thread A, Shaders processing in a thread B, and filtering in a thread C ?
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Post by Hezad »

A little UP for the question about using different threads :) If so, it could really improve the engine !

By the way, Mip Mapping is being implemented right now. I just have to handle some errors with 'my' image ptr format and apply a filter and I'll post the updated code here :)
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Post by Hezad »

Big update :)

I'm now on the v0.4 and a lot of things changed since the previous version :)

A screenshot :
Image

I don't really know which version I lastly posted here but here are the last changes :
v0.04 Changes List



MAJOR :

- Big Optimization with the Shaders calculations.
> Shaders are now calculated only on visible triangles

- Big Optimization while computing mipMap level
> MipMap level is now calculated only once per scanline

- Camera Rotation handling.
> Camera can now rotate according to Y axis and X axis

- Added Init_Engine Sub.
> User can now choose desired resolution

- Added GenerateTore Sub.
> object.GenerateTore(x0,y0,z0,r1,r2,nbfaces)

- material Ambient is modified when Diffuse is modified.
> Can still modify the ambiant after the diffuse modification.


Minor :

- Camera can now translate in world space or in View space
> Move_Camera X,Y,Z, SPACE (IN_VIEWPOS or IN_WORLD)

- Fixed a bug with the Z-Buffer handling

- Fixed a bug in the untextured rendering

You can move in the world with the keyboard arrows (left/right control the camera angle)


Download :
Engine v0.04


Could you please tell me how many FPS you got ?

thanks :D
Alterac
Posts: 33
Joined: Aug 15, 2008 18:02

Post by Alterac »

12fps 800-830 triangles

Ati x1400 w/256mb
T7200 Dual Core
1gb system ram.


Looks good, but even at like 10 triangles, I only got 30fps.

Have you tried to pregen your Sin and Cos tables?

Oh and lol. I love the loops in the Generate Floor function.

Code: Select all

for i as integer = -1 to 1
            
            if i=0 then i=1
            
            for j as integer = -1 to 1
            
                if j=0 then j=1
                
                Flo.Triangle(Flo.nb_triangles).Vertex(0).pos3d.x = i*lSize+lSize
                Flo.Triangle(Flo.nb_triangles).Vertex(0).pos3d.y = 0    
                Flo.Triangle(Flo.nb_triangles).Vertex(0).pos3d.z = j*lSize+lSize
                Flo.Triangle(Flo.nb_triangles).Vertex(0).U = 1
                Flo.Triangle(Flo.nb_triangles).Vertex(0).V = 0
                
                Flo.Triangle(Flo.nb_triangles).Vertex(1).pos3d.x = i*lSize-lSize
                Flo.Triangle(Flo.nb_triangles).Vertex(1).pos3d.y = 0
                Flo.Triangle(Flo.nb_triangles).Vertex(1).pos3d.z = j*lSize+lSize
                Flo.Triangle(Flo.nb_triangles).Vertex(1).U = 0
                Flo.Triangle(Flo.nb_triangles).Vertex(1).V = 0
                
                Flo.Triangle(Flo.nb_triangles).Vertex(2).pos3d.x = i*lSize-lSize
                Flo.Triangle(Flo.nb_triangles).Vertex(2).pos3d.y = 0
                Flo.Triangle(Flo.nb_triangles).Vertex(2).pos3d.z = j*lSize-lSize
                Flo.Triangle(Flo.nb_triangles).Vertex(2).U = 0
                Flo.Triangle(Flo.nb_triangles).Vertex(2).V = 1
                
                Flo.Triangle(Flo.nb_triangles+1).Vertex(0).pos3d.x = i*lSize+lSize
                Flo.Triangle(Flo.nb_triangles+1).Vertex(0).pos3d.y = 0
                Flo.Triangle(Flo.nb_triangles+1).Vertex(0).pos3d.z = j*lSize+lSize
                Flo.Triangle(Flo.nb_triangles+1).Vertex(0).U = 1
                Flo.Triangle(Flo.nb_triangles+1).Vertex(0).V = 0
                
                Flo.Triangle(Flo.nb_triangles+1).Vertex(1).pos3d.x = i*lSize-lSize
                Flo.Triangle(Flo.nb_triangles+1).Vertex(1).pos3d.y = 0
                Flo.Triangle(Flo.nb_triangles+1).Vertex(1).pos3d.z = j*lSize-lSize
                Flo.Triangle(Flo.nb_triangles+1).Vertex(1).U = 0
                Flo.Triangle(Flo.nb_triangles+1).Vertex(1).V = 1
                
                Flo.Triangle(Flo.nb_triangles+1).Vertex(2).pos3d.x = i*lSize+lSize
                Flo.Triangle(Flo.nb_triangles+1).Vertex(2).pos3d.y = 0
                Flo.Triangle(Flo.nb_triangles+1).Vertex(2).pos3d.z = j*lSize-lSize
                Flo.Triangle(Flo.nb_triangles+1).Vertex(2).U = 1
                Flo.Triangle(Flo.nb_triangles+1).Vertex(2).V = 1
            
                Flo.nb_triangles +=2
            next
        next
    

DrV
Site Admin
Posts: 2116
Joined: May 27, 2005 18:39
Location: Midwestern USA
Contact:

Post by DrV »

Hezad wrote:Hey :)

I just wondered something ... Couldn't I win some FPS by running subs in different threads ?

eg : the different filling procedures in a thread A, Shaders processing in a thread B, and filtering in a thread C ?
Can you do these tasks in parallel? If one task needs the output of another task as its input, then they cannot be run in parallel, and threads would not help.

I imagine your code (I have not inspected it) is something like a pipeline, where each task's input is the output of the previous task; in this case, it is not easy to run two tasks in parallel. However, perhaps you can find some tasks where this is not the case; this would be the place to try threads first. If not, you could try splitting a task into smaller units of work that could be done in parallel (render half the screen in one thread and the other half in another, for example), but this will not be nearly as easy.
Lachie Dazdarian
Posts: 2338
Joined: May 31, 2005 9:59
Location: Croatia
Contact:

Post by Lachie Dazdarian »

20 FPS. Hrm...

Athlon 64 X2 4800+. 2 GB RAM.
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Post by Hezad »

thanks for the replies :)

@Alterac

Code: Select all

Have you tried to pregen your Sin and Cos tables?
Nope. I should but I hadn't done it yet :P

Code: Select all

Oh and lol. I love the loops in the Generate Floor function. 
? lol what's the problem ? I use i and j to add an offset on each quarter of the floor(the floor is composed of 4 quads / 8 triangles).


@DrV
Thanks :) All my procedures use the previously computed procedure indeed. hm.. so threads seem unusable in my case. I'll think about splitting task into smaller units usable in parallel.

@Lachie
Thanks for feedback :)




I see the engine runs between 12 and 20 FPS .. I still have optimizations to do ><
Alterac
Posts: 33
Joined: Aug 15, 2008 18:02

Post by Alterac »

No problem with the loops, It just made me smile :D

and on your threads idea, you could probally spawn your rotateobj as a thread.

As long as it all completes before you draw the object.

oh, and oddly enough if I dont Project_object floor I get a 8fps boost.

Of all the objects, removing the floor is the one that makes a nice difference.

I have been tinkering with it quite a bit, and noticed its not your rotate functions that are slowing things down.

Its the projection function.

I can rotate all 21 of the little squares and only lose 1fps, but if I start removing objects it speeds it up greatly.

It also doesnt seem to matter if its texture mapped, or gourad shaded.
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Post by Hezad »

Thanks for feedback and for all your tests Alterac :)
No problem with the loops, It just made me smile :D
okay ^^ Sorry then, I thought you noticed something wrong in it :)
and on your threads idea, you could probally spawn your rotateobj as a thread. As long as it all completes before you draw the object.
Well I'll try this but as you said, the rotations are not the procedures which really make the program to slow down.
oh, and oddly enough if I dont Project_object floor I get a 8fps boost.

Of all the objects, removing the floor is the one that makes a nice difference.
Yep And I think it's because of my clipping function since the floor is the only object which is almost always clipped. I must work on it but I don't really know what to change in it for now.

Its the projection function.

I can rotate all 21 of the little squares and only lose 1fps, but if I start removing objects it speeds it up greatly.
Normal, the project_object sub is in fact the procedure calling all the rendering pipeline for each object :

in order :

- Camera Space transformation
- First Clipping (suppress objects lying totally outside the frustum)
- BackFace Culling
- Shading
- Clipping (chopping triangles lying ON the frustum, this one is very laggy)
- Projection
- Rendering

I should change the name of this sub since it's not only the projection anymore :P But since almost everything is calculated in the project_object sub, it's normal all the FPS loss come from it.


Thanks again for your tests :)
TheMG
Posts: 376
Joined: Feb 08, 2006 16:58

Post by TheMG »

Its great, fantastic that you got it done from scratch! However, it runs a bit slow, 20 ish fps at 640x480 for me, is blitting to the screen buffer the fastest method?
1000101
Posts: 2556
Joined: Jun 13, 2005 23:14
Location: SK, Canada

Post by 1000101 »

TheMG wrote:[...] is blitting to the screen buffer the fastest method?
Assuming the screen is locked, it doesn't matter as it's no different then any other block of memory. The screen is resident in user space and is converted in the background to the system specific format and hardware buffer.
Hezad
Posts: 469
Joined: Dec 17, 2006 23:37
Contact:

Post by Hezad »

@the mg :

thanks :) yeah it needs to be optimized a lot :/



Added some colors and modified the floor generation routine :

Image
Image
Post Reply