A DIY 3D Rendering Engine
A DIY 3D Rendering Engine
Okay... it's not really a full 3D engine, but still pretty cool.
Anyway, I had a thought last night about rendering a 3d scene using only the Window's API GDI library. This library allows you to do trivial things such as draw a line or point, fill a rectangular area with a certain color, etc.
So today, i did some research on how 3D graphics engines render a 3d object onto the screen. I'd already had some experience with opengl, so i know the basics about 3 coordinate systems and i knew that they used a 4x4 matrix to calculate transformations on 3d objects.
At the start of this little project, my goal was to simply manipulate a single point (aka a vertex) in 3d space, but after researching i learned that any transformation done on a point is also done on all other points related to that object (for example, if you rotate one vertex that makes up a cube, you must rotate the whole cube using the same matrix). I won't go into details, but it was a fun (and frustrating!) time. ^_^
If i do develop this further and it turns into a decent 3D library, this particular "engine" would be most useful for rending complex 3d images (like terragen) or small, simple 3d scenes that you can move around in. Because it uses a high level API, it will never reach the performance levels of true 3D graphics libraries like opengl or direct x, as they make more direct use of things like vram, vertex shaders, and the gpu.
Anyway, i've attached a zip file below that contains the binary and the soure code. You can click and drag the cube around, but it always rotates around the Y-axis at the moment.
Later fellas!
Anyway, I had a thought last night about rendering a 3d scene using only the Window's API GDI library. This library allows you to do trivial things such as draw a line or point, fill a rectangular area with a certain color, etc.
So today, i did some research on how 3D graphics engines render a 3d object onto the screen. I'd already had some experience with opengl, so i know the basics about 3 coordinate systems and i knew that they used a 4x4 matrix to calculate transformations on 3d objects.
At the start of this little project, my goal was to simply manipulate a single point (aka a vertex) in 3d space, but after researching i learned that any transformation done on a point is also done on all other points related to that object (for example, if you rotate one vertex that makes up a cube, you must rotate the whole cube using the same matrix). I won't go into details, but it was a fun (and frustrating!) time. ^_^
If i do develop this further and it turns into a decent 3D library, this particular "engine" would be most useful for rending complex 3d images (like terragen) or small, simple 3d scenes that you can move around in. Because it uses a high level API, it will never reach the performance levels of true 3D graphics libraries like opengl or direct x, as they make more direct use of things like vram, vertex shaders, and the gpu.
Anyway, i've attached a zip file below that contains the binary and the soure code. You can click and drag the cube around, but it always rotates around the Y-axis at the moment.
Later fellas!
- Attachments
-
- 3d Graph.zip
- (8.67 KiB) Downloaded 163 times
¯\_(ツ)_/¯ It works on my machine...
Re: A DIY 3D Rendering Engine
Wow man very cool! I am impressed. This is why we hack. To do the impossible!
*cheers
Mabo
*cheers
Mabo
- bad_brain
- Site Owner
- Posts: 11636
- Joined: 06 Apr 2005, 16:00
- 19
- Location: In your eye floaters.
- Contact:
Re: A DIY 3D Rendering Engine
yeah man, I told gogeta already that I would have not the slightest clue even where to start...
Re: A DIY 3D Rendering Engine
Man that's really cool!
I didn't think a cube could be so entertaining haha.
I didn't think a cube could be so entertaining haha.
Re: A DIY 3D Rendering Engine
Okay, here's an update. I reworked the rendering engine and added surface objects, so now the engine simply draws from an array of surface objects (which in turn contains the list of vertices for each surface). This allows me to draw the wireframe lines automatically, unlike in the first one where i specified where to draw the lines.
Right now, there are a few issues that i want to fix. First, when you have an object rotating around the Y-axis from a huge distance, the object distorts really bad when it crosses the X-axis (Try this yourself with the version in the first post, just maximise the window and move the cube to the edge of the screen).
Second, when you move the cube close to the corners of the window (or any "large" distance from the center of the window), it seems too distorted, but maybe this is just me.
Third, i would like to have it so that objects behind other objects aren't drawn over objects in front of them. In other words, i don't want to be able to see through the surfaces. I'm not quite sure how to do this yet, maybe you guys have an idea?
Anyway, aside from those three things, it looks pretty good. I've attached an update below. The cube now spins in place regardless of position, and you can still move it around with the mouse.
Later dudes!
Right now, there are a few issues that i want to fix. First, when you have an object rotating around the Y-axis from a huge distance, the object distorts really bad when it crosses the X-axis (Try this yourself with the version in the first post, just maximise the window and move the cube to the edge of the screen).
Second, when you move the cube close to the corners of the window (or any "large" distance from the center of the window), it seems too distorted, but maybe this is just me.
Third, i would like to have it so that objects behind other objects aren't drawn over objects in front of them. In other words, i don't want to be able to see through the surfaces. I'm not quite sure how to do this yet, maybe you guys have an idea?
Anyway, aside from those three things, it looks pretty good. I've attached an update below. The cube now spins in place regardless of position, and you can still move it around with the mouse.
Later dudes!
- Attachments
-
- 3d Graph_2.zip
- (15.58 KiB) Downloaded 152 times
¯\_(ツ)_/¯ It works on my machine...
Re: A DIY 3D Rendering Engine
Hi everyone! So i've been doing a lot of research on wikipedia in relation to 3d graphics.
I've gotten to the point where i should be choosing whether i want to use a rasterizer (for animated 3d scenes) or a static 3d rendering method, such as ray tracing. At the moment, i think i'm going to stick with rasterization, but i'll probably implement ray tracing in the future.
Additionally, i've also fixed this first and second problems i mentioned above. The problem was with the method of projection i was using. Orthographic projection works okay for drawings, but not so well for 3d scenes. I'm now using what's called perspective projection, which uses a point behind the screen instead of a point in the distance.
I've also done some reading up about my third issue. There are 2 methods i'm considering right now. The first is z-buffering, which keeps a record of the closest drawn polygon for each pixel. This is fairly fast, but uses a lot of memory (see below). The other method sorts the array of primitives from back to front, so that the ones in the back are drawn first. This method works pretty well and produces minimal artifacts, but is very computationally expensive.
Anyway, this is where i'm at right now. I don't have an update to upload at the moment since the only new thing is the perspective projection.
Thoughts and ideas are welcome!
Later dudes.
I've gotten to the point where i should be choosing whether i want to use a rasterizer (for animated 3d scenes) or a static 3d rendering method, such as ray tracing. At the moment, i think i'm going to stick with rasterization, but i'll probably implement ray tracing in the future.
Additionally, i've also fixed this first and second problems i mentioned above. The problem was with the method of projection i was using. Orthographic projection works okay for drawings, but not so well for 3d scenes. I'm now using what's called perspective projection, which uses a point behind the screen instead of a point in the distance.
I've also done some reading up about my third issue. There are 2 methods i'm considering right now. The first is z-buffering, which keeps a record of the closest drawn polygon for each pixel. This is fairly fast, but uses a lot of memory (see below). The other method sorts the array of primitives from back to front, so that the ones in the back are drawn first. This method works pretty well and produces minimal artifacts, but is very computationally expensive.
Code: Select all
//Example of z-ordering memory usage
#define ScreenWidth 1024
#define ScreenHeight 768
//Let's just use a signed short. This will give us a range of -32,768 to 32,768
signed short zBuff = new signed short[ScreenWidth * ScreenHeight];
//The z-buffer takes up ScreenWidth * ScreenHeight * sizeof(signed short) (2 bytes)
//So 1024 * 768 * 2 bytes = 1,572,864 bytes = 1,536 kb = 1.5mb
Thoughts and ideas are welcome!
Later dudes.
¯\_(ツ)_/¯ It works on my machine...
- Lundis
- Distorter of Reality
- Posts: 543
- Joined: 22 Aug 2008, 16:00
- 15
- Location: Deadlock of Awesome
- Contact:
Re: A DIY 3D Rendering Engine
OpenGL uses a depth map at least... I would go for that, I mean, it only uses a few megabytes of memory after all. You probably want to use floats or doubles to represent the depth values though.
You could implement an option to turn the depth testing off if it's not needed, such as if the user specifies all the objects to be rendered in order.
You could implement an option to turn the depth testing off if it's not needed, such as if the user specifies all the objects to be rendered in order.
Re: A DIY 3D Rendering Engine
You're talking about the z-buffer method right? The only problem i see with it is that i don't draw the polygons pixel-by-pixel, i draw lines and fill regions with color, as that's much faster.
¯\_(ツ)_/¯ It works on my machine...
Re: A DIY 3D Rendering Engine
Man that's really cool!
- computathug
- Administrator
- Posts: 2693
- Joined: 29 Mar 2007, 16:00
- 17
- Location: UK
- Contact:
Re: A DIY 3D Rendering Engine
Great work G-Man,
The devil can cite Scripture for his purpose.
-- William Shakespeare, "The Merchant of Venice"
https://tshirt-memes.com
-- William Shakespeare, "The Merchant of Venice"
https://tshirt-memes.com
- Lundis
- Distorter of Reality
- Posts: 543
- Joined: 22 Aug 2008, 16:00
- 15
- Location: Deadlock of Awesome
- Contact:
Re: A DIY 3D Rendering Engine
Gogeta, you've got a point there ^^
But will your method work if half the line is behind an object?
But will your method work if half the line is behind an object?
Re: A DIY 3D Rendering Engine
Thanks guys ^_^
Lundis, implementing the z-buffer method was too much of a hassle, so i went with what's called the "painter's algorithm". All this does is sort each polygon by it's barycenter (the 3-dimensional center of the polygon) from back to front. The C++ STL has a great function for sorting an array in it's algorithms library, so i used that. It works very well.
Anyway, here's a small update. The only new things in this one is the method of projection and i've implemented depth testing, so things look more realistic already . The new method of projection got rid of those problems i've had before pretty well, so i'm happy with it. I'm not sure if i'll stick with the same depth testing method, we'll have to see how it does when i have a few thousand polygons on screen.
Here's what i'm currently adding:
-Support for loading Wavefront Object files (*.obj)
-Rotation around an arbitrary axis (in other words, rotation around a user-specified vector)
Might be added soon:
-Basic lighting:
-Ambient light (needs no explanation, right?)
-Directional light. You specify a point in 3d space and surfaces with be lit (and cast in shadow) based on the relative position of the object from the light source.
That's all for now. Merry christmas!
Lundis, implementing the z-buffer method was too much of a hassle, so i went with what's called the "painter's algorithm". All this does is sort each polygon by it's barycenter (the 3-dimensional center of the polygon) from back to front. The C++ STL has a great function for sorting an array in it's algorithms library, so i used that. It works very well.
Anyway, here's a small update. The only new things in this one is the method of projection and i've implemented depth testing, so things look more realistic already . The new method of projection got rid of those problems i've had before pretty well, so i'm happy with it. I'm not sure if i'll stick with the same depth testing method, we'll have to see how it does when i have a few thousand polygons on screen.
Here's what i'm currently adding:
-Support for loading Wavefront Object files (*.obj)
-Rotation around an arbitrary axis (in other words, rotation around a user-specified vector)
Might be added soon:
-Basic lighting:
-Ambient light (needs no explanation, right?)
-Directional light. You specify a point in 3d space and surfaces with be lit (and cast in shadow) based on the relative position of the object from the light source.
That's all for now. Merry christmas!
- Attachments
-
- 3d Graph.zip
- (45.02 KiB) Downloaded 136 times
¯\_(ツ)_/¯ It works on my machine...