-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update gl.cpp #2
base: master
Are you sure you want to change the base?
Conversation
Yay!
Please split all that into separate commits, especially the reformatting. I see that there are various changes which aren't just reformatting but also change the meaning of code (e.g. replacing It also changed e.g
At some point I was experimenting with using different precisions for the Z buffer, so I used this way of getting the right type without having to change it everywhere. Meanwhile it could be replaced by hardcoding
It's used for installing a SIGINT handler to quit SDL. Without that, you can't terminate the program properly. I guess MSVC doesn't implement this? In that case, you can wrap it in
They're not supposed to be visible externally/globally, which also allows for more optimizations. See also https://stackoverflow.com/questions/1856599/when-to-use-static-keyword-before-global-variables for more info.
Yeah, the line drawing code wasn't really used beyond the initial bringup, it's older than the triangle drawing code and uses a naive, unoptimized and broken way of drawing. I'll leave some comments about the code changes in the review section. |
Ok I made the split commits, all organized now. |
__builtin_expect macro for gnu isn't recognized by msvc, so it doesn't work as expected when I add the custom macro #define |
You noticed that correctly. The unused part is for the W coordinate, which isn't really needed for 3D affine transformations which always have This makes A optimization similar to Much more time is spent during drawing of primitives, so avoiding overdraw (writing pixels which aren't visible in the final frame) would have a much bigger impact on performance. nGL can't do any visibility calculations depending on scenery, so that's up to the application. Another topic is that currently nGL uses a 32-bit Z buffer, which has to be read (and written, if in front) for each pixel of a triangle. A different approach is to depth-sort primitives before drawing them, which avoids that access, but increases overdraw as everything behind it which is just partially visible is fully drawn and then just overwritten again. |
It's not - |
gl.cpp
Outdated
#include <signal.h> | ||
static SDL_Surface *scr; | ||
#ifdef _WIN32 | ||
#include <SDL.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#include <SDL.h>
should actually work for both
gl.cpp
Outdated
static SDL_Surface *scr; | ||
#ifdef _WIN32 | ||
#include <SDL.h> | ||
#include <signal.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be in the "not windows" block?
gl.cpp
Outdated
#else | ||
#include <SDL/SDL.h> | ||
#endif | ||
SDL_Window* sdl_window; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should all be static
, as not used/accessible outside of this source file
gl.cpp
Outdated
SDL_TEXTUREACCESS_STREAMING, | ||
SCREEN_WIDTH, SCREEN_HEIGHT); | ||
|
||
SDL_SetWindowTitle(sdl_window, "nGl"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SDL_SetWindowTitle(sdl_window, "nGl"); | |
SDL_SetWindowTitle(sdl_window, "nGL"); |
gl.cpp
Outdated
@@ -84,7 +100,7 @@ void nglUninit() | |||
#ifdef _TINSPIRE | |||
lcd_init(SCR_TYPE_INVALID); | |||
#else | |||
//TODO | |||
SDL_DestroyRenderer(sdl_renderer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't there something like SDL_Quit
?
//Doesn't interpolate colors even if enabled | ||
void nglDrawLine3D(const VERTEX *v1, const VERTEX *v2) | ||
{ | ||
//TODO: Z-Clipping | ||
// Z-Clipping! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proper Z clipping would involve only drawing the part of the line which fits into the view (z between NEAR_PLANE
and inf). This is currently just a band-aid to avoid a division by zero, so the //TODO
comment should stay.
if(dy > GLFix(1) || dy < GLFix(-1)) | ||
//if(dy > GLFix(1) || dy < GLFix(-1)) | ||
|
||
// if check passes diff_y should always be non zero |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can be more confident here:
// if check passes diff_y should always be non zero | |
// if check passes, diff_y is non zero |
@@ -354,29 +370,36 @@ GLFix nglZBufferAt(const unsigned int x, const unsigned int y) | |||
return z_buffer[x + y * SCREEN_WIDTH]; | |||
} | |||
|
|||
constexpr GLFix ABS(GLFix a) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This belongs into fix.h
, as method
const GLFix diff_y = v2_p.y - v1_p.y; | ||
|
||
const GLFix dx = (v2_p.x - v1_p.x) / diff_y; | ||
const GLFix dx = diff_x / diff_y; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's correct to use those values after the std::swap
above. The swap is there to guarantee that v1_p
has a lower Y than v2_p
, so you would have to change the sign of all the diff_
values as well. Otherwise drawn lines face the wrong direction.
It's easier to just always compute the diffs after the swap though - subtraction is cheap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using diff_x / diff_y
is fine here. In the case where the points have to be swapped, diff_y
is negative and the division returns the correct result. It's important to not mix diffs before and after the swap though, which is the case in line 403 for instance.
Support for SDL2, and fixed some divide by 0 errors with Fix<>, changed some other things for simplicity.
Some questions:
why use this to create the depth buffer instead of
new
:z_buffer = new std::remove_reference<decltype(*z_buffer)>::type[SCREEN_WIDTH*SCREEN_HEIGHT];
why use <signal.h>?
why were all the beginning variables static?
lastly, the #define cluster around line 477, why so much/complicated?:
A lot of the code will appear as changed because MSVC beautified it. I spent a lot of time wondering why I couldn't get a triangle to draw, so I went ahead to learn about matrices and stuff to try and backtrack the problem. I thought of enabling wireframe, so it would draw a 3d line which was pretty basic, then I got the div by 0 errors... Well it's fixed now, I hope my changes can be used.