Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411493 Posts in 69371 Topics- by 58428 Members - Latest Member: shelton786

April 25, 2024, 04:32:55 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityTownhallForum IssuesArchived subforums (read only)Tutorials3D Rendering (without a third party 3D library)
Pages: [1]
Print
Author Topic: 3D Rendering (without a third party 3D library)  (Read 5619 times)
Linc
Level 0
**


Check It Out Now


View Profile
« on: February 19, 2012, 05:08:56 PM »

I'd be interested in a tutorial or an explanation of some sort on how to render simple 3D polygons or shapes on screen. If anyone knows how to do this without using a third party 3D library, like Direct3D or the like, I would love an explanation. C/C++ or Java is preferred, although some sort of pseudo code is great too. I'm pretty good about figuring stuff out myself, so don't feel like you have to get too specific.
Logged

-Lincoln Bergeson
imaginationac
Level 2
**


Makin' games instead of makin' money.


View Profile WWW
« Reply #1 on: February 19, 2012, 06:34:30 PM »

This is psuedocode

I'll try this out with a cube:
Code:
// Define vertices: for a cube, 8 vertices
Vector3[] vertices = new Vector3[8]; // An array of points with 3 coordinates (x, y, z);
vertices[0] = new Vector3(0, 0, 0);
vertices[1] = new Vector3(1, 0, 0);
vertices[2] = new Vector3(1, 1, 0);
vertices[3] = new Vector3(0, 1, 0);
vertices[4] = new Vector3(0, 0, 1);
vertices[5] = new Vector3(1, 0, 1);
vertices[6] = new Vector3(1, 1, 1);
vertices[7] = new Vector3(0, 1, 1);

// Draw line segments between vertices
drawLine(vertices[0], vertices[1]);
drawLine(vertices[0], vertices[4]);
drawLine(vertices[0], vertices[3]);
drawLine(vertices[2], vertices[6]);
drawLine(vertices[2], vertices[1]);
drawLine(vertices[2], vertices[3]);
drawLine(vertices[7], vertices[3]);
drawLine(vertices[7], vertices[4]);
drawLine(vertices[7], vertices[1]);
drawLine(vertices[5], vertices[4]);
drawLine(vertices[5], vertices[6]);
drawLine(vertices[5], vertices[1]);

That's the jist of it. Define your vertices, and draw line segments between the appropriate vertices.

This is even simplier with polygons as they lie on plane.

Someone who has actually done this with 3D volumes will probably come and point out everything I did wrong  Big Laff.

I didn't mention anything about how you determine perspective (accounting for the third axis), face culling, other advanced topics. Not to mention the above psuedocode is too specific. But it got me thinking, so thanks for that.

For Java:
If I remember correctly, the Oracle SDK comes with packages for drawing 2d and 3d shapes.
Logged

Youtube channel | Charger! Dev Log
              
Linc
Level 0
**


Check It Out Now


View Profile
« Reply #2 on: February 20, 2012, 08:35:54 AM »

OK Thanks, I'll see what I can figure out.
Logged

-Lincoln Bergeson
J. Kyle Pittman
Level 6
*


PostCount++;


View Profile WWW
« Reply #3 on: March 07, 2012, 02:49:46 PM »

This is a pretty big topic, and one that can't be covered in a small amount of pseudocode. That being said, if you're comfortable with 3D math, it's not too complicated in principle. (That being said, I've never written my own software rasterizer, but I'm pretty familiar with how 3D APIs work, so I feel pretty confident I can fill in the blanks.)

Your first step would be to write a triangle rasterizer. Given three 2D points in screen space, you should be able to draw a filled triangle between them. I believe this is typically done by sorting the three points top to bottom, calculating the slopes along each edge, and iterating down each row, drawing left to right to fill that row. This is also where you'd take winding order into account, so you can reject triangles that are ordered clockwise or counterclockwise to cull out backfaces.

From there, you'd want to be able to convert 3D points in world space into 2D points in screen space. This is what projection matrices do, and you should be able to find lots of examples of how to construct a projection matrix on the internets. In short, given the aspect ratio of the screen and the FOV of the view frustum, this matrix projects points from 3D space into 2D space. This will actually give you a 4D vector, where the X and Y components are in screen space and the Z and W components represent the depth in different spaces. You can use these to write to a Z-buffer or W-buffer which you can then use to reject pixels that have already been drawn with a nearer value.

Then you'd probably want to write your own vertex buffer and index buffer formats, and you could decide whether you want to support triangle strips or lists or whatever. Regardless of what format you choose, you're always going to be sending individual triangles in screen space to the rasterizer in the end.

That would get you in the ballpark of a very simple fixed-function 3D API.
Logged

Serapth
Level 2
**


View Profile
« Reply #4 on: March 09, 2012, 11:22:57 AM »

