[rlgl] Add Software Rendering Support (#4832)

* add base of rlsw.h

* implement state support
Also replace the triangle rasterization functions with macros that generate specific functions for each state of the rendering system.
Also, add the OpenGL definitions in order to add a binding for rlgl.

* branchless float saturation

* apply perspective correction to colors

* impl line clipping and rasterization
+ tweak function names

* impl face culling

* impl color blending

* fixes and tweaks

* add clear buffer bitmasks

* small optimizations / tweaks

* review ndc to screen projection

* avoid to recalculate MVP when its not needed + tweaks

* review the loading and management of textures
to be closer to the OpenGL API

* texture sampling optimization

* review get pixel functions
+ review unorm/float conversion

* add several buffer format support
Several depth and color formats have been added for the framebuffer.

8-bit, 16-bit, and 24-bit formats are now available for depth.

RGB 8-bit (332), RGB 16-bit (565), and RGB 24-bit (888) formats are now available for color.

Alpha support is no longer present for the framebuffer at the moment, but it can easily be restored by adding the formats and reinterpolating the alpha in the areas that do not perform color blending.

Additionally, this commit brings performance improvements.

* tweaks

* impl line width

* impl points + point size

* fix and improve polygon clipping functions

* impl polygone modes

* add some not planned functions
- `glDepthMask`
- `glColorMask`

* framebuffer resizing + handle init failure

* add quick notes about line clipping algorithms used

* start to impl scissor test + review line clipping
The support for the scissor test has been implemented for clearing as well as for triangle clipping.
The implementation for lines and points is still missing.

I also removed the 2D clipping of lines that used the Cohen-Sutherland algorithm, opting instead to always use the Liang-Barsky algorithm in all cases.
This simplifies the implementation, and the 2D version would have caused issues when interpolating vertices in the future if we want to implement additional features.

* review scissor clear

* review `swScissor`

* impl line scissor clipping

* round screen coordinate (line rasterization)

* impl point scissor clipping

* remove unused defs

* add getter functions

* gl binding

* add `glHint` and `glShadeModel` macros (not implmented)

* binding tweaks

* impl copy framebuffer function + glReadPixels

* review `swCopyFramebuffer`

* update rlgl.h

* update rlgl.h

* texture copy support

* fix typo..

* add get error function

* def sw alloc macros

* reimpl get color buffer func
just in case

* remove normal interpolation

* review texture wrap

* fix ndc projection (viewport/scissor)

* impl framebuffer blit function

* reduce matrix compuations and memory usage

* swBegin tweaks

* preventing a possible division by zero

* remove useless scissor related data

* review color blending system

* greatly improve float saturation

* tweak lerp vertex function

* use opitmized fract function in sw_texture_map

* tweak framebuffer functions for better readability

* optimized copy/blit functions for each dst format

* review framebuffer filling functions

* impl specific quad rendering func

* use of a single global vertex buffer

* fix 'sw_poly_point_render'

* added `SW_RESTRICT` and redesigned `sw_lerp_vertex_PNCTH`

* tweak the pipeline flow regarding the face culling
avoids misprediction, improves vectorization if possible

* new rendering path for axis aligned quads

* oops, translating some comments

* use of `restrict` for blending function parameters

* update rlgl.h

* adding `GRAPHICS_API_OPENGL_11_SOFTWARE` in `DrawMesh`

* add `RL_OPENGL_11_SOFTWARE` enum

* temp tweak

* build fixes

* fix DrawMesh for GL 1.1

* update swClose

* review texture format + fix copy

* set minimum req vertices to 3 (quads)

* check swInit

* review pixelformat

* tweaks

* fix animNormals (DrawMesh)

* fallback color/texcoord (swDrawArrays)

* review swMultMatrixf

* fix texture pool alloc..

* review triangle scanlines
increment all data

* fix `sw_quad_sort_cw`

* impl sdl platform

* rm def

* increase max clipped polygon vertices

* improve triangle rasterization along Y axis
improved robustness against numerical errors
incremental interpolation along Y
simplified function, fewer jumps

* review current vertex data
+ increase max clipped polygon vertices (for extreme cases)

* fix and improve polygon clipping
Sets the vertex count to zero when the polygon is invalid
Stops clipping when the vertex count drops below 3

* fix gradient calculation

* cache texture size minus one + comments

* tweaks

* BGRA copy support

* adding software backend option (cmake)

* update Makefile

* fix face culling

* excluse some exemple with the software backend

* review SW_CLAMP case in sw_texture_map

* review sw_saturate

* review line raster

* fix sw_quad_is_aligned

* review sw_raster_quad_axis_aligned

* tweaks

* codepoint fix (?)

* fix var name...

* rcore_drm software renderering

* cleanup and tweaks

* adding support for `GL_POINT_SIZE` and `GL_LINE_WIDTH` get

* fix sampling issue

* fix swBlendFunc

---------

Co-authored-by: Ray <raysan5@gmail.com>
This commit is contained in:
Le Juez Victor
2025-09-29 10:28:20 +02:00
committed by GitHub
parent 6d9e17594b
commit 584bc14929
9 changed files with 5739 additions and 113 deletions

View File

@@ -149,7 +149,8 @@
#endif
// Security check in case no GRAPHICS_API_OPENGL_* defined
#if !defined(GRAPHICS_API_OPENGL_11) && \
#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE) && \
!defined(GRAPHICS_API_OPENGL_11) && \
!defined(GRAPHICS_API_OPENGL_21) && \
!defined(GRAPHICS_API_OPENGL_33) && \
!defined(GRAPHICS_API_OPENGL_43) && \
@@ -159,7 +160,7 @@
#endif
// Security check in case multiple GRAPHICS_API_OPENGL_* defined
#if defined(GRAPHICS_API_OPENGL_11)
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
#if defined(GRAPHICS_API_OPENGL_21)
#undef GRAPHICS_API_OPENGL_21
#endif
@@ -174,6 +175,11 @@
#endif
#endif
// Software implementation uses OpenGL 1.1 functionality
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
#define GRAPHICS_API_OPENGL_11
#endif
// OpenGL 2.1 uses most of OpenGL 3.3 Core functionality
// WARNING: Specific parts are checked with #if defines
#if defined(GRAPHICS_API_OPENGL_21)
@@ -427,7 +433,8 @@ typedef struct rlRenderBatch {
// OpenGL version
typedef enum {
RL_OPENGL_11 = 1, // OpenGL 1.1
RL_OPENGL_11_SOFTWARE = 0, // Software rendering
RL_OPENGL_11, // OpenGL 1.1
RL_OPENGL_21, // OpenGL 2.1 (GLSL 120)
RL_OPENGL_33, // OpenGL 3.3 (GLSL 330)
RL_OPENGL_43, // OpenGL 4.3 (using GLSL 330)
@@ -768,6 +775,10 @@ RLAPI unsigned int rlLoadFramebuffer(void); // Loa
RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel); // Attach texture/renderbuffer to a framebuffer
RLAPI bool rlFramebufferComplete(unsigned int id); // Verify framebuffer is complete
RLAPI void rlUnloadFramebuffer(unsigned int id); // Delete framebuffer from GPU
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
RLAPI void rlCopyFramebuffer(int x, int y, int w, int h, int format, void* pixels);
RLAPI void rlResizeFramebuffer(int width, int height);
#endif
// Shaders management
RLAPI unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode); // Load shader from code strings
@@ -834,24 +845,32 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#endif
#if defined(GRAPHICS_API_OPENGL_11)
#if defined(__APPLE__)
#include <OpenGL/gl.h> // OpenGL 1.1 library for OSX
#include <OpenGL/glext.h> // OpenGL extensions library
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
#define RLSW_IMPL
#define SW_MALLOC(sz) RL_MALLOC(sz)
#define SW_REALLOC(ptr, newSz) RL_REALLOC(ptr, newSz)
#define SW_FREE(ptr) RL_FREE(ptr)
#include "external/rlsw.h" // OpenGL 1.1 software implementation
#else
// APIENTRY for OpenGL function pointer declarations is required
#if !defined(APIENTRY)
#if defined(_WIN32)
#define APIENTRY __stdcall
#else
#define APIENTRY
#if defined(__APPLE__)
#include <OpenGL/gl.h> // OpenGL 1.1 library for OSX
#include <OpenGL/glext.h> // OpenGL extensions library
#else
// APIENTRY for OpenGL function pointer declarations is required
#if !defined(APIENTRY)
#if defined(_WIN32)
#define APIENTRY __stdcall
#else
#define APIENTRY
#endif
#endif
// WINGDIAPI definition. Some Windows OpenGL headers need it
#if !defined(WINGDIAPI) && defined(_WIN32)
#define WINGDIAPI __declspec(dllimport)
#endif
#endif
// WINGDIAPI definition. Some Windows OpenGL headers need it
#if !defined(WINGDIAPI) && defined(_WIN32)
#define WINGDIAPI __declspec(dllimport)
#endif
#include <GL/gl.h> // OpenGL 1.1 library
#include <GL/gl.h> // OpenGL 1.1 library
#endif
#endif
#endif
@@ -2337,6 +2356,14 @@ void rlglInit(int width, int height)
glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation)
#endif
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
if (!swInit(width, height))
{
TRACELOG(RL_LOG_ERROR, "RLGL: Software renderer initialization failed!");
exit(-1);
}
#endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Store screen size into global variables
RLGL.State.framebufferWidth = width;
@@ -2363,6 +2390,10 @@ void rlglClose(void)
glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture
TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture unloaded successfully", RLGL.State.defaultTextureId);
#endif
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
swClose();
#endif
}
// Load OpenGL extensions
@@ -2672,7 +2703,9 @@ void *rlGetProcAddress(const char *procName)
int rlGetVersion(void)
{
int glVersion = 0;
#if defined(GRAPHICS_API_OPENGL_11)
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
glVersion = RL_OPENGL_11_SOFTWARE;
#elif defined(GRAPHICS_API_OPENGL_11)
glVersion = RL_OPENGL_11;
#endif
#if defined(GRAPHICS_API_OPENGL_21)
@@ -3713,6 +3746,20 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
return pixels;
}
#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
void rlCopyFramebuffer(int x, int y, int w, int h, int format, void* pixels)
{
unsigned int glInternalFormat, glFormat, glType;
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
swCopyFramebuffer(x, y, w, h, glFormat, glType, pixels);
}
void rlResizeFramebuffer(int width, int height)
{
swResizeFramebuffer(width, height);
}
#endif
// Read screen pixel data (color buffer)
unsigned char *rlReadScreenPixels(int width, int height)
{
@@ -5313,4 +5360,4 @@ static Matrix rlMatrixInvert(Matrix mat)
}
#endif
#endif // RLGL_IMPLEMENTATION
#endif // RLGL_IMPLEMENTATION