mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 10:05:44 -04:00
Simplify projection matrix calculation and add more explanatory comments
This commit is contained in:
parent
03ccdbbc5c
commit
da8ab3d979
@ -200,10 +200,13 @@ CC_API void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix);
|
||||
CC_API void Gfx_LoadIdentityMatrix(MatrixType type);
|
||||
CC_API void Gfx_EnableTextureOffset(float x, float y);
|
||||
CC_API void Gfx_DisableTextureOffset(void);
|
||||
/* Calculates an orthographic matrix suitable with this backend. (usually for 2D) */
|
||||
|
||||
/* Calculates an orthographic projection matrix suitable with this backend. (usually for 2D) */
|
||||
void Gfx_CalcOrthoMatrix(float width, float height, struct Matrix* matrix);
|
||||
/* Calculates a projection matrix suitable with this backend. (usually for 3D) */
|
||||
/* Calculates a perspective projection matrix suitable with this backend. (usually for 3D) */
|
||||
void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zFar, struct Matrix* matrix);
|
||||
/* NOTE: Projection matrix calculation is here because it can depend the graphics backend */
|
||||
/* (e.g. OpenGL uses a Z clip range of [-1, 1], whereas Direct3D9 uses a range of [0, 1]) */
|
||||
|
||||
/* Outputs a .png screenshot of the backbuffer. */
|
||||
cc_result Gfx_TakeScreenshot(struct Stream* output);
|
||||
|
@ -717,9 +717,18 @@ void Gfx_DisableTextureOffset(void) {
|
||||
}
|
||||
|
||||
void Gfx_CalcOrthoMatrix(float width, float height, struct Matrix* matrix) {
|
||||
Matrix_Orthographic(matrix, 0.0f, width, 0.0f, height, ORTHO_NEAR, ORTHO_FAR);
|
||||
matrix->row3.Z = 1.0f / (ORTHO_NEAR - ORTHO_FAR);
|
||||
matrix->row4.Z = ORTHO_NEAR / (ORTHO_NEAR - ORTHO_FAR);
|
||||
/* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterrh */
|
||||
/* The simplified calculation below uses: L = 0, R = width, T = 0, B = height */
|
||||
float zNear = ORTHO_NEAR, zFar = ORTHO_FAR;
|
||||
*matrix = Matrix_Identity;
|
||||
|
||||
matrix->row1.X = 2.0f / width;
|
||||
matrix->row2.Y = -2.0f / height;
|
||||
matrix->row3.Z = 1.0f / (zNear - zFar);
|
||||
|
||||
matrix->row4.X = -1.0f;
|
||||
matrix->row4.Y = 1.0f;
|
||||
matrix->row4.Z = zNear / (zNear - zFar);
|
||||
}
|
||||
|
||||
static float CalcZNear(float fov) {
|
||||
@ -732,11 +741,24 @@ static float CalcZNear(float fov) {
|
||||
return 0.00390625f;
|
||||
}
|
||||
|
||||
static double Cotangent(double x) { return Math_Cos(x) / Math_Sin(x); }
|
||||
void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zFar, struct Matrix* matrix) {
|
||||
Matrix_PerspectiveFieldOfView(matrix, fov, aspect, CalcZNear(fov), zFar);
|
||||
/* Adjust the projection matrix to produce reversed Z values */
|
||||
matrix->row3.Z = -matrix->row3.Z - 1.0f;
|
||||
matrix->row4.Z = -matrix->row4.Z;
|
||||
/* Deliberately swap zNear/zFar in projection matrix calculation to produce */
|
||||
/* a projection matrix that results in a reversed depth buffer */
|
||||
/* https://developer.nvidia.com/content/depth-precision-visualized */
|
||||
float zNear_ = zFar;
|
||||
float zFar_ = CalcZNear(fov);
|
||||
|
||||
/* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovrh */
|
||||
float c = (float)Cotangent(0.5f * fov);
|
||||
*matrix = Matrix_Identity;
|
||||
|
||||
matrix->row1.X = c / aspect;
|
||||
matrix->row2.Y = c;
|
||||
matrix->row3.Z = zFar_ / (zNear_ - zFar_);
|
||||
matrix->row3.W = -1.0f;
|
||||
matrix->row4.Z = (zNear_ * zFar_) / (zNear_ - zFar_);
|
||||
matrix->row4.W = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
|
@ -167,7 +167,7 @@ void Matrix_Mul(struct Matrix* result, const struct Matrix* left, const struct M
|
||||
}
|
||||
|
||||
void Matrix_Orthographic(struct Matrix* result, float left, float right, float top, float bottom, float zNear, float zFar) {
|
||||
/* Transposed, source https://msdn.microsoft.com/en-us/library/dd373965(v=vs.85).aspx */
|
||||
/* Transposed, source https://learn.microsoft.com/en-us/windows/win32/opengl/glortho */
|
||||
*result = Matrix_Identity;
|
||||
|
||||
result->row1.X = 2.0f / (right - left);
|
||||
@ -181,20 +181,20 @@ void Matrix_Orthographic(struct Matrix* result, float left, float right, float t
|
||||
|
||||
static double Tan_Simple(double x) { return Math_Sin(x) / Math_Cos(x); }
|
||||
void Matrix_PerspectiveFieldOfView(struct Matrix* result, float fovy, float aspect, float zNear, float zFar) {
|
||||
float c = zNear * (float)Tan_Simple(0.5f * fovy);
|
||||
float c = (float)Tan_Simple(0.5f * fovy);
|
||||
|
||||
/* Transposed, source https://msdn.microsoft.com/en-us/library/dd373537(v=vs.85).aspx */
|
||||
/* Transposed, source https://learn.microsoft.com/en-us/windows/win32/opengl/glfrustum */
|
||||
/* For a FOV based perspective matrix, left/right/top/bottom are calculated as: */
|
||||
/* left = -c * aspect, right = c * aspect, bottom = -c, top = c */
|
||||
/* Calculations are simplified because of left/right and top/bottom symmetry */
|
||||
*result = Matrix_Identity;
|
||||
result->row4.W = 0.0f;
|
||||
|
||||
result->row1.X = zNear / (c * aspect);
|
||||
result->row2.Y = zNear / c;
|
||||
result->row4.Z = -(2.0f * zFar * zNear) / (zFar - zNear);
|
||||
result->row1.X = 1.0f / (c * aspect);
|
||||
result->row2.Y = 1.0f / c;
|
||||
result->row3.Z = -(zFar + zNear) / (zFar - zNear);
|
||||
result->row4.Z = -(2.0f * zFar * zNear) / (zFar - zNear);
|
||||
result->row3.W = -1.0f;
|
||||
result->row4.W = 0.0f;
|
||||
}
|
||||
|
||||
void Matrix_LookRot(struct Matrix* result, Vec3 pos, Vec2 rot) {
|
||||
|
@ -236,6 +236,9 @@ void Gfx_RestoreAlphaState(cc_uint8 draw) {
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Textures--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void CopyTextureData(void* dst, int dstStride, const struct Bitmap* src, int srcStride) {
|
||||
/* We need to copy scanline by scanline, as generally srcStride != dstStride */
|
||||
cc_uint8* src_ = (cc_uint8*)src->scan0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user