I wrote my own software renderer years ago, because well... you had to.

It's been a long time, but there was one book on the subject that was absolutely required reading, Michael Abrash's Zen of Graphics Programming.  It's out of print, but appears there is a 4$ used option.


It's ancient by todays standards, and is way too low to the metal for most people to get much from it, but for you it's an absolutely perfect read.  The author writes in an easy to read style, and probably taught me more about optimization and graphics than anything one or thing since. I wish I kept all my old paper books ( moving from 2000 sq/ft to 800 sq/ft requires certain sacrifices ), as I would love to re-read this book.


If you've never heard of Michael Abrash ( kids these days! ), his resume is quite impressive.  First he worked on NT 3.1, then was *recruited* by John Carmack to work on the Quake engine, then he worked on the original Xbox.  He then created a software rasterizer for Rad Tools, which was acquired by Intel, where he went on to work on the GPGPU project.  All this time, Gabe Newell has been trying to recruit him to work at Valve ( both had a history together at MS ), which he finally joined.

Michael Abrash is literally a living legend in game programming... that absolutely nobody has ever heard of.  The likes of David Jaffe or Jonathon Blow aren't even worthy of wiping this guys boots!



... end of history lesson.


TL;DR, if you can find a copy of Zen of Graphics Programming for cheap, pick it up.
Logged
Linc
Level 0
**


Check It Out Now


View Profile
« Reply #5 on: March 09, 2012, 03:15:57 PM »

Thanks, Serapth. I'll be sure to buy that book, it looks really interesting. And also thanks a bunch Pirate Hearts, both of you answers where almost exactly what I was looking for.
Logged

-Lincoln Bergeson
berniek
Level 0
*


View Profile
« Reply #6 on: March 09, 2012, 04:09:30 PM »

Also pick up Computer Graphics Principles and Practice by Foley and van Dam. Which is The goto book for any graphics programmer. Contains pseudo C code for everything.

Even Carmack said he was using it a lot while developing Quake.

I bought mine like 15 years ago and I still use it almost daily, it's just that good.
Logged
powly
Level 4
****



View Profile WWW
« Reply #7 on: March 09, 2012, 08:22:41 PM »

I've never felt the need of a projection matrix while software rendering. It just introduces innecessary calculations into the vertex calculations.

If I wanted to get 3D points projected onto the screen, I'd do something like this:

Code:
const float k = screenwidth/2.0f;
void dot3d(float x, float y, float z)
{
    if(z<=.0f)
        return;
    float s = k/z;
    dot2d(screenwidth/2.0f+s*x, screenheight/2.0f+s*y);
    return;
}

k is a constant determining your field of view, and usually it'll be something between screenwidth/4 and screenwidth. With this approach you can render simple starfields and IFS fractals and many other interesting 3D point clouds. This applies to lines and triangles as well, so you can just calculate 2 or 3 coordinates and rasterize the space between those.
Logged
mcc
Level 10
*****


glitch


View Profile WWW
« Reply #8 on: March 10, 2012, 12:00:16 AM »

Note that even if you can do 3D without a library like Direct3D or OpenGL, it is better to do it with one of those two libraries because those libraries can take advantage of GPU acceleration. A software renderer you write yourself will never perform as well as a GPU-accelerated renderer (although there might be reasons you could want to write a software renderer anyway, such as greater flexibility).
Logged

My projects:<br />Games: Jumpman Retro-futuristic platforming iJumpman iPhone version Drumcircle PC+smartphone music toy<br />More: RUN HELLO
powly
Level 4
****



View Profile WWW
« Reply #9 on: March 10, 2012, 04:27:32 AM »

For learning purposes writing a software renderer is a great help - after figuring everything out yourself using the GPU is easy and feels magical. And there are (increasingly few) platforms where you just don't have hardware acceleration Smiley
Logged
cplhasse
Level 1
*


View Profile
« Reply #10 on: April 09, 2012, 05:34:38 PM »

This is more of a math topic than a programming one I think.
There is a formula you can write down to create a projection matrix for an arbitrary projection from 3D -> 2D space, but unless you've studied the math quite a bit it won't make any sense. The relevant topic is projective geometry and you'll need to be fairly comfortable with linear algebra to get anything out of it. It's not a small subject and you'll need to get quite familiar with concepts like homogenous coordinates which might seem unintuitive at first.

If you don't care about the math, then you're better of just using an existing library that hides it from you.
Logged
ubik
Level 0
***


View Profile
« Reply #11 on: April 14, 2012, 10:33:02 PM »

This is an excellent (and necessary) thing for learning purposes.  Especially write a raytracer and a raycaster.

But if you are doing something for release, for god's sake use OpenGL or some other canned library.  The number of advantages you get from hardware acceleration are so extreme that it's foolish not to exploit them.
Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic