diff --git a/.github/workflows/build_webassembly.yml b/.github/workflows/build_webassembly.yml
index d79b12b1c..1e4066c26 100644
--- a/.github/workflows/build_webassembly.yml
+++ b/.github/workflows/build_webassembly.yml
@@ -18,20 +18,20 @@ on:
jobs:
build:
runs-on: windows-latest
-
+
env:
RELEASE_NAME: raylib-dev_webassembly
-
+
steps:
- name: Checkout
uses: actions/checkout@master
-
+
- name: Setup emsdk
uses: mymindstorm/setup-emsdk@v14
with:
- version: 3.1.71
+ version: 5.0.3
actions-cache-folder: 'emsdk-cache'
-
+
- name: Setup Release Version
run: |
echo "RELEASE_NAME=raylib-${{ github.event.release.tag_name }}_webassembly" >> $GITHUB_ENV
@@ -39,7 +39,7 @@ jobs:
if: github.event_name == 'release' && github.event.action == 'published'
- name: Setup Environment
- run: |
+ run: |
mkdir build
cd build
mkdir ${{ env.RELEASE_NAME }}
@@ -47,14 +47,14 @@ jobs:
mkdir include
mkdir lib
cd ../..
-
+
- name: Build Library
run: |
cd src
emcc -v
make PLATFORM=PLATFORM_WEB EMSDK_PATH="D:/a/raylib/raylib/emsdk-cache/emsdk-main" RAYLIB_RELEASE_PATH="../build/${{ env.RELEASE_NAME }}/lib" -B
cd ..
-
+
- name: Generate Artifacts
run: |
copy /Y .\src\raylib.h .\build\${{ env.RELEASE_NAME }}\include\raylib.h
@@ -67,7 +67,7 @@ jobs:
7z a ./${{ env.RELEASE_NAME }}.zip ./${{ env.RELEASE_NAME }}
dir
shell: cmd
-
+
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
@@ -75,7 +75,7 @@ jobs:
path: |
./build/${{ env.RELEASE_NAME }}
!./build/${{ env.RELEASE_NAME }}.zip
-
+
- name: Upload Artifact to Release
uses: softprops/action-gh-release@v1
with:
diff --git a/CHANGELOG b/CHANGELOG
index 9bfdbe484..053ff3018 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -8,26 +8,785 @@ Release: raylib 6.0 (?? March 2026)
-------------------------------------------------------------------------
KEY CHANGES:
- New Software Renderer backend [rlsw]
- - New rcore platform backend: Memory (memory buffer)
- - New rcore platform backend: Win32 (experimental)
- - New rcore platform backend: Emscripten (experimental)
- - Redesigned Skeletal Animation System
+ - New platform backend: Memory (memory buffer)
+ - New platform backend: Win32 (experimental)
+ - New platform backend: Emscripten (experimental)
- Redesigned fullscreen modes and high-dpi content scaling
+ - Redesigned Skeletal Animation System
- Redesigned Build Config System [config.h]
- New File System API
- New Text Management API
- New tool: [rexm] raylib examples manager
+ - Added +50 new examples to learn from
Detailed changes:
-TODO...
+[rcore] ADDED: Logging and file-system functionality from `utils` (#4551) by @raysan5 -WARNING-
+[rcore] ADDED: Flags set/clear macros: FLAG_SET, FLAG_CLEAR, FLAG_IS_SET (#5169) by @raysan5
+[rcore] ADDED: Warnings in case of no platform backend defined by @raysan5
+[rcore] ADDED: `ComputeSHA256()` (#5264) by @iamahuman1395
+[rcore] ADDED: `GetKeyName()` (#4544) by @lecongsebastien
+[rcore] REMOVED: GIF recording option, added example by @raysan5 -WARNING-
+[rcore] REMOVED: `CORE.Window.fullscreen` variable, using available flag instead by @raysan5
+[rcore] REMOVED: `SetupFramebuffer()`, most platforms do not need it any more by @raysan5
+[rcore] REMOVED: `TRACELOGD()` macro, hardly ever used by @raysan5
+[rcore] RENAMED: Shader location SHADER_LOC_VERTEX_INSTANCETRANSFORMS (#5592) by @CrackedPixel
+[rcore] REVIEWED: Gamepads database on latest `SDL2 2.32.8` and `SDL3 3.3.6` #5403 by @raysan5
+[rcore] REVIEWED: Alt-Tab not working in borderless fullscreen (#3865, #4655) by @veins1
+[rcore] REVIEWED: Automation system, saving to memory buffer and binary file (#5476) by @belan2470
+[rcore] REVIEWED: Check if `shader.locs` is not NULL before try to access (#5622) by @maiconpintoabreu
+[rcore] REVIEWED: Content scaling on macOS (#5186) by @mchcopl
+[rcore] REVIEWED: `GetRandomValue()`, fix modulo bias (#5392) by @Marcos-D -WARNING-
+[rcore] REVIEWED: Controller not available after window init (#5358) by @sergii
+[rcore] REVIEWED: Cursor lock/unlock inconsistent behaviour (#5323) by @tacf
+[rcore] REVIEWED: Description of `RestoreWindow()` by @johnnymarler
+[rcore] REVIEWED: Touch position register on automation event handling (#5470) by @belan2470
+[rcore] REVIEWED: FLAG_IS_SET to check if all bits in the flag are set in the value (#5441) by @vushu
+[rcore] REVIEWED: Fix for BI_ALPHABITFIELDS for clipbaord image narrow support (#5586) by @crisserpl2
+[rcore] REVIEWED: Flags checks, fixes #5597 by @raysan5
+[rcore] REVIEWED: Fullscreen request #5601 by @raysan5
+[rcore] REVIEWED: HighDPI content scaling on changing monitors with different DPI #5335 #5356 by @raysan5
+[rcore] REVIEWED: HighDPI content scaling on macOS by @raysan5
+[rcore] REVIEWED: Implement `FLAG_WINDOW_ALWAYS_RUN` on Android (#5414) by @caszuu
+[rcore] REVIEWED: Init main framebuffer using render size (should be same as currentFbo) by @raysan5
+[rcore] REVIEWED: Platform code formatting and organization by @raysan5
+[rcore] REVIEWED: Replace #pragma message with TRACELOG inside the clipboard image function (#5596) by @maiconpintoabreu
+[rcore] REVIEWED: Requested window flags application after window initialization by @raysan5
+[rcore] REVIEWED: Setting some flags disabled fullscreen (#4618, 4619) by @veins1
+[rcore] REVIEWED: Some flags for window/context creation attributes by @raysan5
+[rcore] REVIEWED: Support window flags with initialization issues (#4837) by @Andersama
+[rcore] REVIEWED: Swap `TraceLog()` to `TRACELOG` macro (#5226) by @iamahuman1395
+[rcore] REVIEWED: Swap local variable `isCursorHidden` to use new method `IsCursorHidden()` by @maiconpintoabreu
+[rcore] REVIEWED: Touch `pointCount` reduction (#4661) by @maiconpintoabreu
+[rcore] REVIEWED: Unscale the window size on resize if we are doing automatic HighDPI scaling by @Jeffm2501
+[rcore] REVIEWED: Use `FLAG_*` macros where possible (#5169) by @iamahuman1395
+[rcore] REVIEWED: Wayland checks, using compilation flags when possible #5564 by @raysan5
+[rcore] REVIEWED: `InitWindow()`, issues due to unchecked result of `InitPlatform()` (#4803) by @sleeptightAnsiC
+[rcore] REVIEWED: `InitWindow()`, fixed issue when using an empty window title (#5526) by @CrackedPixel
+[rcore] REVIEWED: `GetRenderWidth()`, and `GetRenderHeight()`, return the FBO size if one is active by @Jeffm2501
+[rcore] REVIEWED: `GetWindowPosition()`, return internal value by @raysan5
+[rcore] REVIEWED: `ToggleBorderlessFullscreen()`, not hiding taskbar (#5383) by @xenomustache
+[rcore] REVIEWED: `IsMouseButton*()`, random key codes return unexpected results (#5516) by @jasoncnm
+[rcore] REVIEWED: `IsGamepadButton*()`, for consistency with key and mouse equivalents by @raysan5
+[rcore] REVIEWED: `SetGamepadVibration()`, TRACELOG message (#4615) by @Asdqwe
+[rcore] REVIEWED: `MAX_GAMEPAD_AXES` for consistency #4960 by @raysan5
+[rcore] REVIEWED: `MAX_GAMEPAD_NAME_LENGTH` #4695 by @raysan5
+[rcore] REVIEWED: `LoadRandomSequence()`, using `GetRandomValue()` #5393 by @raysan5
+[rcore] REVIEWED: `LoadShaderFromMemory()`, use default locations for default shader #4641 by @raysan5
+[rcore] REVIEWED: `ComputeSHA1()`, computation on messages longer than 31 bytes (#5397) by @me
+[rcore] REVIEWED: `ComputeSHA256()` by @raysan5
+[rcore] REVIEWED: `DecodeDataBase64()`, decoding error when input string is invalid (#5170) by @zet23t
+[rcore] REVIEWED: `DecodeDataBase64()`, follow convention: by @raysan5
+[rcore] REVIEWED: `DecompressData()`, fixed buffer copying by @raysan5
+[rcore] REVIEWED: `GetClipboardImage()`, make symbol available on all platforms by @raysan5
+[rcore] REVIEWED: `GetRandomValue()`, explained the new approach to get more uniform random values range by @raysan5
+[rcore] REVIEWED: `FileExists()`, using macro by @raysan5
+[rcore] REVIEWED: `IsFileExtension()`, to avoid other modules dependency #5071 by @raysan5
+[rcore] REVIEWED: `LoadDirectoryFilesEx()`, count files if not recursive (#5496) by @katanya04
+[rcore] REVIEWED: `LoadDirectoryFilesEx()`, minor tweak #5569 by @raysan5
+[rcore] REVIEWED: `UnloadDirectoryFiles`, added NULL check by @Bigfoot71
+[rcore] REVIEWED: `ScanDirectoryFiles*()`, #4833 by @raysan5
+[rcore] REVIEWED: `ScanDirectoryFilesRecursively()`, fix issues by @mlorenc
+[rcore] REVIEWED: `ScanDirectoryFilesRecursively()`, makes `path` static by @Bigfoot71
+[rcore] REVIEWED: `SaveFileText()`, const input text by @raysan5
+[rcore] REVIEWED: `TakeScreenshot()`, avoid path filtering by @raysan5
+[rcore] REVIEWED: `TakeScreenshot()`, only scale the screenshot by the DPI scale if required by @Jeffm2501
+[rcore] REDESIGNED: Fullscreen modes, use current display resolution by @raysan5 -WARNING-
+[rcore] REDESIGNED: `EncodeDataBase64()`/`DecodeDataBase64()`, use NULL terminated strings by @raysan5 -WARNING-
+[rcore][GLFW] ADDED: Clipboard image support for linux (#5603) by @maiconpintoabreu
+[rcore][GLFW] REVIEWED: Fix `IsWindowFocused()` inverted logic (#5333) by @iamahuman1395
+[rcore][GLFW] REVIEWED: Fullscreen modes on Linux (X11 over XWayland) by @raysan5
+[rcore][GLFW] REVIEWED: Make sure that GLFW uses RL_*ALLOC macros (#4777) by @sleeptightAnsiC
+[rcore][GLFW] REVIEWED: Set correct default axes for gamepads that are not connected (#5444) by @LeapersEdge
+[rcore][GLFW] REVIEWED: Window initialization on HighDPI monitor (Windows) #5549 by @raysan5
+[rcore][GLFW] REVIEWED: Window scaling on Wayland with GLFW 3.4+ (#5564) by @0xPD33
+[rcore][GLFW] REVIEWED: Window scaling with HighDPI on macOS #5059 by @raysan5
+[rcore][GLFW] REVIEWED: `InitPlatform()`, crash caused by `glfwCreateWindow()` (#4804) by @sleeptightAnsiC
+[rcore][GLFW] REVIEWED: `InitPlatform()`, code simplification by @raysan5
+[rcore][GLFW] REVIEWED: `GetWindowHandle()`, return correct handle under Linux X11 by @Didas72
+[rcore][GLFW] REVIEWED: `WindowSizeCallback()` by @raysan5
+[rcore][GLFW] REVIEWED: `CORE.Window.eventWaiting` and `FLAG_WINDOW_ALWAYS_RUN` handling (#4642) by @Asdqwe
+[rcore][GLFW] REVIEWED: `GetGamepadButtonPressed()`, return GAMEPAD_BUTTON_*_TRIGGER_2 if pressed (#4742) by @whaleymar
+[rcore][GLFW] REVIEWED: Update `mappings.h` using `GenerateMappings.cmake` by @sleeptightAnsiC
+[rcore][RGFW] ADDED: New backend option: `PLATFORM_WEB_RGFW` and update RGFW (#4480) by @colleagueRiley
+[rcore][RGFW] REVIEWED: Added missing Right Control key by @M374LX
+[rcore][RGFW] REVIEWED: Changed `RGFW_window_eventWait` timeout to -1 by @doggymangc
+[rcore][RGFW] REVIEWED: Duplicate entries reemoved from `keyMappingRGFW` (#5242) by @iamahuman1395
+[rcore][RGFW] REVIEWED: Fix Escape always closing the window by @M374LX
+[rcore][RGFW] REVIEWED: Forward declare the windows stuff, prevents failures in GCC (#5269) by @Jeffm2501
+[rcore][RGFW] REVIEWED: Requires RGBA8 images as window icons (#5431) by @crisserpl2
+[rcore][RGFW] REVIEWED: Window width calculation by adding wOffset (#5457) by @qubitxr
+[rcore][RGFW] REVIEWED: `SetGamepadVibration()` implementation (#4612) by @JupiterRider
+[rcore][SDL] REVIEWED: `FLAG_WINDOW_ALWAYS_RUN` implementation (#4598) by @Asdqwe
+[rcore][SDL] REVIEWED: First touch position is overwritten with mouse position by @zet23t
+[rcore][SDL] REVIEWED: Avoid `rtext` module dependency #4959 by @raysan5
+[rcore][SDL] REVIEWED: Fix crash when `strncpy()` tries to copy using NULL pointer (#5359) by @MikiZX1
+[rcore][SDL] REVIEWED: Fix gamepad detection (#5176) by @brccabral
+[rcore][SDL] REVIEWED: Fix maximizing, minimizing and restoring windows for SDL2 (#4607) by @Asdqwe
+[rcore][SDL] REVIEWED: Fix show, hide, focus and unfocus window/flags states for SDL2 (#4610) by @Asdqwe
+[rcore][SDL] REVIEWED: Fix text input (characters) (#5574) by @TheKodeToad
+[rcore][SDL] REVIEWED: Gamepad event handling by adding joystick instance id tracking (#4724) by @Asdqwe
+[rcore][SDL] REVIEWED: RGB order on SDL3 #3568 by @raysan5
+[rcore][SDL] REVIEWED: `SetGamepadMappings()` (#5548) by @arleyuti
+[rcore][SDL] REVIEWED: Handle monitor ID correctly on SDL3 (#5290) by @sleeptightAnsiC
+[rcore][Web] ADDED: Clipboard image implementation for web (#5614) by @maiconpintoabreu
+[rcore][Web] ADDED: `GetWindowScaleDPI()`, implementation for PLATFORM_WEB (#4526) by @Asdqwe
+[rcore][Web] ADDED: `IsWindowHidden()` (#4789) by @marionauta
+[rcore][Web] REVIEWED: Fix reversed window blur/focus logic for web (#5590) by @aceiii
+[rcore][Web] REVIEWED: Fix undeclared canvas variable error (#5507) by @vdemcak
+[rcore][Web] REVIEWED: Replaced hardcoded canvas id references with module variable (#4735) by @zet23t
+[rcore][Web] REVIEWED: Store canvas name id at platform initialization by @raysan5
+[rcore][Web] REVIEWED: Support software renderer on Web, blitting framebuffer data directly to a 2d canvas by @raysan5
+[rcore][Web] REVIEWED: Using `Module` provided canvas id for event binding (#4690) by @zet23t
+[rcore][Web] REVIEWED: Using `EmscriptenKeyboardCallback()` to consume key events by @moros1138
+[rcore][Web] REVIEWED: `IsWindowFocused()` (#4640) by @marionauta
+[rcore][Web] REVIEWED: `GetApplicationDirectory()` for Wasm, returning root VFS (#5495) by @git
+[rcore][Win32] ADDED: `rcore_desktop_win32`, new native Win32 platform backend (#4869) by @johnnymarler
+[rcore][Win32] REDESIGNED: New native Win32 platform backend, simplification and formating by @raysan5
+[rcore][Win32] REVIEWED: New Win32 platform backend to accomodate `rlsw` Software Renderer by @raysan5
+[rcore][Win32] REVIEWED: Fix window width calculation by adding wOffset (#5480) by @crisserpl2
+[rcore][Win32] REVIEWED: Implemented `SetWindowMaxSize()`, `SetWindowMinSize()` and `SetWindowSize()` (#5536) by @mikeemm
+[rcore][Win32] REVIEWED: Remove `-fno-stack-protector` and add `requestFullscreen` on exported methods by @emilhakimov415
+[rcore][Win32] REVIEWED: VSync flag not being applied (#5521) by @mikeemm
+[rcore][Win32] REVIEWED: Window minimizing/maximizing functionality (#5524) by @mikeemm
+[rcore][Android] REVIEWED: Content scaling functionality for HighDPI (#4769) by @Bigfoot71
+[rcore][Android] REVIEWED: `SetWindowState()` (#5424) by @caszuu
+[rcore][Android] REVIEWED: `GetCurrentMonitor()` implementation (#5204) by @guntzjonas
+[rcore][Android] REVIEWED: `android_fopen()` mechanims, after removing `utils` module dependency by @raysan5
+[rcore][Android] REVIEWED: `fopen()` wrapping mechanism, to use --wrap=fopen on build systems (#5624) by @ghera
+[rcore][Android] REVIEWED: `LoadMusicStream()` due to missing fopen redirect (#5589) by @ghera
+[rcore][Android] REVIEWED: Fallback on dirent filename when all route fails (#5484) by @lucas150670
+[rcore][Android] REVIEWED: Gesture system not reporting GESTURE_NONE (#5452) by @padmadevd
+[rcore][Android] REVIEWED: Keyboard input detected as gamepad on some devices (#5439) by @decruz
+[rcore][Android] REVIEWED: Replaced `android_fopen()` with linker `--wrap=fopen` (#5605) by @ghera
+[rcore][DRM] ADDED: Support asynchronous page-flipping and framebuffer caching by @rob-bits -WARNING-
+[rcore][DRM] REVIEWED: Compiler flag SUPPORT_DRM_CACHE, to enable triple buffered DRM caching by @rob-bits
+[rcore][DRM] REVIEWED: Backspace key in RPI SSH keyboard by @matthijs
+[rcore][DRM] REVIEWED: Check if video mode is valid and rename to match with other methods (#5235) by @maiconpintoabreu
+[rcore][DRM] REVIEWED: Disable touch position simulation from mouse movement for touchscreen devices (#5279) by @MULTidll
+[rcore][DRM] REVIEWED: Fix resources memory leak (#5494) by @matthewkennedy
+[rcore][DRM] REVIEWED: Platform initialization messages by @raysan5
+[rcore][DRM] REVIEWED: Use `eglGetPlatformDisplayEXT()` for Mali compatibility (#5446) by @decruz
+[rcore][DRM] REVIEWED: `FindNearestConnectorMode()`, prefer mode with smallest number of unused pixels (#5158) by @maiphi
+[rcore][DRM] REVIEWED: `eglGetPlatformDisplay()` usage by @raysan5
+[rcore][DRM] REVIEWED: Improved touch input handling and multitouch support (#5447) by @MULTidll
+[rcore][DRM] REVIEWED: DRM cache buffers support #4988 by @raysan5
+[rlgl] ADDED: Software Rendering Support (#4832) by @Bigfoot71
+[rlgl] ADDED: `rlGetProcAddress()` (#5062) by @danilwhale
+[rlgl] ADDED: `rlUnloadShader()` (#5631) by @raysan5
+[rlgl] REMOVED: `RLGL_RENDER_TEXTURES_HINT`, enabled by default and no complaints of anyone having issues #5479 by @raysan5
+[rlgl] REVIEWED: Allow tint colors in GL_LINE (wires) and GL_POINT (points) draw modes on OpenGL 1.1 clean (#5207) by @lanur622
+[rlgl] REVIEWED: Attribute name and location, for consistency by @raysan5
+[rlgl] REVIEWED: Behavior for texture in OpenGL 1.1 draw states (#5328) by @lanur622
+[rlgl] REVIEWED: Better default values for normals and tangents (VBOs) (#4763) by @Bigfoot71
+[rlgl] REVIEWED: Clean up Matrix handling and rl* functions to follow convention (#5505) by @nathanmburg
+[rlgl] REVIEWED: Delete shader object in case compilation fails by @raysan5
+[rlgl] REVIEWED: Fixed shader tangents to be vec4 by @Sir-Irk
+[rlgl] REVIEWED: Increased depth size and clip distances to avoid z-fighting issues by @raysan5
+[rlgl] REVIEWED: Issues compiling for OpenGL 1.1 #5088 by @raysan5
+[rlgl] REVIEWED: Make sure ShaderUniformDataType matches rlShaderUniformDataType (#4577) by @RicoP
+[rlgl] REVIEWED: Potential issue with animated normals on OpenGL 1.1 by @raysan5
+[rlgl] REVIEWED: Using define for buffers size by @raysan5
+[rlgl] REVIEWED: Warning log macro (#5043) by @vinnyhorgan
+[rlgl] REVIEWED: Preserve texture on mode switching (#4364) by @Destructor17
+[rlgl] REVIEWED: Proposed fix for default near/far clipping range (#4906) by @Bigfoot71
+[rlgl] REVIEWED: `rlLoadTexture()`, max mipmap levels to use #5400 by @raysan5
+[rlgl] REVIEWED: `rlLoadTexture()`, uncomplete texture do to issue on mipmap loading #5416 by @raysan5
+[rlgl] REVIEWED: `rlLoadTextureDepth()`, address inconsistencies with WebGL 2.0 for sized depth formats #5500 by @raysan5
+[rlgl] REVIEWED: `rlReadScreenPixels()`, optimizations (#4667) by @pope
+[rlgl] REVIEWED: `rlSetTexture()` not overriding default mode (#5200) by @maiconpintoabreu
+[rlgl] REVIEWED: `rlActiveDrawBuffers`, fix for OpenGL ES 3.0 (#4605) by @Bigfoot71
+[rlgl] REVIEWED: `rlGetPixelDataSize()`, correct compressed data size calculation per blocks #5416 by @raysan5
+[rlgl] REVIEWED: `instranceTransform` shader location index #4538 (#4579) by @meadiode
+[rlgl] REVIEWED: `SetShaderValueTexture()`, updatee comments (#4703) by @pejorativefox
+[rlgl] REDESIGNED: Avoid program crash if GPU data is tried to be loaded before `InitWindow()` #4751 by @raysan5 -WARNING-
+[rlgl] REDESIGNED: Shader loading API function names for more consistency #5631 by @raysan5 -WARNING-
+[rlsw] ADDED: `swGetColorBuffer()` for convenience by @raysan5
+[rlsw] REVIEWED: Completeness of `glDraw*()` functions (#5304) by @Bigfoot71
+[rlsw] REVIEWED: Fix axis aligned quad detection (#5314) by @Bigfoot71
+[rlsw] REVIEWED: Fix clipping issue on software render (#5342) by @Bigfoot71
+[rlsw] REVIEWED: Make sure SSE is being used when compiling with MSVC by @raysan5
+[rlsw] REVIEWED: SIMD instrinsics must be explicitly enabled by developer, only SSE supported at the moment #5316 by @raysan5
+[rlsw] REVIEWED: Segmentation fault when trying to render a model (#5622) by @maiconpintoabreu
+[rlsw] REVIEWED: Simplify framebuffer logic and add blit/copy fast path (#5312) by @Bigfoot71
+[rlsw] REVIEWED: Review depth formats and fix depth writing (#5317) by @Bigfoot71
+[rlsw] REVIEWED: Smarter texture management (#5296) by @Bigfoot71
+[rlsw] REVIEWED: Subpixel correction (#5300) by @Bigfoot71
+[rlsw] REVIEWED: C++ support (#5291) by @alexgb0
+[rshapes] ADDED: `DrawLineDashed()` (#5222) by @luis605
+[rshapes] ADDED: `DrawEllipseV()` and `DrawEllipseLinesV()` (#4963) by @meowstr
+[rshapes] REVIEWED: `DrawLine()`, fix pixel offset issue on drawing (#4666) by @Bigfoot71
+[rshapes] REVIEWED: `DrawRectangleGradientEx()`, incorrect parameter names (#4980) by @vincent
+[rshapes] REVIEWED: `DrawRectangleLines`, fix pixel offset issue (#4669) by @Bigfoot71
+[rshapes] REVIEWED: `DrawRectangleRounded()`, allow to draw rectangles with a size < 1 (#4683) by @tea
+[rshapes] REVIEWED: `CheckCollisionLines()`, formating and follow raylib conventions by @raysan5
+[rshapes] REVIEWED: `DrawCircleSector*()`, optimization to prevent division by zero (#4843) by @theundergroundsorcerer
+[rshapes] REVIEWED: `CheckCollisionLines()`, properly detect collision if one line is almost vertical (#5510, #5531) by @bielern
+[rtextures] REVIEWED: Cubemap mipmap loading improvements (#4721) by @Not-Nik
+[rtextures] REVIEWED: Setting mipmaps MAX_LEVEL based on actual mipcount input (#4622) by @JettMonstersGoBoom
+[rtextures] REVIEWED: TCC compilation due to `emmintrin.h` not found (#4707) by @sleeptightAnsiC
+[rtextures] REVIEWED: `Image`, initialization align to avoid issues with some platforms (#5214) by @psxdev
+[rtextures] REVIEWED: `LoadImageDataNormalized()`, missing increments of k (#4745) by @henrikglass
+[rtextures] REVIEWED: `LoadImageFromScreen()`, use the render size instead of screen size (#5192) by @JeffM2501
+[rtextures] REVIEWED: `GenImageFontAtlas()`, fix memory corruption in reallocation (#5602) by @creeperblin
+[rtextures] REVIEWED: `GenImageFontAtlas()`, no need for the conservative approach flag by @raysan5
+[rtextures] REVIEWED: `GenImageFontAtlas()`, scale image to fit all characters, in case it fails size estimation #5542 by @raysan5
+[rtextures] REVIEWED: `GetImageColor()` (#5560) by @raysan5
+[rtextures] REVIEWED: `ExportImage()` by @raysan5
+[rtextures] REVIEWED: `HalfToFloat()` and `FloatToHalf()` dereferencing issues with an union (#4729) by @Asdqwe
+[rtextures] REVIEWED: `ImageClearBackground()` and `ImageDrawRectangleRec()` optimizations (#5363) by @ChocolateChipKookie
+[rtextures] REVIEWED: `ImageColorReplace()`, alpha issue replacement (#5047) by @RomainPlmg
+[rtextures] REVIEWED: `ImageDrawLineEx(), to be able to draw even numbered thicknesses (#5042) by @Sir-Irk
+[rtextures] REVIEWED: `ImageBlurGaussian()`, fix integer overflow in cast (#5037) by @garrisonhh
+[rtext] ADDED: `LoadTextLines()`/`UnloadTextLines()` by @raysan5
+[rtext] ADDED: `MeasureTextCodepoints()` for direct measurement of codepoints (#5623) by @creeperblin
+[rtext] RENAMED: Variable names for consistency, `textLength` (length in bytes) vs `textSize` (measure in pixels) by @raysan5
+[rtext] REVIEWED: Support default font loading with no GPU enabled, to be used with Image API
+[rtext] REVIEWED: Default font alpha on Big Endian systems (#4624) by @Fancy2209
+[rtext] REVIEWED: Font atlas image generation, added some comments #5141 by @raysan5
+[rtext] REVIEWED: Multiply security checks to avoid crashes on wrongly provided string data (#4751) by @raysan5
+[rtext] REVIEWED: Potential security concerns while copying unbounded text data between strings by @raysan5
+[rtext] REVIEWED: Properly clean up the default font on unload, it may be reused if the window is created again by @Jeffm2501
+[rtext] REVIEWED: Remove some `const` from text buffer return values by @raysan5
+[rtext] REVIEWED: Some security vulnerabilities in font loading (#5433, #5434, #5436, #5450) by @oneafter
+[rtext] REVIEWED: Use `const` for codepoints arrays passed to function #5159 by @raysan5
+[rtext] REVIEWED: Use `strstr()` instead of `TextFindIndex()` (#4764) by @brabissimoooooo
+[rtext] REVIEWED: `LoadFont()`, improve load message (#5050) by @katanya04
+[rtext] REVIEWED: `LoadFont*()`, provide more detailed info on glyphs failing to pack (#5141) by @raysan5
+[rtext] REVIEWED: `LoadCodepoints()`, local variable shadowing `codepoints` (#5430) by @KiviTK
+[rtext] REVIEWED: `LoadCodepoints()`, comment explaining functionality (#4787) by @loftafi
+[rtext] REVIEWED: `LoadFontFromImage()`, limit pixel scanning to image dimensions (#5626) by @joe
+[rtext] REVIEWED: `LoadFontDataBDF()` #5346 by @raysan5
+[rtext] REVIEWED: `LoadTextLines()` by @raysan5
+[rtext] REVIEWED: `ExportFontAsCode()` #5497 by @raysan5
+[rtext] REVIEWED: `ExportFontAsCode()` not checking `isGpuReady` #4894 by @raysan5
+[rtext] REVIEWED: `GetCodepointCount()`, misuse of cast (#4741) by @sleeptightAnsiC
+[rtext] REVIEWED: `GenImageFontAtlas()`, memory corruption and invalid size calculation (#5602) by @konakona418
+[rtext] REVIEWED: `TextInsert()`, fix bug on insertion (#5644) by @CrackedPixel
+[rtext] REVIEWED: `TextJoin()`, convert `const char **` to `char**` by @raysan5
+[rtext] REVIEWED: `TextReplace()` and `TextLength()`, avoid using `strcpy()` by @raysan5
+[rtext] REVIEWED: `TextReplace()` by @raysan5
+[rtext] REVIEWED: `TextReplace()`, improvements (#5511) by @belan2470
+[rtext] REVIEWED: `TextReplaceBetween()` by @raysan5
+[rtext] REVIEWED: `TextSubtext(), fixes (#4759) by @veins1
+[rtext] REVIEWED: `TextToPascal()`, fix issue by @raysan5
+[rtext] REVIEWED: `TextToFloat()`, remove removed inaccurate comment (#4596) by @hexmaster111
+[rtext] REDESIGNED: `LoadFontData()`, added input parameter by @raysan5 -WARNING-
+[rmodels] ADDED: Support CPU animation in OpenGL 1.1 (#4925) by @JeffM2501
+[rmodels] RENAMED: Skinning shader variables (new default naming) by @raysan5
+[rmodels] REVIEWED: glTF animation framerate calculation (#4472, #5445) by @TheLazyIndianTechie
+[rmodels] REVIEWED: Assign meshes without bone weights to the bone they are attached to so they animate by @Jeffm2501
+[rmodels] REVIEWED: Out of bound memory read in `Material.maps` (#5534) by @Sumethh
+[rmodels] REVIEWED: Segfaults with animation system (#4635) by @JettMonstersGoBoom
+[rmodels] REVIEWED: Transform the vertex normals by the animated matrix (#4646) by @Jeffm2501
+[rmodels] REVIEWED: Use the animated verts and normals in OpenGL 1.1 if they exist by @Jeffm2501
+[rmodels] REVIEWED: GLTF bone weight assignments for meshes parented to armature (#4923) by @JeffM2501
+[rmodels] REVIEWED: `LoadOBJ()`, avoid fatal errors on OBJ model loading by @raysan5
+[rmodels] REVIEWED: `LoadOBJ()`, don't upload meshes, `LoadModel()` will upload them (#5083) by @JeffM2501
+[rmodels] REVIEWED: `LoadOBJ()`, loading crash when there are no normals present (#5079) by @zet23t
+[rmodels] REVIEWED: `LoadGLFT()`, avoid loading attributes already loaded (#4996) by @raysan5
+[rmodels] REVIEWED: `LoadGLTF()`, anim correctly inherits world transform (#5206) by @ArmanOmmid
+[rmodels] REVIEWED: `LoadGLTF()`, fix memory leak when model has no bones (#5629) by @vberdugo
+[rmodels] REVIEWED: `LoadGLTF()`, fixing offset for processing tangents (#5015) by @Sir-Irk
+[rmodels] REVIEWED: `LoadGLTF()`, log warning about draco compression not supported #5567 by @raysan5
+[rmodels] REVIEWED: `LoadGLTF()`, separate roughness and metallic channels on load (#4739) by @Not-Nik
+[rmodels] REVIEWED: `LoadGLTF()`, support 16 bit vec3 values (#5388) by @Jeffm2501
+[rmodels] REVIEWED: `LoadGLTF()`, fixed NULL pointer dereference (#4564) by @CalebHeydon
+[rmodels] REVIEWED: `LoadIQM()` and `LoadModelAnimationsIQM()`, fix memory leaks (#4649) by @peter15914
+[rmodels] REVIEWED: `LoadM3D()`, don't require a M3d animation only file to have a mesh (#5475) by @Jeffm2501
+[rmodels] REVIEWED: `LoadImageFromCgltfImage()`, fix crash when NULL is passed (#4563) by @CalebHeydon
+[rmodels] REVIEWED: `LoadImageFromCgltfImage()`, fix NULL pointer dereference (#4557) by @CalebHeydon
+[rmodels] REVIEWED: `LoadModelAnimationsGLTF()`, properly load 1 frame animations (#5561) by @arlez80
+[rmodels] REVIEWED: `LoadModelAnimationsGLTF()`, anim correctly inherits world transform (#5206) by @ArmanOmmid
+[rmodels] REVIEWED: `UploadMesh()`, improve default normal and tangent values (#4763) by @Bigfoot71
+[rmodels] REVIEWED: `GenMeshTangents()`, improvements (#4937) by @Bigfoot71
+[rmodels] REVIEWED: `UpdateModelAnimation()` optimization (#5244) by @Arrangemonk
+[rmodels] REVIEWED: `UpdateModelAnimationBones()`, break on first mesh found and formating by @raysan5
+[rmodels] REVIEWED: `UpdateModelAnimationBones()`, fix normal transform (#4634) by @Bigfoot71
+[rmodels] REVIEWED: `UpdateModelAnimationBones()`, optimizations (#4602) by @Kirandeep-Singh-Khehra
+[rmodels] REVIEWED: `UpdateModelAnimationBones()`, bones animation scale (#4896) by @mUnicorn
+[rmodels] REVIEWED: `DrawBillboardPro()`, flipped texture source rectangle draw correctly (#5276) by @aixiansheng
+[rmodels] REVIEWED: `DrawMesh()`, OpenGL11 fixes added texture consistency check (#5328) by @meisei4
+[rmodels] REVIEWED: `DrawMeshInstanced()`, breaking if instanceTransform was unused (#5469) by @al13n321
+[rmodels] REVIEWED: `DrawSphereEx()`, normals support (#4926) by @karl-zylinski
+[rmodels] REVIEWED: `ExportMesh()`, improve OBJ vertex data precision and lower memory usage (#4496) by @mikeemm
+[raudio] REVIEWED: Fix a glitch at the end of a sound (#5578) by @mackron
+[raudio] REVIEWED: Improvements to device configuration (#5577) by @mackron
+[raudio] REVIEWED: Initialize sound alias properties as if it was a new sound (#5123) by @JeffM2501
+[raudio] REVIEWED: Music stopping some frames too early by @veins1
+[raudio] REVIEWED: Remove usage of `ma_data_converter_get_required_input_frame_count()` (#5568) by @mackron
+[raudio] REVIEWED: Better computation of the default audio stream buffer size (#4898) by @JeffM2501
+[raudio] REVIEWED: Documentation for audio stream processor, number of channels (#4753) by @goto40
+[raudio] REVIEWED: `LoadWAV()`, fixed buffer overflow when loading WAV files (#4539) by @CalebHeydon
+[raudio] REVIEWED: `LoadMusicStream()`, issues in Android due to missing fopen redirect (#5589) by @ghera
+[raudio] REVIEWED: `LoadMusicStreamFromMemory()` for QOA, reduced the number of allocs and memcpy (#5108) by @lassade
+[raudio] REVIEWED: `UnloadMusicStream()`, properly close FLAC (#5133) by @rossberg
+[raudio] REVIEWED: `UpdateMusicStream()`, prevent to run without music playing (#5046) by @maiconpintoabreu
+[raudio] REVIEWED: `WaveFormat()`, fixed memory leak on early-return (#4779) by @deckarep
+[raudio] REVIEWED: `WaveFormat()`, freeing memory issue (#5481) by @MarcosTypeAP
+[raudio] REVIEWED: `GetMusicTimePlayed()`, fix music shorter than buffer size (#5048) by @veins1
+[raudio] REVIEWED: `GetMusicTimePlayed()`, returns incorrect time after restart (#4914) by @Servall4
+[raudio] REDESIGNED: `SetSoundPan()` and `SetMusicPan()` ranges from [-1.0..1.0] (#5350) by @raysan5 -WARNING-
+[raymath] ADDED: `MatrixUnit()` and `MatrixMultiplyValue()` (#5613) by @lamweilun
+[raymath] ADDED: `MatrixCompose()` (#5324) by @EDBCREPO
+[raymath] ADDED: `Vector2CrossProduct()` (#4520) by @uwiwiow
+[raymath] REVIEWED: Fix C++ operator overloads (#4535) by @ListeriaM
+[raymath] REVIEWED: Vector2Angle(), detailed documentation (#4556) by @mrjonjonjon
+[raymath] REVIEWED: Wrap float3 and float16 for consistency with other types (#5540) by @n-s-kiselev
+[raymath] REVIEWED: `HalfToFloat()`, fix mantissa hex value by @backspaceoverload
+[raymath] REVIEWED: `MatrixCompose()` by @raysan5
+[raymath] REVIEWED: `MatrixDeterminant()` #4780 by @raysan5
+[raymath] REVIEWED: `MatrixDecompose()` removes shear (#5201) by @ArmanOmmid
+[raymath] REVIEWED: `MatrixMultiply()` intrinsics support: SSE (#5427) by @mcdubhghlas
+[raymath] REVIEWED: `QuaternionFromVector3ToVector3()` (#5508) by @The4codeblocks
+[rcamera] REVIEWED: `Camera3D.fovy` description (#5164) by @0stamina
+[rcamera] REVIEWED: Camera move up and right work with Z up cameras (#5458) by @Jeffm2501
+[rcamera] REVIEWED: Camera pan speed (#5554) by @CrackedPixel
+[rcamera] REVIEWED: Fix camera initial position (#4657) by @Asdqwe
+[rcamera] REVIEWED: Clamp camera pitch (#5137) by @feive7
+
+[build][CI] ADDED: ARM64 with Visual Studio (#4781) by @Peter0x44
+[build][CI] ADDED: `update_examples.yml` by @raysan5
+[build][CI] RENAMED: GitHub Actions files, clearer naming by @raysan5
+[build][CI] REVIEWED: Linux workflow to run on `ubuntu-latest` by @raysan5
+[build][CI] REVIEWED: Remove double zip and misleading zip type (#5512) by @maiconpintoabreu
+[build][CI] REVIEWED: `update_examples.yml` workflow (#5130) by @iamahuman1395
+[build][Script] REVIEWED: `build_example_web.bat` by @raysan5
+[build][Make] ADDED: ARM64 support to Linux builds by @quaylynrimer11
+[build][Make] REVIEWED: Use `libraylib.web.a` naming on PLATFORM_WEB by @raysan5 -WARNING-
+[build][Make] REVIEWED: Only include rglfw.c for glfw platform by @johnnymarler
+[build][Make] REVIEWED: Fix template to support `libraylib.web.a` (#5620) by @skazu0611
+[build][Make] REVIEWED: Avoid using != assignment (#5464) by @sleeptightAnsiC
+[build][Make] REVIEWED: Improve support for `PLATFORM_DESKTOP_WIN32` (#5311) by @GithubPrankster
+[build][Make] REVIEWED: Latest NDK version compiling errors on Android (#5389) by @Sethbones
+[build][Make] REVIEWED: Makefile to support software renderer by @raysan5
+[build][Make] REVIEWED: Properly detect if ABI is Android by @lumenkeyes
+[build][Make] REVIEWED: Remove path override/change for linux (#5641) by @CrackedPixel
+[build][Make] REVIEWED: Renamed `PLATFORM_DESKTOP_SDL3` to `USING_VERSION_SDL3` #5175 by @raysan5
+[build][Make] REVIEWED: Tag to locate examples list: `#EXAMPLES_LIST_*` by @raysan5
+[build][Make] REVIEWED: Undefine _GNU_SOURCE for rglfw building (#4732) by @Peter0x44
+[build][Make] REVIEWED: `-sASSERTIONS` usage by linker #4717 by @raysan5
+[build][Make] REVIEWED: `Makefile.Web` per-example target generation including used resources by @raysan5
+[build][Make] REVIEWED: android-libc.txt generation by @lumenkeyes
+[build][Make] REVIEWED: examples Makefile PLATFORM define (#4582) by @Asdqwe
+[build][VS2022] ADDED: Filters and platform files in MSVC for ease of editing (#4644) by @Jeffm2501
+[build][VS2022] REVIEWED: Default raylib resource file .rc for projects by @raysan5
+[build][VS2022] REVIEWED: Fix MSVC warnings (#5619) by @Jeffm2501
+[build][VS2022] REVIEWED: MSVC warnings (#5595) by @Jeffm2501
+[build][VS2022] REVIEWED: Fixed VS2022 broken build by @alexander_nichols
+[build][VSCode] REVIEWED: Makefile for `PLATFORM_WEB` (#5620) by @takenoko-pm
+[build][CMake] ADDED: Support for SDL3, reviewed SDL2 package cheking by @kariem2k
+[build][CMake] ADDED: emscripten build options (#5180) by @brccabral
+[build][CMake] ADDED: QNX EGL 2.0 library configuration (#5499) by @jscaffidi
+[build][CMake] REVIEWED: Android configuration issues (#4671) by @Bigfoot71
+[build][CMake] REVIEWED: Definition to use SDL3 (#5175) by @brccabral
+[build][CMake] REVIEWED: X11 libraries as glfw make private (#5625) by @maiconpintoabreu
+[build][CMake] REVIEWED: Don't build examples using audio if audio is disabled (#4652) by @Peter0x44
+[build][CMake] REVIEWED: Export automatically raylib definitions and compile/link options (#5179) by @brccabral
+[build][CMake] REVIEWED: Expose RGFW platform backend (#5386) by @Sethbones
+[build][CMake] REVIEWED: Set PLATFORM to Web by default when configuring web builds with emcmake (#4748) by @gilzoide
+[build][CMake] REVIEWED: Set correct description for verbose option by @brccabral
+[build][CMake] REVIEWED: Set version to 3.12 (#4547) by @zyperpl
+[build][CMake] REVIEWED: Update `LibraryConfigurations.cmake (#5617) by @m0391n
+[build][CMake] REVIEWED: Use STATIC lib ON by default (#4799) by @brccabral
+[build][CMake] REVIEWED: Using addCMacro instead of defineCMacro (#4620) by @Joonsey
+[build][CMake] REVIEWED: Web compilation system (#5181) by @brccabral
+[build][CMake] REVIEWED: Set `libm` as public so it can be linked by consumer (#5193) by @brccabral
+[build][Cmake] REVIEWED: Expose PLATFORM_WEB_RGFW (#5579) by @crisserpl2
+[build][Zig] ADDED: Android target to build by @lumenkeyes
+[build][Zig] REVIEWED: Link EGL for Android by @lumenkeyes
+[build][Zig] REVIEWED: Approach to build for web with zig-build (#5157) by @haxsam
+[build][Zig] REVIEWED: Fix build accessing env vars (#5490) by @iisakki
+[build][Zig] REVIEWED: Fix emscripten building by @johnnymarler
+[build][Zig] REVIWED: Move examples/build.zig into main build.zig by @johnnymarler
+[build][Zig] REVIEWED: Fix raygui inclusion in windows crosscompilation (#4489) by @kimierik
+[build][Zig] REVIEWED: Issue on emscripten run if the user has not installed emsdk by @emilhakimov415
+[build][Zig] REVIEWED: Make X11 the default display backend instead of choosing at runtime (#5168) by @Not-Nik
+[build][Zig] REVIEWED: Using `addLibrary()` and set root modules manually by @myQwil
+[build][Zig] REVIEWED: `build.zig.zon`, use the new zig v0.14 version (#4819) by @zewenn
+[build][Zig] REVIEWED: `build.zig.zon`, update hashes (#4826) by @david
+[build][Zig] REVIEWED: Improve build system (#4531) by @haxsam
+[build][Zig] REVIEWED: Properly generate Android triple by @lumenkeyes
+[build][Zig] REVIEWED: XCode-frameworks dependency for latest zig (#4675) by @mobiuscog
+
+[examples] ADDED: Missing examples VS2022 projects by @raysan5
+[examples] ADDED: Missing glsl120 shaders by @raysan5
+[examples] ADDED: Missing resources on some examples by @raysan5
+[examples] ADDED: `core_3d_fps_controller` by @agnis16
+[examples] ADDED: `core_clipboard_text` (#5231) by @robinsaviary
+[examples] ADDED: `core_delta_time` (#5216) by @robinsaviary
+[examples] ADDED: `core_directory_files` (#5230) by @hugo
+[examples] ADDED: `core_highdpi_testbed` by @raysan5
+[examples] ADDED: `core_highdpi_demo` example by @johnnymarler
+[examples] ADDED: `core_input_actions` (#5211) by @JettMonstersGoBoom
+[examples] ADDED: `core_keyboard_testbed` by @raysan5
+[examples] ADDED: `core_monitor_change` (#5215) by @maiconpintoabreu
+[examples] ADDED: `core_render_texture` by @raysan5
+[examples] ADDED: `core_text_file_loading` (#5278) by @NimComPoo-04
+[examples] ADDED: `core_undo_redo` by @raysan5
+[examples] ADDED: `core_viewport_scaling` (#5313) by @agnis16
+[examples] ADDED: `core_compute_hash` by @raysan5
+[examples] ADDED: `shapes_ball_physics` (#5372) by @davidbuzatto
+[examples] ADDED: `shapes_bullet_hell` (#5218) by @zerohorsepower
+[examples] ADDED: `shapes_clock_of_clocks` (#5263) by @themushroompirates
+[examples] ADDED: `shapes_clock_of_clocks` by @hmz-rhl
+[examples] ADDED: `shapes_dashed_line` (#5222) by @luis605
+[examples] ADDED: `shapes_double_pendulum` by @joecheong2006
+[examples] ADDED: `shapes_hilbert_curve` (#5454) by @hmz-rhl
+[examples] ADDED: `shapes_kaleidoscope` (#5233) by @hugo
+[examples] ADDED: `shapes_lines_drawing` (#5283) by @robinsaviary
+[examples] ADDED: `shapes_math_angle_rotation` (#5236) by @krispysnacc
+[examples] ADDED: `shapes_math_sine_cosine` (#5257) by @Jopestpe
+[examples] ADDED: `shapes_mouse_trail` (#5246) by @balamurugan
+[examples] ADDED: `shapes_particles` (#5260) by @JordSant
+[examples] ADDED: `shapes_penrose_tile` (#5376) by @davidbuzatto
+[examples] ADDED: `shapes_pie_chart` (#5227) by @GideonSerf
+[examples] ADDED: `shapes_recursive_tree` (#5229) by @Jopestpe
+[examples] ADDED: `shapes_rlgl_color_wheel` example (#5355) by @robinsaviary
+[examples] ADDED: `shapes_rlgl_triangle` example (#5353) by @robinsaviary
+[examples] ADDED: `shapes_starfield` (#5255) by @themushroompirates
+[examples] ADDED: `shapes_triangle_strip` (#5240) by @Jopestpe
+[examples] ADDED: `text_inline_styling` by @raysan5
+[examples] ADDED: `text_strings_management` (#5379) by @davidbuzatto
+[examples] ADDED: `text_words_alignment` (#5254) by @themushroompirates
+[examples] ADDED: `textured_clipboard_image` (#5604) by @maiconpintoabreu
+[examples] ADDED: `textures_cellular_automata` (#5395) by @JordSant
+[examples] ADDED: `textures_frame_buffer_rendering` (#5468) by @jackboakes
+[examples] ADDED: `textures_magnifying_glass` (#5587) by @dgamebillda
+[examples] ADDED: `textures_screen_buffer` (#5357) by @agnis16
+[examples] ADDED: `textures_sprite_stacking` example (#5345) by @robinsaviary
+[examples] ADDED: `models_animation_timing` by @raysan5
+[examples] ADDED: `models_directional_billboard` (#5351) by @robinsaviary
+[examples] ADDED: `models_animation_bone_blending` (#5543) by @dmitrii-brand
+[examples] ADDED: `models_basic_voxel` (#5212) by @timlittle88
+[examples] ADDED: `models_decals` (#5298) by @themushroompirates
+[examples] ADDED: `models_geometry_textures_cube` (#5221) by @Jopestpe
+[examples] ADDED: `models_tesseract` by @raysan5
+[examples] ADDED: `shaders_render_depth_texture` by @luis605
+[examples] ADDED: `shaders_ascii_rendering` (#5213) by @maiconpintoabreu
+[examples] ADDED: `shaders_color_correction` (#5307) by @JordSant
+[examples] ADDED: `shaders_game_of_life` (#5394) by @JordSant
+[examples] ADDED: `shaders_mandelbrot_set` (#5282) by @JordSant
+[examples] ADDED: `shaders_normalmap` by @Sir-Irk
+[examples] ADDED: `shaders_rounded_rectangle` (#4719) by @anstropleuton
+[examples] ADDED: `shaders_view_depth` (luis605)
+[examples] ADDED: `audio_sound_positionning` by @Bigfoot71
+[examples] REMOVED: `core_gamepad_info` by @raysan5
+[examples] REMOVED: `core_loading_thread` by @raysan5
+[examples] RENAMED: Sprite fonts resource directory by @raysan5
+[examples] RENAMED: `core_3d_fps_controller` to `core_3d_camera_fps` by @raysan5
+[examples] RENAMED: `core_high_dpi` to `core_highdpi_demo` by @raysan5
+[examples] RENAMED: `core_input_gestures_web` to `core_input_gestures_testbed` by @raysan5
+[examples] RENAMED: `shapes_draw_circle_sector` to `shapes_circle_sector_drawing` by @raysan5
+[examples] RENAMED: `shapes_draw_rectangle_rounded` to `shapes_rounded_rectangle_drawing` by @raysan5
+[examples] RENAMED: `shapes_draw_ring` to `shapes_ring_drawing` by @raysan5
+[examples] RENAMED: `shapes_easings_ball_anim` to `shapes_easings_ball` by @raysan5
+[examples] RENAMED: `shapes_easings_box_anim` to `shapes_easings_box` by @raysan5
+[examples] RENAMED: `shapes_easings_rectangle_array` to `shapes_easings_rectangles` by @raysan5
+[examples] RENAMED: `text_draw_3d` to `text_3d_drawing` by @raysan5
+[examples] RENAMED: `text_raylib_fonts` -> `text_sprite_fonts` by @raysan5
+[examples] RENAMED: `text_unicode` to `text_unicode_emojis` by @raysan5
+[examples] RENAMED: `textures_draw_tiled` to `textures_tiled_drawing` by @raysan5
+[examples] RENAMED: `textures_polygon` to `textures_polygon_drawing` by @raysan5
+[examples] RENAMED: `textures_sprite_anim` to `textures_sprite_animation` by @raysan5
+[examples] RENAMED: `models_animation` to `models_animation_playing` by @raysan5
+[examples] RENAMED: `models_billboard` to `models_billboard_rendering` by @raysan5
+[examples] RENAMED: `models_cubicmap` to `models_cubicmap_rendering` by @raysan5
+[examples] RENAMED: `models_draw_cube_texture` to `models_textured_cube` by @raysan5
+[examples] RENAMED: `models_geometry_textures_cube` to `models_rotating_cube` by @raysan5
+[examples] RENAMED: `models_gpu_skinning` to `models_animation_gpu_skinning` by @raysan5
+[examples] RENAMED: `models_heightmap` to `models_heightmap_rendering` by @raysan5
+[examples] RENAMED: `models_skybox` to `models_skybox_rendering` by @raysan5
+[examples] RENAMED: `shaders_deferred_render` to `shaders_deferred_rendering` by @raysan5
+[examples] RENAMED: `shaders_eratosthenes` to `shaders_eratosthenes_sieve` by @raysan5
+[examples] RENAMED: `shaders_fog` to `shaders_fog_rendering` by @raysan5
+[examples] RENAMED: `shaders_hybrid_render` to `shaders_hybrid_rendering` by @raysan5
+[examples] RENAMED: `shaders_lightmap` to `shaders_lightmap_rendering` by @raysan5
+[examples] RENAMED: `shaders_normal_map` to `shaders_normalmap_rendering` by @raysan5
+[examples] RENAMED: `shaders_raymarching` to `shaders_raymarching_rendering` by @raysan5
+[examples] RENAMED: `shaders_shadowmap` to `shaders_shadowmap_rendering` by @raysan5
+[examples] RENAMED: `shaders_spotlight` to `shaders_spotlight_rendering` by @raysan5
+[examples] RENAMED: `shaders_texture_drawing` to `shaders_texture_rendering` by @raysan5
+[examples] RENAMED: `shaders_view_depth` to `shaders_depth_rendering` by @raysan5
+[examples] RENAMED: `shaders_write_depth` to `shaders_depth_writing` by @raysan5
+[examples] RENAMED: `shaders_normalmap` to `shaders_normal_map` by @raysan5
+[examples] RENAMED: `audio_fft_spectrum_visualizer` to `audio_spectrum_visualizer` by @raysan5
+[examples] REVIEWED: All examples header section comments, for better organization and consistency by @raysan5
+[examples] REVIEWED: All examples MSVC warnings and non-working examples by @Jeffm2501
+[examples] REVIEWED: Moved some examples out of `others` category, removing category by @raysan5
+[examples] REVIEWED: Shaders formating to follow raylib code conventions by @raysan5
+[examples] REVIEWED: `examples_template`, adding info about new rexm tool by @raysan5
+[examples] REVIEWED: `core_2d_camera_mouse_zoom` by @raysan5
+[examples] REVIEWED: `core_3d_camera_fps` by @raysan5
+[examples] REVIEWED: `core_3d_fps_controller` by @agnis16
+[examples] REVIEWED: `core_3d_fps_controller` by @raysan5
+[examples] REVIEWED: `core_clipboard_text` by @raysan5
+[examples] REVIEWED: `core_custom_frame_control`, to work properly on web by @PanicTitan
+[examples] REVIEWED: `core_custom_frame_control`, avoid divide by 0 by @johnnymarler
+[examples] REVIEWED: `core_delta_time` by @raysan5
+[examples] REVIEWED: `core_directory_files` by @raysan5
+[examples] REVIEWED: `core_highdpi_testbed` by @raysan5
+[examples] REVIEWED: `core_input_actions` by @raysan5
+[examples] REVIEWED: `core_input_gamepad, fix hardcoded gamepad 0 by @lepasona
+[examples] REVIEWED: `core_input_gamepad` by @raysan5
+[examples] REVIEWED: `core_input_gestures_testbed` by @raysan5
+[examples] REVIEWED: `core_monitor_detector` by @raysan5
+[examples] REVIEWED: `core_random_sequence` by @raysan5
+[examples] REVIEWED: `core_render_texture` by @raysan5
+[examples] REVIEWED: `core_text_file_loading` (#5339) by @cs24b016
+[examples] REVIEWED: `core_undo_redo` by @raysan5
+[examples] REVIEWED: `core_viewport_scaling` by @raysan5
+[examples] REVIEWED: `core_window_flags` by @raysan5
+[examples] REVIEWED: `core_window_flags`, add borderless windowed toggle by @johnnymarler
+[examples] REVIEWED: `core_window_flags`, prevent immediate window restore from minimize by @johnnymarler
+[examples] REVIEWED: `core_window_letterbox` by @raysan5
+[examples] REVIEWED: `core_input_gamepad`, vibration test button (#5362) by @sergii
+[examples] REVIEWED: `core_directory_files` (#5343) by @hugo
+[examples] REVIEWED: `core_input_virtual_controls` (#4584) by @danilwhale
+[examples] REVIEWED: `shapes_bouncing_ball`, added gravity (#5217) by @Jopestpe
+[examples] REVIEWED: `shapes_kaleidoscope` rewind, forward and reset buttons (#5369) by @hugo
+[examples] REVIEWED: `shapes_digital_clock` by @raysan5
+[examples] REVIEWED: `shapes_bullet_hell` by @raysan5
+[examples] REVIEWED: `shapes_double_pendulum` by @raysan5
+[examples] REVIEWED: `shapes_easings_testbed` by @raysan5
+[examples] REVIEWED: `shapes_hilbert_curve` #5454 by @raysan5
+[examples] REVIEWED: `shapes_hilbert_curve` by @raysan5
+[examples] REVIEWED: `shapes_lines_drawing` by @raysan5
+[examples] REVIEWED: `shapes_penrose_tile` by @raysan5
+[examples] REVIEWED: `shapes_penrose_tile` formating by @raysan5
+[examples] REVIEWED: `shapes_pie_chart` by @raysan5
+[examples] REVIEWED: `shapes_rlgl_triangle` by @raysan5
+[examples] REVIEWED: `shapes_triangle_strip`, fix array size and simplify loop (#5280) by @Jopestpe
+[examples] REVIEWED: `text_draw_3d` by @zeankey
+[examples] REVIEWED: `text_font_sdf` by @raysan5
+[examples] REVIEWED: `text_inline_styling` by @raysan5
+[examples] REVIEWED: `text_raylib_fonts` by @raysan5
+[examples] REVIEWED: `text_unicode_ranges` by @raysan5
+[examples] REVIEWED: `text_words_alignment` (#5411) by @lucarandrianirina2507
+[examples] REVIEWED: `text_draw_3d`, fix text size by @zeankey
+[examples] REVIEWED: `textures_bunnymark`, replaced bunny image #5344 by @raysan5
+[examples] REVIEWED: `textures_clipboard_image` by @raysan5
+[examples] REVIEWED: `textures_framebuffer_rendering` by @raysan5
+[examples] REVIEWED: `textures_image_kernel` by @raysan5
+[examples] REVIEWED: `textures_screen_buffer` by @raysan5
+[examples] REVIEWED: `textures_sprite_stacking` by @raysan5
+[examples] REVIEWED: `textures_textured_curve` (#5463) by @Jeffm2501
+[examples] REVIEWED: `textures_bunnymark` by @raysan5
+[examples] REVIEWED: `models_first_person_maze` (#5478) by @pauldahacker
+[examples] REVIEWED: `models_decals`, fixed unload crash, added buttons (#5306) by @themushroompirates
+[examples] REVIEWED: `models_animation_bone_blending` by @raysan5
+[examples] REVIEWED: `models_basic_voxel` by @raysan5
+[examples] REVIEWED: `models_basic_voxel`, fix raycasting logic (#5643) by @SardineMilk
+[examples] REVIEWED: `models_basic_voxel`, replaced `GetRenderWidth()` by `GetScreenWidth()` (#5635) by @SardineMilk
+[examples] REVIEWED: `models_decals` by @raysan5
+[examples] REVIEWED: `models_first_person_maze` by @raysan5
+[examples] REVIEWED: `models_loading_vox` by @raysan5
+[examples] REVIEWED: `models_mesh_picking` by @raysan5
+[examples] REVIEWED: `models_point_rendering` by @raysan5
+[examples] REVIEWED: `models_rlgl_solar_system` by @raysan5
+[examples] REVIEWED: `models_skybox_rendering` by @raysan5
+[examples] REVIEWED: `models_textures_tiling` shaders by @raysan5
+[examples] REVIEWED: `models_animation_blending` by @raysan5
+[examples] REVIEWED: `shaders_ascii_rendering` (#5219) by @maiconpintoabreu
+[examples] REVIEWED: `shaders_ascii_rendering` by @raysan5
+[examples] REVIEWED: `shaders_basic_pbr`, to work on web (#4516) by @afanolovcic
+[examples] REVIEWED: `shaders_color_correction` by @raysan5
+[examples] REVIEWED: `shaders_defered_render` for OpenGL ES 3.0 (#4617) by @Bigfoot71
+[examples] REVIEWED: `shaders_deferred_render` (#4676) by @veins1
+[examples] REVIEWED: `shaders_deferred_render` by @raysan5
+[examples] REVIEWED: `shaders_deferred_rendering` by @raysan5
+[examples] REVIEWED: `shaders_game_of_life` by @raysan5
+[examples] REVIEWED: `shaders_game_of_life` for web (#5399) by @JordSant
+[examples] REVIEWED: `shaders_hybrid_rendering`, shaders issues by @raysan5
+[examples] REVIEWED: `shaders_julia_set` by @raysan5
+[examples] REVIEWED: `shaders_mandelbrot_set` (#5310) by @JordSant
+[examples] REVIEWED: `shaders_mandelbrot_set` for WebGL (#5286) by @JordSant
+[examples] REVIEWED: `shaders_mesh_instancing` by @raysan5
+[examples] REVIEWED: `shaders_multi_sample2d` by @raysan5
+[examples] REVIEWED: `shaders_normal_map` by @raysan5
+[examples] REVIEWED: `shaders_normalmap_rendering` by @raysan5
+[examples] REVIEWED: `shaders_normalmap` #5032 by @raysan5
+[examples] REVIEWED: `shaders_normalmap` by @raysan5
+[examples] REVIEWED: `shaders_rounded_rectangle` by @raysan5
+[examples] REVIEWED: `shaders_shadowmap_rendering` by @raysan5
+[examples] REVIEWED: `shaders_shadowmap_rendering` example by @raysan5
+[examples] REVIEWED: `shaders_spotlight` by @raysan5
+[examples] REVIEWED: `shaders_texture_drawing` by @raysan5
+[examples] REVIEWED: `shaders_cel_shading` by @raysan5
+[examples] REVIEWED: `shaders_cel_shading`, cel-shading and outline using inverted hull (#5615) by @galexeev
+[examples] REVIEWED: `audio_fft_spectrum_visualizer`, not working on web by @raysan5
+[examples] REVIEWED: `audio_music_stream` by @raysan5
+[examples] REVIEWED: `audio_sound_multi` by @raysan5
+[examples] REVIEWED: `audio_sound_positioning` by @dabbott
+[examples] REVIEWED: `rlgl_compute_shader` by @raysan5
+[examples] REVIEWED: `raylib_opengl_interop`, remove unnecessary defines (#5618) by @m0391n
+[examples] REVIEWED: `raylib_opengl_interop` single header library not having it's implementation loaded (#5498) by @jscaffidi
+[examples] REVIEWED: Example shader `depth_render.fs` by @raysan5
+[examples] REVIEWED: Example shader `depth_write.fs` by @raysan5
+[examples] REVIEWED: Example shader `normalmap.fs` by @raysan5
+[examples] REVIEWED: Example shader `palette_switch.fs` (#5205) by @benjaminsmallarz
+[examples] REVIEWED: Example shader `write_depth.fs` for glsl120 by @maiconpintoabreu
+[examples] REDESIGNED: `core_clipboard_text`, based on #5248 by @raysan5
+[examples] REDESIGNED: `shapes_digital_clock` by @raysan5
+[examples] REDESIGNED: `shapes_kaleidoscope`, store lines #5361 by @raysan5
+[examples] REDESIGNED: `text_unicode_ranges` by @raysan5
+[examples] REDESIGNED: `models_animation_blending` by @raysan5
+[examples] REDESIGNED: `audio_raw_stream`, remove callback usage (#5637) by @dan-hoang
+
+[bindings] ADDED: Common Lisp binding by @colin
+[bindings] ADDED: D Object Oriented wrapper (#4550) by @RealDoigt
+[bindings] ADDED: Dart binding (#5585) by @FinnDemonCat
+[bindings] ADDED: Deno binding for 5.5 (#5462) by @JJLDonley
+[bindings] ADDED: Jai binding (#4565) by @ahmedqarmout2
+[bindings] ADDED: Raylib-cs.BleedingEdge (#4999) by @danilwhale
+[bindings] ADDED: SwiftForth language binding (#5319) by @dave
+[bindings] ADDED: Wave language (#5539) by @youngjae681
+[bindings] ADDED: c3-lang for raylib 5.5 (#4555) by @afanolovcic
+[bindings] ADDED: chicken scheme (#5449) by @meowstr
+[bindings] ADDED: elle bindings (#5370) by @acquitefx
+[bindings] ADDED: raylib-ada (#5150) by @artem.v.ageev
+[bindings] ADDED: uiua bindings (#4993) by @marcosgrzesiak
+[bindings] ADDED: Ring language (#5421) by @SabeDoesThings
+[bindings] ADDED: ReiLua, Lua binding (#4589) by @legendaryredfox
+[bindings] ADDED: Matte bindings (#4586) by @legendaryredfox
+[bindings] UPDATED: Nim wrapper version (#4638) by @planetis-m
+[bindings] UPDATED: Raylib.nelua version (#4698) by @AuzFox
+[bindings] UPDATED: Fennel binding (#4585) by @0riginaln0
+[bindings] UPDATED: Jaylib to 5.5 (#4546) by @glowiak
+[bindings] UPDATED: Ruby binding (#4639) by @BotRandomness
+[bindings] UPDATED: V language binding (#4691) by @mobiuscog
+[bindings] UPDATED: `racket-raylib` version by @eutro
+[bindings] UPDATED: fortran-raylib to 5.5 (#4518) by @interkosmos
+[bindings] UPDATED: raylib-beef (#4514) by @Jannis.v.hagen
+[bindings] UPDATED: raylib-cpp to 5.5 (#4511) by @RobLoach
+[bindings] UPDATED: raylib-cs binding link (#4746) by @Rgebee
+[bindings] UPDATED: raylib-d to 5.5 (#4506) by @schveiguy
+[bindings] UPDATED: raylib-lua (#4567) by @legendaryredfox
+[bindings] UPDATED: raylib-py to 5.5 (#4519) by @jorgegomes83
+[bindings] UPDATED: raylib-python-cffi to 5.0 (#4512) by @villares
+[bindings] UPDATED: raylib-python-cffi to 5.5 (#4517) by @villares
+[bindings] UPDATED: raylib-zig by @Not-Nik
+[bindings] UPDATED: Multiple bindings (#4504, #4559, #4633, #4920, #5538, #5546)
+[bindings] REMOVED: Broken repo links from bindings (#4572) by @legendaryredfox
+[bindings] UPDATED: Factor bindings to 5.5 (#5648) by @ArnautDaniel
+[bindings] UPDATED: Raylib-cs to 5.5 (#4628) by @JupiterRider
+[bindings] UPDATED: raylib-go to 5.5 (#4566) by @JupiterRider
+[bindings] UPDATED: racket-raylib (#4884) by @eutro
+[bindings] UPDATED: raylib-odin binding license (#5647) by @jtorrestx
+[bindings] UPDATED: raylib-zig (#5103) by @Not-Nik
+[bindings] UPDATED: keybindings versions (#4570) by @legendaryredfox
+[bindings] UPDATED: Common Lisp binding (#5014) by @fosskers
+[bindings] REMOVED: raylib-v7 binding (#5090) by @Auios
+
+[rlparser] RENAMED: `raylib_parser` to `rlparser` by @raysan5
+[rlparser] REVIEWED: Command-line info by @raysan5
+[rexm] ADDED: Automated-testing system by @raysan5
+[rexm] ADDED: Build check warnings logs by @raysan5
+[rexm] ADDED: Command `update` to validate and update required files by @raysan5
+[rexm] ADDED: Example automated-testing by @raysan5
+[rexm] ADDED: Examples validation by @raysan5
+[rexm] ADDED: Implemented examples commands for automatic testing by @raysan5
+[rexm] ADDED: Implemented file rename requirements by @raysan5
+[rexm] ADDED: More detailed log info by @raysan5
+[rexm] ADDED: Read examples years created/reviewed info by @raysan5
+[rexm] ADDED: Resources scanning from examples for automated copying by @raysan5
+[rexm] ADDED: Security checks to verify examples categories provided by @raysan5
+[rexm] ADDED: Support example removal by @raysan5
+[rexm] ADDED: TestLog option for logs processing (without rebuilding) by @raysan5
+[rexm] ADDED: Web metadata validation and update by @raysan5
+[rexm] ADDED: Web platform logs automated reports by @raysan5
+[rexm] ADDED: `LoadExamplesData()` to support filtering and sorting by @raysan5
+[rexm] ADDED: `RemoveVSProjectFromSolution()` by @raysan5
+[rexm] ADDED: `AddVSProjectToSolution()` by @raysan5
+[rexm] ADDED: Examples buildind command by @raysan5
+[rexm] ADDED: Legend info on report generation by @raysan5
+[rexm] ADDED: `UpdateSourceMetadata()` by @raysan5
+[rexm] ADDED: Allow building web examples locally on Windows platform by @raysan5
+[rexm] ADDED: Generate second report with examples with issues by @raysan5
+[rexm] ADDED: Automatic validation and update of examples by @raysan5
+[rexm] ADDED: Automatically fix not found VS2022 project / solution by @raysan5
+[rexm] ADDED: Check example exists (compilation worked) before trying to run it by @raysan5
+[rexm] ADDED: Copy examples web-build files to `raylib.com` by @raysan5
+[rexm] ADDED: Remove duplicate entries on examples list on `update` process by @raysan5
+[rexm] ADDED: Automatic validation and update by @raysan5
+[rexm] ADDED: Example building, using default examples `Makefile`/`Makefile.Web` by @raysan5
+[rexm] ADDED: Rebuild to support full categories by @raysan5
+[rexm] ADDED: Support building full example collection and categories by @raysan5
+[rexm] ADDED: Support examples data `validation` and **report generation** by @raysan5
+[rexm] ADDED: Support paths customization with environment variables by @raysan5
+[rexm] ADDED: Support testing running on `PLATFORM_DRM` by @raysan5
+[rexm] REVIEWED: Fixed some issues, improved `make` call defining base path by @raysan5
+[rexm] REVIEWED: Avoid external tool for UUIDv4 generation, implement custom function by @raysan5
+[rexm] REVIEWED: Avoid updating metadata from `others` examples by @raysan5
+[rexm] REVIEWED: Allow external path definition for VS solution file by @raysan5
+[rexm] REVIEWED: Reports moved to reports directory by @raysan5
+[rexm] REVIEWED: Automated testing for Web by @raysan5
+[rexm] REVIEWED: Examples header info inconsistencies by @raysan5
+[rexm] REVIEWED: Get example info from example header when added, to be added to collection by @raysan5
+[rexm] REVIEWED: Makefile and default paths (#5224) by @Teeto44
+[rexm] REVIEWED: Testing report generation by @raysan5
+[rexm] REVIEWED: Update `nextCatIndex` (#5616) by @CrackedPixel
+[rexm] REVIEWED: Added variable assignment to rename option (#5077) by @lpow100
+[rexm] REVIEWED: Ran examples testing for macos (#5366) by @MaeBrooks
+[remx] REVIEWED: Add check for category on new name (#5093) by @maiconpintoabreu
+[remx] REVIEWED: Add warning for missing new name (#5092) by @maiconpintoabreu
+[rexm] REVIEWED: Add compiled rexm to gitignore (#5086) by @maiconpintoabreu
+[rexm] REVIEWED: Update examples status report when examples Updated by @raysan5
+[rexm] REVIEWED: `ScanExampleResources()` avoid resources to be saved by the program by @raysan5
+[rexm] REVIEWED: `UpdateSourceMetadata()` and `TextReplaceBetween()` by @raysan5
+[rexm] REVIEWED: `examples.js` example addition working by @raysan5
+[rexm] REVIEWED: `add` command logic for existing examplee addition by @raysan5
+[rexm] REVIEWED: Replace example name on project file by @raysan5
+[rexm] REVIEWED: Report issues if logs can not be loaded by @raysan5
+[rexm] REVIEWED: VS project adding to solution by @raysan5
+[rexm] REVIEWED: `UpdateSourceMetadata()` by @raysan5
+[rexm] REVIEWED: Example renaming on `examples.js` by @raysan5
+[rexm] REVIEWED: Examples source code headers metadata by @raysan5
+[rexm] REVIEWED: `README.md` generation improvements by @raysan5
+[rexm] REVIEWED: Store example resource paths by @raysan5
+[rexm] REVIEWED: `Makefile.Web` before trying to rebuild new example for web by @raysan5
+[rexm] REVIEWED: Using `Makefile.Web` for specific web versions generation by @raysan5
+
+[external] RENAMED: `rl_gputex.h` to `rltexgpu.h`, compressed textures loading
+[external] REVIEWED: `rltexgpu.h`, make it usable standalone by @raysan5
+[external] REVIEWED: `rltexgpu.h, fix the swizzling in `rl_load_dds_from_memory()` (#5422) by @msmith-codes
+[external]`REVIEWED: `rltexgpu.h, decouple logging and memory allocation from raylib by @sleeptightAnsiC
+[external] REVIEWED: `jar_mod.h`, buffer overflow on memcpy by @LoneAuios
+[external] REVIEWED: `sdefl` and `sinfl` issues (#5367) by @raysan5
+[external] REVIEWED: `sinfl_bsr()`, improvements by @RicoP
+[external] REVIEWED: `stb_truetype`, fix composite glyph scaling logic (#4811) by @ashishbhattarai
+[external] UPDATED: dr_libs (#5020) by @Emil2010
+[external] UPDATED: miniaudio to v0.11.22 (#4983) by @M374LX
+[external] UPDATED: miniaudio to v0.11.23 (#5234) by @pyrokn8
+[external] UPDATED: miniaudio to v0.11.24 (#5506) by @vdemcak
+[external] UPDATED: raygui to 5.0-dev for examples by @raysan5
+[external] UPDATED: RGFW to 1.5 (#4688) by @ColleagueRiley
+[external] UPDATED: RGFW to 1.6 (#4795) by @colleagueRiley
+[external] UPDATED: RGFW to 1.7 (#4965) by @M374LX
+[external] UPDATED: RGFW to 1.7.5-dev (#4976) by @M374LX
+[external] UPDATED: RGFW to 2.0.0 (#5582) by @CrackedPixel
+
+[misc] ADDED: SECURITY.md for security reporting policies by @raysan5
+[misc] ADDED: `examples/examples_list`, to be used by `rexm` or other tools by @raysan5
+[misc] ADDED: `fix_win32_compatibility.h`, utility header to avoid `windows.h` inclusion conflicts by @Jeffm2501
+[misc] RENAMED: Move and rename `raylib_parser` to `tools/rlparser` by @raysan5 -WARNING-
+[misc] REVIEWED: Avoid `realloc()` usage, security improvement by @raysan5
+[misc] REVIEWED: Prioritize `calloc()` calls than `malloc()` on some cases by @raysan5
+[misc] REVIEWED: Code comments using imperative format by @raysan5
+[misc] REVIEWED: Webpage reference comments start with `REF:`, more consistent with `TODO:` and `NOTE:` comments by @raysan5
+[misc] REVIEWED: CONVENTIONS.md, added additional conventions by @raysan5
+[misc] REVIEWED: ROADMAP.md with potential future improvements by @raysan5
+[misc] REVIEWED: Comments formating, using imperative mode by @raysan5
+[misc] REVIEWED: Multiple examples inconsistencies on heeaders and overall structure to follow template by @raysan5
+[misc] REVIEWED: Code gardening: cleaning, reviewed comments, warnings, variables names... by @raysan5, @JeffM2501, @maiconpintoabreu, @CrackedPixel
-------------------------------------------------------------------------
Release: raylib 5.5 (18 November 2024)
-------------------------------------------------------------------------
KEY CHANGES:
- - New tool: raylib project creator
- - New rcore backends: RGFW and SDL3
+ - New tool: raylib project creator [rpc]
+ - New platform backends: RGFW
+ - New platform backends: SDL3 (along SDL2)
- New platforms supported: Dreamcast, N64, PSP, PSVita, PS4
- Added GPU Skinning support (all platforms and GL versions)
- Added raymath C++ operators
@@ -137,9 +896,9 @@ Detailed changes:
[rlgl] ADDED: Vertex normals for RLGL immediate drawing mode (#3866) by @bohonghuang -WARNING-
[rlgl] ADDED: `rlCullDistance*()` variables and getters (#3912) by @KotzaBoss
[rlgl] ADDED: `rlSetClipPlanes()` function (#3912) by @KotzaBoss
-[rlgl] ADDED: `isGpuReady` flag, allow font loading with no GPU acceleration by @Ray -WARNING-
+[rlgl] ADDED: `isGpuReady` flag, allow font loading with no GPU acceleration by @raysan5 -WARNING-
[rlgl] REVIEWED: Changed RLGL_VERSION from 4.5 to 5.0 (#3914) by @rsteinke1111
-[rlgl] REVIEWED: Shader load failing returns 0, instead of fallback by @Ray -WARNING-
+[rlgl] REVIEWED: Shader load failing returns 0, instead of fallback by @raysan5 -WARNING-
[rlgl] REVIEWED: Standalone mode default flags (#4334) by @Asdqwe
[rlgl] REVIEWED: Fix hardcoded index values in vboID array (#4312) by @JettMonstersGoBoom
[rlgl] REVIEWED: GLint64 did not exist before OpenGL 3.2 (#4284) by @Tchan0
@@ -203,7 +962,7 @@ Detailed changes:
[rtextures] ADDED: `ImageFromChannel()` (#4105) by @brccabral
[rtextures] ADDED: `ImageDrawLineEx()` (#4097) by @Bigfoot71
[rtextures] ADDED: `ImageDrawTriangle()` (#4094) by @Bigfoot71
-[rtextures] REMOVED: SVG files loading and drawing, moving it to raylib-extras by @Ray -WARNING-
+[rtextures] REMOVED: SVG files loading and drawing, moving it to raylib-extras by @raysan5 -WARNING-
[rtextures] REVIEWED: `LoadImage()`, added support for 3-channel QOI images (#4384) by @R-YaTian
[rtextures] REVIEWED: `LoadImageRaw()` #3926 by @raysan5
[rtextures] REVIEWED: `LoadImageColors()`, advance k in loop (#4120) by @brccabral
@@ -231,7 +990,7 @@ Detailed changes:
[rtext] ADDED: `TextToCamel()` (#4033) by @IoIxD
[rtext] ADDED: `TextToSnake()` (#4033) by @IoIxD
[rtext] ADDED: `TextToFloat()` (#3627) by @Benjamin Schmid Ties
-[rtext] REDESIGNED: `SetTextLineSpacing()` by @Ray -WARNING-
+[rtext] REDESIGNED: `SetTextLineSpacing()` by @raysan5 -WARNING-
[rtext] REVIEWED: `LoadFontDataBDF()` name and formating by @raysan5
[rtext] REVIEWED: `LoadFontDefault()`, initialize glyphs and recs to zero #4319 by @raysan5
[rtext] REVIEWED: `LoadFontEx()`, avoid default font fallback (#4077) by @Peter0x44 -WARNING-
@@ -239,7 +998,7 @@ Detailed changes:
[rtext] REVIEWED: `LoadBMFont()`, issue on not glyph data initialized by @raysan5
[rtext] REVIEWED: `LoadFontFromMemory()`, use strncpy() to fix buffer overflow (#3795) by @Mingjie Shen
[rtext] REVIEWED: `LoadCodepoints()` returning a freed ptr when count is 0 (#4089) by @Alice Nyaa
-[rtext] REVIEWED: `LoadFontData()` avoid fallback glyphs by @Ray -WARNING-
+[rtext] REVIEWED: `LoadFontData()` avoid fallback glyphs by @raysan5 -WARNING-
[rtext] REVIEWED: `LoadFontData()`, load image only if glyph has been found in font by @raysan5
[rtext] REVIEWED: `ExportFontAsCode()`, fix C++ compiler errors (#4013) by @DarkAssassin23
[rtext] REVIEWED: `MeasureTextEx()` height calculation (#3770) by @Marrony Neris
@@ -458,7 +1217,7 @@ Detailed changes:
[bindings] UPDATED: Python raylib-py v5.0.0beta1 (#3557) by @jorgegomes83
[bindings] UPDATED: raylib-d binding (#3561) by @schveiguy
[bindings] UPDATED: Janet (#3553) by @Dmitry Matveyev
-[bindings] UPDATED: Raylib.nelua (#3552) by @guy.smith764
+[bindings] UPDATED: Raylib.nelua (#3552) by @AuzFox
[bindings] UPDATED: raylib-cpp to 5.0 (#3551) by @RobLoach
[bindings] UPDATED: Pascal binding (#3548) by @Gunko Vadim
[external] UPDATED: stb_truetype.h to latest version by @raysan5
diff --git a/HISTORY.md b/HISTORY.md
index 7f5539816..b68ee44f4 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -419,7 +419,7 @@ Highlights for `raylib 4.5`:
- **`NEW` Support QOA audio format (import/export)**: Just a couple of months ago the new [QOA file format](https://qoaformat.org/) was published, a very simple, portable and open source quite-ok-audio file format. raylib already supports it, added to `raudio` module and including audio loading from file, loading from memory, streaming from file, streaming from memory and **exporting to QOA** audio format. **Because simplicity really matters to raylib!**
- - **`NEW` Module for compressed textures loading**: [`rl_gputex`](https://github.com/raysan5/raylib/blob/master/src/external/rl_gputex.h), a portable single-file header-only small library to load compressed texture file-formats (DDS, PKM, KTX, PVR, ASTC). Provided functionality is not new to raylib but it was part of the raylib `rtextures` module, now it has been moved into a separate self-contained library, **improving portability**. Note that this module is only intended to **load compressed data from files, ready to be uploaded to GPU**, no compression/decompression functionality is provided. This change is a first step towards a better modularization of raylib library.
+ - **`NEW` Module for compressed textures loading**: [`rl_gputex`](https://github.com/raysan5/raylib/blob/master/src/external/rltexgpu.h), a portable single-file header-only small library to load compressed texture file-formats (DDS, PKM, KTX, PVR, ASTC). Provided functionality is not new to raylib but it was part of the raylib `rtextures` module, now it has been moved into a separate self-contained library, **improving portability**. Note that this module is only intended to **load compressed data from files, ready to be uploaded to GPU**, no compression/decompression functionality is provided. This change is a first step towards a better modularization of raylib library.
- **Reviewed `rlgl` module for automatic limits checking**: Again, [`rlgl`](https://github.com/raysan5/raylib/blob/master/src/rlgl.h) has been reviewed to simplify usage. Now users do not need to worry about reaching the internal render-batch limits when they send their triangles to draw 2d/3d, `rlgl` manages it automatically! This change allows a **great simplification for other modules** like `rshapes`, `rtextures` and `rmodels` that do not need to worry about bufffer overflows and can just define as many vertex as desired!
@@ -533,7 +533,7 @@ Some astonishing numbers for this release:
- **+320** closed issues (for a TOTAL of **+2130**!)
- **+1800** commits since previous RELEASE (for a TOTAL of **+9600**!)
- **18** functions ADDED to raylib API (for a TOTAL of **599**!)
- - **??** functions REVIEWED with fixes and improvements
+ - **+50** new examples to learn from (for a TOTAL of **212**!)
- **+200** new contributors (for a TOTAL of **+840**!)
Highlights for `raylib 6.0`:
diff --git a/ROADMAP.md b/ROADMAP.md
index 9d333089a..10754e52b 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -13,16 +13,28 @@ Here is a wishlist with features and ideas to improve the library. Note that fea
_Current version of raylib is complete and functional but there is always room for improvements._
-**raylib 5.x**
- - [ ] `rcore`: Support additional platforms: iOS, consoles?
- - [x] `rcore_web`: Avoid GLFW dependency, functionality can be directly implemented using emscripten SDK
- - [x] `rlgl`: Review GLSL shaders naming conventions for consistency
- - [ ] `textures`: Improve compressed textures support, loading and saving
+**raylib 7.0**
+ - [ ] `rcore_desktop_win32`: Improve new Windows platform backend - inputs, highdpi
+ - [ ] `rcore_desktop_emscripten`: Improve new Web platform backend - inputs, highdpi
+ - [ ] `rcore_desktop_cocoa`: Create additional platform backend: macOS
+ - [ ] `rcore_desktop_x11`: Create additional platform backend: Linux/X11
+ - [ ] `rcore_desktop_wayland`: Create additional platform backend: Linux/Wayland
+ - [ ] `rcore`: Investigate alternative embedded platforms and realtime OSs
+ - [ ] `rlsw`: Software renderer optimizations: mipmaps, platform-specific SIMD
+ - [ ] `rtextures`: Consider moving N-patch system to separate example
+ - [ ] `rtextures`: Review blending modes system, provide more options or better samples
+ - [ ] `raudio`: Support microphone input, basic API to read microphone
+ - [ ] `rltexgpu`: Improve compressed textures support, loading and saving, improve KTX 2.0
+ - [ ] `rlobj`: Create OBJ loader, supporting material file separately (low priority)
+
+**raylib 6.0**
+ - [x] `rlsw`: New Software Renderer backend, pseudo-OpenGL 1.1 implementation
+ - [x] `rcore_emscripten`: New emscripten-only backend, avoiding GLFW dependency
+ - [x] `rlgl`: Review GLSL shaders naming conventions for consistency, redesigned shader API
- [x] `rmodels`: Improve 3d objects loading, specially animations (obj, gltf)
- [x] `examples`: Review all examples, add more and better code explanations
- - [x] Software renderer backend? Maybe using `Image` provided API
-**raylib 4.x**
+**raylib 5.0**
- [x] Split core module into separate platforms?
- [x] Redesign gestures system, improve touch inputs management
- [x] Redesign camera module (more flexible) ([#1143](https://github.com/raysan5/raylib/issues/1143), https://github.com/raysan5/raylib/discussions/2507)
@@ -30,7 +42,6 @@ _Current version of raylib is complete and functional but there is always room f
- [x] Focus on HTML5 ([raylib 5k gamejam](https://itch.io/jam/raylib-5k-gamejam)) and embedded platforms (RPI and similar SOCs)
- [x] Additional support libraries: [raygui](https://github.com/raysan5/raygui), [rres](https://github.com/raysan5/rres)
-
**raylib 4.0**
- [x] Improved consistency and coherency in raylib API
- [x] Continuous Deployment using GitHub Actions
diff --git a/cmake/LibraryConfigurations.cmake b/cmake/LibraryConfigurations.cmake
index 9e7efe792..7af078de0 100644
--- a/cmake/LibraryConfigurations.cmake
+++ b/cmake/LibraryConfigurations.cmake
@@ -190,7 +190,7 @@ if (NOT ${OPENGL_VERSION} MATCHES "OFF")
elseif (${OPENGL_VERSION} MATCHES "ES 3.0")
set(GRAPHICS "GRAPHICS_API_OPENGL_ES3")
elseif (${OPENGL_VERSION} MATCHES "Software")
- set(GRAPHICS "GRAPHICS_API_OPENGL_11_SOFTWARE")
+ set(GRAPHICS "GRAPHICS_API_OPENGL_SOFTWARE")
endif ()
if (NOT "${SUGGESTED_GRAPHICS}" STREQUAL "" AND NOT "${SUGGESTED_GRAPHICS}" STREQUAL "${GRAPHICS}")
message(WARNING "You are overriding the suggested GRAPHICS=${SUGGESTED_GRAPHICS} with ${GRAPHICS}! This may fail.")
diff --git a/examples/Makefile b/examples/Makefile
index 899d040e3..6b15d22ff 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -95,7 +95,7 @@ USE_EXTERNAL_GLFW ?= FALSE
GLFW_LINUX_ENABLE_WAYLAND ?= FALSE
GLFW_LINUX_ENABLE_X11 ?= TRUE
-# Enable support for X11 by default on Linux when using GLFW
+# Enable support for X11 by default on Linux when using RGFW
# NOTE: Wayland is disabled by default, only enable if you are sure
RGFW_LINUX_ENABLE_WAYLAND ?= FALSE
RGFW_LINUX_ENABLE_X11 ?= TRUE
@@ -169,8 +169,8 @@ ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_R
EMSDK_PATH ?= C:/raylib/emsdk
EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten
CLANG_PATH = $(EMSDK_PATH)/upstream/bin
- PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit
- NODE_PATH = $(EMSDK_PATH)/node/20.18.0_64bit/bin
+ PYTHON_PATH = $(EMSDK_PATH)/python/3.13.3_64bit
+ NODE_PATH = $(EMSDK_PATH)/node/22.16.0_64bit/bin
export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH):$$(PATH)
endif
endif
@@ -622,6 +622,7 @@ TEXTURES = \
textures/textures_blend_modes \
textures/textures_bunnymark \
textures/textures_cellular_automata \
+ textures/textures_clipboard_image \
textures/textures_fog_of_war \
textures/textures_framebuffer_rendering \
textures/textures_gif_player \
@@ -634,6 +635,7 @@ TEXTURES = \
textures/textures_image_rotate \
textures/textures_image_text \
textures/textures_logo_raylib \
+ textures/textures_magnifying_glass \
textures/textures_mouse_painting \
textures/textures_npatch_drawing \
textures/textures_particles_blending \
@@ -703,6 +705,7 @@ SHADERS = \
shaders/shaders_ascii_rendering \
shaders/shaders_basic_lighting \
shaders/shaders_basic_pbr \
+ shaders/shaders_cel_shading \
shaders/shaders_color_correction \
shaders/shaders_custom_uniform \
shaders/shaders_deferred_rendering \
@@ -744,6 +747,7 @@ AUDIO = \
audio/audio_sound_multi \
audio/audio_sound_positioning \
audio/audio_spectrum_visualizer \
+ audio/audio_stream_callback \
audio/audio_stream_effects
#EXAMPLES_LIST_END
diff --git a/examples/Makefile.Web b/examples/Makefile.Web
index 648e5eef4..68c34f31b 100644
--- a/examples/Makefile.Web
+++ b/examples/Makefile.Web
@@ -168,8 +168,8 @@ ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_R
EMSDK_PATH ?= C:/raylib/emsdk
EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten
CLANG_PATH = $(EMSDK_PATH)/upstream/bin
- PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit
- NODE_PATH = $(EMSDK_PATH)/node/20.18.0_64bit/bin
+ PYTHON_PATH = $(EMSDK_PATH)/python/3.13.3_64bit
+ NODE_PATH = $(EMSDK_PATH)/node/22.16.0_64bit/bin
export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH):$$(PATH)
endif
endif
@@ -596,6 +596,7 @@ TEXTURES = \
textures/textures_blend_modes \
textures/textures_bunnymark \
textures/textures_cellular_automata \
+ textures/textures_clipboard_image \
textures/textures_fog_of_war \
textures/textures_framebuffer_rendering \
textures/textures_gif_player \
@@ -608,6 +609,7 @@ TEXTURES = \
textures/textures_image_rotate \
textures/textures_image_text \
textures/textures_logo_raylib \
+ textures/textures_magnifying_glass \
textures/textures_mouse_painting \
textures/textures_npatch_drawing \
textures/textures_particles_blending \
@@ -677,6 +679,7 @@ SHADERS = \
shaders/shaders_ascii_rendering \
shaders/shaders_basic_lighting \
shaders/shaders_basic_pbr \
+ shaders/shaders_cel_shading \
shaders/shaders_color_correction \
shaders/shaders_custom_uniform \
shaders/shaders_deferred_rendering \
@@ -718,6 +721,7 @@ AUDIO = \
audio/audio_sound_multi \
audio/audio_sound_positioning \
audio/audio_spectrum_visualizer \
+ audio/audio_stream_callback \
audio/audio_stream_effects
# Default target entry
@@ -1023,6 +1027,9 @@ textures/textures_bunnymark: textures/textures_bunnymark.c
textures/textures_cellular_automata: textures/textures_cellular_automata.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+textures/textures_clipboard_image: textures/textures_clipboard_image.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
textures/textures_fog_of_war: textures/textures_fog_of_war.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@@ -1071,6 +1078,11 @@ textures/textures_logo_raylib: textures/textures_logo_raylib.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/raylib_logo.png@resources/raylib_logo.png
+textures/textures_magnifying_glass: textures/textures_magnifying_glass.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
+ --preload-file textures/resources/raybunny.png@resources/raybunny.png \
+ --preload-file textures/resources/parrots.png@resources/parrots.png
+
textures/textures_mouse_painting: textures/textures_mouse_painting.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@@ -1365,6 +1377,14 @@ shaders/shaders_basic_pbr: shaders/shaders_basic_pbr.c
--preload-file shaders/resources/road_mra.png@resources/road_mra.png \
--preload-file shaders/resources/road_n.png@resources/road_n.png
+shaders/shaders_cel_shading: shaders/shaders_cel_shading.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
+ --preload-file shaders/resources/models/old_car_new.glb@resources/models/old_car_new.glb \
+ --preload-file shaders/resources/shaders/glsl100/cel.vs@resources/shaders/glsl100/cel.vs \
+ --preload-file shaders/resources/shaders/glsl100/cel.fs@resources/shaders/glsl100/cel.fs \
+ --preload-file shaders/resources/shaders/glsl100/outline_hull.vs@resources/shaders/glsl100/outline_hull.vs \
+ --preload-file shaders/resources/shaders/glsl100/outline_hull.fs@resources/shaders/glsl100/outline_hull.fs
+
shaders/shaders_color_correction: shaders/shaders_color_correction.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file shaders/resources/parrots.png@resources/parrots.png \
@@ -1550,7 +1570,8 @@ audio/audio_mixed_processor: audio/audio_mixed_processor.c
--preload-file audio/resources/coin.wav@resources/coin.wav
audio/audio_module_playing: audio/audio_module_playing.c
- $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
+ --preload-file audio/resources/mini1111.xm@resources/mini1111.xm
audio/audio_music_stream: audio/audio_music_stream.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
@@ -1577,6 +1598,9 @@ audio/audio_spectrum_visualizer: audio/audio_spectrum_visualizer.c
--preload-file audio/resources/shaders/glsl100/fft.fs@resources/shaders/glsl100/fft.fs \
--preload-file audio/resources/country.mp3@resources/country.mp3
+audio/audio_stream_callback: audio/audio_stream_callback.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
audio/audio_stream_effects: audio/audio_stream_effects.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file audio/resources/country.mp3@resources/country.mp3
diff --git a/examples/README.md b/examples/README.md
index a4e65b9f5..43e2dcc63 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -17,7 +17,7 @@ You may find it easier to use than other toolchains, especially when it comes to
- `zig build [module]` to compile all examples for a module (e.g. `zig build core`)
- `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`)
-## EXAMPLES COLLECTION [TOTAL: 208]
+## EXAMPLES COLLECTION [TOTAL: 212]
### category: core [49]
@@ -26,14 +26,14 @@ Examples using raylib [core](../src/rcore.c) module platform functionality: wind
| example | image | difficulty
level | version
created | last version
updated | original
developer |
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
| [core_basic_window](core/core_basic_window.c) |
| ⭐☆☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
-| [core_delta_time](core/core_delta_time.c) |
| ⭐☆☆☆ | 5.5 | 5.6-dev | [Robin](https://github.com/RobinsAviary) |
+| [core_delta_time](core/core_delta_time.c) |
| ⭐☆☆☆ | 5.5 | 6.0 | [Robin](https://github.com/RobinsAviary) |
| [core_input_keys](core/core_input_keys.c) |
| ⭐☆☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_input_mouse](core/core_input_mouse.c) |
| ⭐☆☆☆ | 1.0 | 5.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_input_mouse_wheel](core/core_input_mouse_wheel.c) |
| ⭐☆☆☆ | 1.1 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_input_gamepad](core/core_input_gamepad.c) |
| ⭐☆☆☆ | 1.1 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_input_multitouch](core/core_input_multitouch.c) |
| ⭐☆☆☆ | 2.1 | 2.5 | [Berni](https://github.com/Berni8k) |
| [core_input_gestures](core/core_input_gestures.c) |
| ⭐⭐☆☆ | 1.4 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
-| [core_input_gestures_testbed](core/core_input_gestures_testbed.c) |
| ⭐⭐⭐☆ | 5.0 | 5.6-dev | [ubkp](https://github.com/ubkp) |
+| [core_input_gestures_testbed](core/core_input_gestures_testbed.c) |
| ⭐⭐⭐☆ | 5.0 | 6.0 | [ubkp](https://github.com/ubkp) |
| [core_input_virtual_controls](core/core_input_virtual_controls.c) |
| ⭐⭐☆☆ | 5.0 | 5.0 | [GreenSnakeLinux](https://github.com/GreenSnakeLinux) |
| [core_2d_camera](core/core_2d_camera.c) |
| ⭐⭐☆☆ | 1.5 | 3.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_2d_camera_mouse_zoom](core/core_2d_camera_mouse_zoom.c) |
| ⭐⭐☆☆ | 4.2 | 4.2 | [Jeffery Myers](https://github.com/JeffM2501) |
@@ -62,16 +62,16 @@ Examples using raylib [core](../src/rcore.c) module platform functionality: wind
| [core_random_sequence](core/core_random_sequence.c) |
| ⭐☆☆☆ | 5.0 | 5.0 | [Dalton Overmyer](https://github.com/REDl3east) |
| [core_automation_events](core/core_automation_events.c) |
| ⭐⭐⭐☆ | 5.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_highdpi_demo](core/core_highdpi_demo.c) |
| ⭐⭐☆☆ | 5.0 | 5.5 | [Jonathan Marler](https://github.com/marler8997) |
-| [core_render_texture](core/core_render_texture.c) |
| ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
+| [core_render_texture](core/core_render_texture.c) |
| ⭐☆☆☆ | 6.0 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_undo_redo](core/core_undo_redo.c) |
| ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_viewport_scaling](core/core_viewport_scaling.c) |
| ⭐⭐☆☆ | 5.5 | 5.5 | [Agnis Aldiņš](https://github.com/nezvers) |
| [core_input_actions](core/core_input_actions.c) |
| ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) |
| [core_directory_files](core/core_directory_files.c) |
| ⭐☆☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) |
-| [core_highdpi_testbed](core/core_highdpi_testbed.c) |
| ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
-| [core_screen_recording](core/core_screen_recording.c) |
| ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
-| [core_clipboard_text](core/core_clipboard_text.c) |
| ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Ananth S](https://github.com/Ananth1839) |
+| [core_highdpi_testbed](core/core_highdpi_testbed.c) |
| ⭐☆☆☆ | 6.0 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
+| [core_screen_recording](core/core_screen_recording.c) |
| ⭐⭐☆☆ | 6.0 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
+| [core_clipboard_text](core/core_clipboard_text.c) |
| ⭐⭐☆☆ | 6.0 | 6.0 | [Ananth S](https://github.com/Ananth1839) |
| [core_text_file_loading](core/core_text_file_loading.c) |
| ⭐☆☆☆ | 5.5 | 5.6 | [Aanjishnu Bhattacharyya](https://github.com/NimComPoo-04) |
-| [core_compute_hash](core/core_compute_hash.c) |
| ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
+| [core_compute_hash](core/core_compute_hash.c) |
| ⭐⭐☆☆ | 6.0 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_keyboard_testbed](core/core_keyboard_testbed.c) |
| ⭐⭐☆☆ | 5.6 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_window_web](core/core_window_web.c) |
| ⭐☆☆☆ | 1.3 | 5.5 | [Ramon Santamaria](https://github.com/raysan5) |
@@ -94,7 +94,7 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
| [shapes_easings_ball](shapes/shapes_easings_ball.c) |
| ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [shapes_easings_box](shapes/shapes_easings_box.c) |
| ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [shapes_easings_rectangles](shapes/shapes_easings_rectangles.c) |
| ⭐⭐⭐☆ | 2.0 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
-| [shapes_recursive_tree](shapes/shapes_recursive_tree.c) |
| ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) |
+| [shapes_recursive_tree](shapes/shapes_recursive_tree.c) |
| ⭐⭐⭐☆ | 6.0 | 6.0 | [Jopestpe](https://github.com/jopestpe) |
| [shapes_ring_drawing](shapes/shapes_ring_drawing.c) |
| ⭐⭐⭐☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
| [shapes_circle_sector_drawing](shapes/shapes_circle_sector_drawing.c) |
| ⭐⭐⭐☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
| [shapes_rounded_rectangle_drawing](shapes/shapes_rounded_rectangle_drawing.c) |
| ⭐⭐⭐☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
@@ -104,30 +104,32 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
| [shapes_digital_clock](shapes/shapes_digital_clock.c) |
| ⭐⭐⭐⭐️ | 5.5 | 5.6 | [Hamza RAHAL](https://github.com/hmz-rhl) |
| [shapes_double_pendulum](shapes/shapes_double_pendulum.c) |
| ⭐⭐☆☆ | 5.5 | 5.5 | [JoeCheong](https://github.com/Joecheong2006) |
| [shapes_dashed_line](shapes/shapes_dashed_line.c) |
| ⭐☆☆☆ | 5.5 | 5.5 | [Luís Almeida](https://github.com/luis605) |
-| [shapes_triangle_strip](shapes/shapes_triangle_strip.c) |
| ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) |
+| [shapes_triangle_strip](shapes/shapes_triangle_strip.c) |
| ⭐⭐☆☆ | 6.0 | 6.0 | [Jopestpe](https://github.com/jopestpe) |
| [shapes_vector_angle](shapes/shapes_vector_angle.c) |
| ⭐⭐☆☆ | 1.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [shapes_pie_chart](shapes/shapes_pie_chart.c) |
| ⭐⭐⭐☆ | 5.5 | 5.6 | [Gideon Serfontein](https://github.com/GideonSerf) |
| [shapes_kaleidoscope](shapes/shapes_kaleidoscope.c) |
| ⭐⭐☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) |
-| [shapes_clock_of_clocks](shapes/shapes_clock_of_clocks.c) |
| ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) |
-| [shapes_math_sine_cosine](shapes/shapes_math_sine_cosine.c) |
| ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) |
-| [shapes_mouse_trail](shapes/shapes_mouse_trail.c) |
| ⭐☆☆☆ | 5.6 | 5.6-dev | [Balamurugan R](https://github.com/Bala050814) |
+| [shapes_clock_of_clocks](shapes/shapes_clock_of_clocks.c) |
| ⭐⭐☆☆ | 5.5 | 6.0 | [JP Mortiboys](https://github.com/themushroompirates) |
+| [shapes_math_sine_cosine](shapes/shapes_math_sine_cosine.c) |
| ⭐⭐☆☆ | 6.0 | 6.0 | [Jopestpe](https://github.com/jopestpe) |
+| [shapes_mouse_trail](shapes/shapes_mouse_trail.c) |
| ⭐☆☆☆ | 5.6 | 6.0 | [Balamurugan R](https://github.com/Bala050814) |
| [shapes_simple_particles](shapes/shapes_simple_particles.c) |
| ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
-| [shapes_starfield_effect](shapes/shapes_starfield_effect.c) |
| ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) |
-| [shapes_lines_drawing](shapes/shapes_lines_drawing.c) |
| ⭐☆☆☆ | 5.6-dev | 5.6 | [Robin](https://github.com/RobinsAviary) |
-| [shapes_math_angle_rotation](shapes/shapes_math_angle_rotation.c) |
| ⭐☆☆☆ | 5.6-dev | 5.6 | [Kris](https://github.com/krispy-snacc) |
-| [shapes_rlgl_color_wheel](shapes/shapes_rlgl_color_wheel.c) |
| ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) |
-| [shapes_rlgl_triangle](shapes/shapes_rlgl_triangle.c) |
| ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) |
-| [shapes_ball_physics](shapes/shapes_ball_physics.c) |
| ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [David Buzatto](https://github.com/davidbuzatto) |
-| [shapes_penrose_tile](shapes/shapes_penrose_tile.c) |
| ⭐⭐⭐⭐️ | 5.5 | 5.6-dev | [David Buzatto](https://github.com/davidbuzatto) |
+| [shapes_starfield_effect](shapes/shapes_starfield_effect.c) |
| ⭐⭐☆☆ | 5.5 | 6.0 | [JP Mortiboys](https://github.com/themushroompirates) |
+| [shapes_lines_drawing](shapes/shapes_lines_drawing.c) |
| ⭐☆☆☆ | 6.0 | 5.6 | [Robin](https://github.com/RobinsAviary) |
+| [shapes_math_angle_rotation](shapes/shapes_math_angle_rotation.c) |
| ⭐☆☆☆ | 6.0 | 5.6 | [Kris](https://github.com/krispy-snacc) |
+| [shapes_rlgl_color_wheel](shapes/shapes_rlgl_color_wheel.c) |
| ⭐⭐⭐☆ | 6.0 | 6.0 | [Robin](https://github.com/RobinsAviary) |
+| [shapes_rlgl_triangle](shapes/shapes_rlgl_triangle.c) |
| ⭐⭐☆☆ | 6.0 | 6.0 | [Robin](https://github.com/RobinsAviary) |
+| [shapes_ball_physics](shapes/shapes_ball_physics.c) |
| ⭐⭐☆☆ | 6.0 | 6.0 | [David Buzatto](https://github.com/davidbuzatto) |
+| [shapes_penrose_tile](shapes/shapes_penrose_tile.c) |
| ⭐⭐⭐⭐️ | 5.5 | 6.0 | [David Buzatto](https://github.com/davidbuzatto) |
| [shapes_hilbert_curve](shapes/shapes_hilbert_curve.c) |
| ⭐⭐⭐☆ | 5.6 | 5.6 | [Hamza RAHAL](https://github.com/hmz-rhl) |
| [shapes_easings_testbed](shapes/shapes_easings_testbed.c) |
| ⭐⭐⭐☆ | 2.5 | 2.5 | [Juan Miguel López](https://github.com/flashback-fx) |
-### category: textures [30]
+### category: textures [32]
Examples using raylib textures functionality, including image/textures loading/generation and drawing, provided by raylib [textures](../src/rtextures.c) module.
| example | image | difficulty
level | version
created | last version
updated | original
developer |
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
+| [textures_clipboard_image](textures/textures_clipboard_image.c) |
| ⭐☆☆☆ | 6.0 | 6.0 | [Maicon Santana](https://github.com/maiconpintoabreu) |
+| [textures_magnifying_glass](textures/textures_magnifying_glass.c) |
| ⭐⭐⭐☆ | 5.6 | 5.6 | [Luke Vaughan](https://github.com/badram) |
| [textures_logo_raylib](textures/textures_logo_raylib.c) |
| ⭐☆☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [textures_srcrec_dstrec](textures/textures_srcrec_dstrec.c) |
| ⭐⭐⭐☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) |
| [textures_image_drawing](textures/textures_image_drawing.c) |
| ⭐⭐☆☆ | 1.4 | 1.4 | [Ramon Santamaria](https://github.com/raysan5) |
@@ -155,7 +157,7 @@ Examples using raylib textures functionality, including image/textures loading/g
| [textures_image_rotate](textures/textures_image_rotate.c) |
| ⭐⭐☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [textures_screen_buffer](textures/textures_screen_buffer.c) |
| ⭐⭐☆☆ | 5.5 | 5.5 | [Agnis Aldiņš](https://github.com/nezvers) |
| [textures_textured_curve](textures/textures_textured_curve.c) |
| ⭐⭐⭐☆ | 4.5 | 4.5 | [Jeffery Myers](https://github.com/JeffM2501) |
-| [textures_sprite_stacking](textures/textures_sprite_stacking.c) |
| ⭐⭐☆☆ | 5.6-dev | 6.0 | [Robin](https://github.com/RobinsAviary) |
+| [textures_sprite_stacking](textures/textures_sprite_stacking.c) |
| ⭐⭐☆☆ | 6.0 | 6.0 | [Robin](https://github.com/RobinsAviary) |
| [textures_cellular_automata](textures/textures_cellular_automata.c) |
| ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
| [textures_framebuffer_rendering](textures/textures_framebuffer_rendering.c) |
| ⭐⭐☆☆ | 5.6 | 5.6 | [Jack Boakes](https://github.com/jackboakes) |
@@ -178,9 +180,9 @@ Examples using raylib text functionality, including sprite fonts loading/generat
| [text_unicode_ranges](text/text_unicode_ranges.c) |
| ⭐⭐⭐⭐️ | 5.5 | 5.6 | [Vadim Gunko](https://github.com/GuvaCode) |
| [text_3d_drawing](text/text_3d_drawing.c) |
| ⭐⭐⭐⭐️ | 3.5 | 4.0 | [Vlad Adrian](https://github.com/demizdor) |
| [text_codepoints_loading](text/text_codepoints_loading.c) |
| ⭐⭐⭐☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
-| [text_inline_styling](text/text_inline_styling.c) |
| ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Wagner Barongello](https://github.com/SultansOfCode) |
-| [text_words_alignment](text/text_words_alignment.c) |
| ⭐☆☆☆ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) |
-| [text_strings_management](text/text_strings_management.c) |
| ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [David Buzatto](https://github.com/davidbuzatto) |
+| [text_inline_styling](text/text_inline_styling.c) |
| ⭐⭐⭐☆ | 6.0 | 6.0 | [Wagner Barongello](https://github.com/SultansOfCode) |
+| [text_words_alignment](text/text_words_alignment.c) |
| ⭐☆☆☆ | 6.0 | 6.0 | [JP Mortiboys](https://github.com/themushroompirates) |
+| [text_strings_management](text/text_strings_management.c) |
| ⭐⭐⭐☆ | 6.0 | 6.0 | [David Buzatto](https://github.com/davidbuzatto) |
### category: models [30]
@@ -210,22 +212,22 @@ Examples using raylib models functionality, including models loading/generation
| [models_textured_cube](models/models_textured_cube.c) |
| ⭐⭐☆☆ | 4.5 | 4.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [models_animation_gpu_skinning](models/models_animation_gpu_skinning.c) |
| ⭐⭐⭐☆ | 4.5 | 4.5 | [Daniel Holden](https://github.com/orangeduck) |
| [models_bone_socket](models/models_bone_socket.c) |
| ⭐⭐⭐⭐️ | 4.5 | 4.5 | [iP](https://github.com/ipzaur) |
-| [models_tesseract_view](models/models_tesseract_view.c) |
| ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Timothy van der Valk](https://github.com/arceryz) |
+| [models_tesseract_view](models/models_tesseract_view.c) |
| ⭐⭐☆☆ | 6.0 | 6.0 | [Timothy van der Valk](https://github.com/arceryz) |
| [models_basic_voxel](models/models_basic_voxel.c) |
| ⭐⭐☆☆ | 5.5 | 5.5 | [Tim Little](https://github.com/timlittle) |
-| [models_rotating_cube](models/models_rotating_cube.c) |
| ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) |
-| [models_decals](models/models_decals.c) |
| ⭐⭐⭐⭐️ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) |
-| [models_directional_billboard](models/models_directional_billboard.c) |
| ⭐⭐☆☆ | 5.6-dev | 5.6 | [Robin](https://github.com/RobinsAviary) |
-| [models_animation_blend_custom](models/models_animation_blend_custom.c) |
| ⭐⭐⭐⭐️ | 5.5 | 5.5 | [dmitrii-brand](https://github.com/dmitrii-brand) |
-| [models_animation_blending](models/models_animation_blending.c) |
| ☆☆☆☆ | 5.5 | 5.6-dev | [Kirandeep](https://github.com/Kirandeep-Singh-Khehra) |
-| [models_animation_timming](models/models_animation_timming.c) |
| ⭐⭐☆☆ | 5.6 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
+| [models_rotating_cube](models/models_rotating_cube.c) |
| ⭐☆☆☆ | 6.0 | 6.0 | [Jopestpe](https://github.com/jopestpe) |
+| [models_decals](models/models_decals.c) |
| ⭐⭐⭐⭐️ | 6.0 | 6.0 | [JP Mortiboys](https://github.com/themushroompirates) |
+| [models_directional_billboard](models/models_directional_billboard.c) |
| ⭐⭐☆☆ | 6.0 | 6.0 | [Robin](https://github.com/RobinsAviary) |
+| [models_animation_blend_custom](models/models_animation_blend_custom.c) |
| ⭐⭐⭐⭐️ | 5.5 | 6.0 | [dmitrii-brand](https://github.com/dmitrii-brand) |
+| [models_animation_blending](models/models_animation_blending.c) |
| ⭐⭐⭐⭐️ | 5.5 | 6.0 | [Kirandeep](https://github.com/Kirandeep-Singh-Khehra) |
+| [models_animation_timing](models/models_animation_timing.c) |
| ⭐⭐⭐☆ | 6.0 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
-### category: shaders [34]
+### category: shaders [35]
Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.c) module.
| example | image | difficulty
level | version
created | last version
updated | original
developer |
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
-| [shaders_ascii_rendering](shaders/shaders_ascii_rendering.c) |
| ⭐⭐☆☆ | 5.5 | 5.6 | [Maicon Santana](https://github.com/maiconpintoabreu) |
+| [shaders_ascii_rendering](shaders/shaders_ascii_rendering.c) |
| ⭐⭐☆☆ | 5.5 | 6.0 | [Maicon Santana](https://github.com/maiconpintoabreu) |
| [shaders_basic_lighting](shaders/shaders_basic_lighting.c) |
| ⭐⭐⭐⭐️ | 3.0 | 4.2 | [Chris Camacho](https://github.com/chriscamacho) |
| [shaders_model_shader](shaders/shaders_model_shader.c) |
| ⭐⭐☆☆ | 1.3 | 3.7 | [Ramon Santamaria](https://github.com/raysan5) |
| [shaders_shapes_textures](shaders/shaders_shapes_textures.c) |
| ⭐⭐☆☆ | 1.7 | 3.7 | [Ramon Santamaria](https://github.com/raysan5) |
@@ -237,15 +239,15 @@ Examples using raylib shaders functionality, including shaders loading, paramete
| [shaders_texture_outline](shaders/shaders_texture_outline.c) |
| ⭐⭐⭐☆ | 4.0 | 4.0 | [Serenity Skiff](https://github.com/GoldenThumbs) |
| [shaders_texture_waves](shaders/shaders_texture_waves.c) |
| ⭐⭐☆☆ | 2.5 | 3.7 | [Anata](https://github.com/anatagawa) |
| [shaders_julia_set](shaders/shaders_julia_set.c) |
| ⭐⭐⭐☆ | 2.5 | 4.0 | [Josh Colclough](https://github.com/joshcol9232) |
-| [shaders_mandelbrot_set](shaders/shaders_mandelbrot_set.c) |
| ⭐⭐⭐☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
-| [shaders_color_correction](shaders/shaders_color_correction.c) |
| ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
+| [shaders_mandelbrot_set](shaders/shaders_mandelbrot_set.c) |
| ⭐⭐⭐☆ | 6.0 | 6.0 | [Jordi Santonja](https://github.com/JordSant) |
+| [shaders_color_correction](shaders/shaders_color_correction.c) |
| ⭐⭐☆☆ | 6.0 | 6.0 | [Jordi Santonja](https://github.com/JordSant) |
| [shaders_eratosthenes_sieve](shaders/shaders_eratosthenes_sieve.c) |
| ⭐⭐⭐☆ | 2.5 | 4.0 | [ProfJski](https://github.com/ProfJski) |
| [shaders_fog_rendering](shaders/shaders_fog_rendering.c) |
| ⭐⭐⭐☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) |
| [shaders_simple_mask](shaders/shaders_simple_mask.c) |
| ⭐⭐☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) |
| [shaders_hot_reloading](shaders/shaders_hot_reloading.c) |
| ⭐⭐⭐☆ | 3.0 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [shaders_mesh_instancing](shaders/shaders_mesh_instancing.c) |
| ⭐⭐⭐⭐️ | 3.7 | 4.2 | [seanpringle](https://github.com/seanpringle) |
| [shaders_multi_sample2d](shaders/shaders_multi_sample2d.c) |
| ⭐⭐☆☆ | 3.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
-| [shaders_normalmap_rendering](shaders/shaders_normalmap_rendering.c) |
| ⭐⭐⭐⭐️ | 5.6 | 5.6 | [Jeremy Montgomery](https://github.com/Sir_Irk) |
+| [shaders_normalmap_rendering](shaders/shaders_normalmap_rendering.c) |
| ⭐⭐⭐⭐️ | 6.0 | 6.0 | [Jeremy Montgomery](https://github.com/Sir_Irk) |
| [shaders_spotlight_rendering](shaders/shaders_spotlight_rendering.c) |
| ⭐⭐☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) |
| [shaders_deferred_rendering](shaders/shaders_deferred_rendering.c) |
| ⭐⭐⭐⭐️ | 4.5 | 4.5 | [Justin Andreas Lacoste](https://github.com/27justin) |
| [shaders_hybrid_rendering](shaders/shaders_hybrid_rendering.c) |
| ⭐⭐⭐⭐️ | 4.2 | 4.2 | [Buğra Alptekin Sarı](https://github.com/BugraAlptekinSari) |
@@ -256,11 +258,12 @@ Examples using raylib shaders functionality, including shaders loading, paramete
| [shaders_basic_pbr](shaders/shaders_basic_pbr.c) |
| ⭐⭐⭐⭐️ | 5.0 | 5.5 | [Afan OLOVCIC](https://github.com/_DevDad) |
| [shaders_lightmap_rendering](shaders/shaders_lightmap_rendering.c) |
| ⭐⭐⭐☆ | 4.5 | 4.5 | [Jussi Viitala](https://github.com/nullstare) |
| [shaders_rounded_rectangle](shaders/shaders_rounded_rectangle.c) |
| ⭐⭐⭐☆ | 5.5 | 5.5 | [Anstro Pleuton](https://github.com/anstropleuton) |
-| [shaders_depth_rendering](shaders/shaders_depth_rendering.c) |
| ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Luís Almeida](https://github.com/luis605) |
-| [shaders_game_of_life](shaders/shaders_game_of_life.c) |
| ⭐⭐⭐☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
+| [shaders_depth_rendering](shaders/shaders_depth_rendering.c) |
| ⭐⭐⭐☆ | 6.0 | 6.0 | [Luís Almeida](https://github.com/luis605) |
+| [shaders_game_of_life](shaders/shaders_game_of_life.c) |
| ⭐⭐⭐☆ | 6.0 | 6.0 | [Jordi Santonja](https://github.com/JordSant) |
| [shaders_rlgl_compute](shaders/shaders_rlgl_compute.c) |
| ⭐⭐⭐⭐️ | 4.0 | 4.0 | [Teddy Astie](https://github.com/tsnake41) |
+| [shaders_cel_shading](shaders/shaders_cel_shading.c) |
| ⭐⭐⭐☆ | 6.0 | 6.0 | [Gleb A](https://github.com/ggrizzly) |
-### category: audio [9]
+### category: audio [10]
Examples using raylib audio functionality, including sound/music loading and playing. This functionality is provided by raylib [raudio](../src/raudio.c) module. Note this module can be used standalone independently of raylib.
@@ -268,13 +271,14 @@ Examples using raylib audio functionality, including sound/music loading and pla
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
| [audio_module_playing](audio/audio_module_playing.c) |
| ⭐☆☆☆ | 1.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [audio_music_stream](audio/audio_music_stream.c) |
| ⭐☆☆☆ | 1.3 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
-| [audio_raw_stream](audio/audio_raw_stream.c) |
| ⭐⭐⭐☆ | 1.6 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
+| [audio_raw_stream](audio/audio_raw_stream.c) |
| ⭐⭐⭐☆ | 1.6 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [audio_sound_loading](audio/audio_sound_loading.c) |
| ⭐☆☆☆ | 1.1 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [audio_mixed_processor](audio/audio_mixed_processor.c) |
| ⭐⭐⭐⭐️ | 4.2 | 4.2 | [hkc](https://github.com/hatkidchan) |
| [audio_stream_effects](audio/audio_stream_effects.c) |
| ⭐⭐⭐⭐️ | 4.2 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [audio_sound_multi](audio/audio_sound_multi.c) |
| ⭐⭐☆☆ | 5.0 | 5.0 | [Jeffery Myers](https://github.com/JeffM2501) |
| [audio_sound_positioning](audio/audio_sound_positioning.c) |
| ⭐⭐☆☆ | 5.5 | 5.5 | [Le Juez Victor](https://github.com/Bigfoot71) |
-| [audio_spectrum_visualizer](audio/audio_spectrum_visualizer.c) |
| ⭐⭐⭐☆ | 6.0 | 5.6-dev | [IANN](https://github.com/meisei4) |
+| [audio_spectrum_visualizer](audio/audio_spectrum_visualizer.c) |
| ⭐⭐⭐☆ | 6.0 | 6.0 | [IANN](https://github.com/meisei4) |
+| [audio_stream_callback](audio/audio_stream_callback.c) |
| ⭐⭐⭐☆ | 6.0 | 6.0 | [Dan Hoang](https://github.com/dan-hoang) |
Some example missing? As always, contributions are welcome, feel free to send new examples!
Here is an [examples template](examples_template.c) with instructions to start with!
diff --git a/examples/audio/audio_spectrum_visualizer.c b/examples/audio/audio_spectrum_visualizer.c
index d2dbbbb57..f5ffe2f2d 100644
--- a/examples/audio/audio_spectrum_visualizer.c
+++ b/examples/audio/audio_spectrum_visualizer.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★★☆] 3/4
*
-* Example originally created with raylib 6.0, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Inspired by Inigo Quilez's https://www.shadertoy.com/
* Resources/specification: https://gist.github.com/soulthreads/2efe50da4be1fb5f7ab60ff14ca434b8
diff --git a/examples/audio/audio_stream_callback.c b/examples/audio/audio_stream_callback.c
index e31e8e80b..a033571d1 100644
--- a/examples/audio/audio_stream_callback.c
+++ b/examples/audio/audio_stream_callback.c
@@ -6,133 +6,53 @@
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
-* Example created by Dan Hoang (@dan-hoang) and reviewed by
+* Example created by Dan Hoang (@dan-hoang) and reviewed by Ramon Santamaria (@raysan5)
+*
+* NOTE: Example sends a wave to the audio device,
+* user gets the choice of four waves: sine, square, triangle, and sawtooth
+* A stream is set up to play to the audio device; stream is hooked to a callback that
+* generates a wave, that is determined by user choice
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
-* Copyright (c) 2015-2026
+* Copyright (c) 2026 Dan Hoang (@dan-hoang)
*
********************************************************************************************/
#include "raylib.h"
+
#include
#include
#define BUFFER_SIZE 4096
#define SAMPLE_RATE 44100
-// This example sends a wave to the audio device
-// The user gets the choice of four waves: sine, square, triangle, and sawtooth
-// A stream is set up to play to the audio device
-// The stream is hooked to a callback that generates a wave
-// The callback used is determined by user choice
-typedef enum
-{
+// Wave type
+typedef enum {
SINE,
SQUARE,
TRIANGLE,
SAWTOOTH
} WaveType;
-int waveFrequency = 440;
-int newWaveFrequency = 440;
-int waveIndex = 0;
+//------------------------------------------------------------------------------------
+// Module Functions Declaration
+//------------------------------------------------------------------------------------
+static void SineCallback(void *framesOut, unsigned int frameCount);
+static void SquareCallback(void *framesOut, unsigned int frameCount);
+static void TriangleCallback(void *framesOut, unsigned int frameCount);
+static void SawtoothCallback(void *framesOut, unsigned int frameCount);
-// Buffer for keeping the last second of uploaded audio, part of which will be drawn on the screen
-float buffer[SAMPLE_RATE] = {};
+static int waveFrequency = 440;
+static int newWaveFrequency = 440;
+static int waveIndex = 0;
-void SineCallback(void *framesOut, unsigned int frameCount)
-{
- int wavelength = SAMPLE_RATE/waveFrequency;
-
- // Synthesize the sine wave
- for (int i = 0; i < frameCount; i++)
- {
- ((float *)framesOut)[i] = sin(2*PI*waveIndex/wavelength);
-
- waveIndex++;
-
- if (waveIndex >= wavelength)
- {
- waveFrequency = newWaveFrequency;
- waveIndex = 0;
- }
- }
-
- // Save the synthesized samples for later drawing
- for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
- for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
-}
-
-void SquareCallback(void *framesOut, unsigned int frameCount)
-{
- int wavelength = SAMPLE_RATE/waveFrequency;
-
- // Synthesize the square wave
- for (int i = 0; i < frameCount; i++)
- {
- ((float *)framesOut)[i] = (waveIndex < wavelength/2)? 1 : -1;
- waveIndex++;
-
- if (waveIndex >= wavelength)
- {
- waveFrequency = newWaveFrequency;
- waveIndex = 0;
- }
- }
-
- // Save the synthesized samples for later drawing
- for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
- for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
-}
-
-void TriangleCallback(void *framesOut, unsigned int frameCount)
-{
- int wavelength = SAMPLE_RATE/waveFrequency;
-
- // Synthesize the triangle wave
- for (int i = 0; i < frameCount; i++)
- {
- ((float *)framesOut)[i] = (waveIndex < wavelength/2)? (-1 + 2.0f*waveIndex/(wavelength/2)) : (1 - 2.0f*(waveIndex - wavelength/2)/(wavelength/2));
- waveIndex++;
-
- if (waveIndex >= wavelength)
- {
- waveFrequency = newWaveFrequency;
- waveIndex = 0;
- }
- }
-
- // Save the synthesized samples for later drawing
- for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
- for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
-}
-
-void SawtoothCallback(void *framesOut, unsigned int frameCount)
-{
- int wavelength = SAMPLE_RATE/waveFrequency;
-
- // Synthesize the sawtooth wave
- for (int i = 0; i < frameCount; i++)
- {
- ((float *)framesOut)[i] = -1 + 2.0f*waveIndex/wavelength;
- waveIndex++;
-
- if (waveIndex >= wavelength)
- {
- waveFrequency = newWaveFrequency;
- waveIndex = 0;
- }
- }
-
- // Save the synthesized samples for later drawing
- for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
- for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
-}
-
-AudioCallback waveCallbacks[] = { SineCallback, SquareCallback, TriangleCallback, SawtoothCallback };
-char *waveTypesAsString[] = { "sine", "square", "triangle", "sawtooth" };
+// Buffer to keep the last second of uploaded audio,
+// part of which will be drawn on the screen
+static float buffer[SAMPLE_RATE] = { 0 };
+static AudioCallback waveCallbacks[] = { SineCallback, SquareCallback, TriangleCallback, SawtoothCallback };
+static char *waveTypesAsString[] = { "sine", "square", "triangle", "sawtooth" };
//------------------------------------------------------------------------------------
// Program main entry point
@@ -167,7 +87,6 @@ int main(void)
{
// Update
//----------------------------------------------------------------------------------
-
if (IsKeyDown(KEY_UP))
{
newWaveFrequency += 10;
@@ -199,7 +118,6 @@ int main(void)
SetAudioStreamCallback(stream, waveCallbacks[waveType]);
}
-
//----------------------------------------------------------------------------------
// Draw
@@ -226,7 +144,7 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
- UnloadAudioStream(stream); // Close raw audio stream and delete buffers from RAM
+ UnloadAudioStream(stream); // Close raw audio stream and delete buffers from RAM
CloseAudioDevice(); // Close audio device (music streaming is automatically stopped)
CloseWindow(); // Close window and OpenGL context
@@ -234,3 +152,95 @@ int main(void)
return 0;
}
+
+//------------------------------------------------------------------------------------
+// Module Functions Definition
+//------------------------------------------------------------------------------------
+static void SineCallback(void *framesOut, unsigned int frameCount)
+{
+ int wavelength = SAMPLE_RATE/waveFrequency;
+
+ // Synthesize the sine wave
+ for (int i = 0; i < frameCount; i++)
+ {
+ ((float *)framesOut)[i] = sin(2*PI*waveIndex/wavelength);
+
+ waveIndex++;
+
+ if (waveIndex >= wavelength)
+ {
+ waveFrequency = newWaveFrequency;
+ waveIndex = 0;
+ }
+ }
+
+ // Save the synthesized samples for later drawing
+ for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
+ for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
+}
+
+static void SquareCallback(void *framesOut, unsigned int frameCount)
+{
+ int wavelength = SAMPLE_RATE/waveFrequency;
+
+ // Synthesize the square wave
+ for (int i = 0; i < frameCount; i++)
+ {
+ ((float *)framesOut)[i] = (waveIndex < wavelength/2)? 1 : -1;
+ waveIndex++;
+
+ if (waveIndex >= wavelength)
+ {
+ waveFrequency = newWaveFrequency;
+ waveIndex = 0;
+ }
+ }
+
+ // Save the synthesized samples for later drawing
+ for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
+ for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
+}
+
+static void TriangleCallback(void *framesOut, unsigned int frameCount)
+{
+ int wavelength = SAMPLE_RATE/waveFrequency;
+
+ // Synthesize the triangle wave
+ for (int i = 0; i < frameCount; i++)
+ {
+ ((float *)framesOut)[i] = (waveIndex < wavelength/2)? (-1 + 2.0f*waveIndex/(wavelength/2)) : (1 - 2.0f*(waveIndex - wavelength/2)/(wavelength/2));
+ waveIndex++;
+
+ if (waveIndex >= wavelength)
+ {
+ waveFrequency = newWaveFrequency;
+ waveIndex = 0;
+ }
+ }
+
+ // Save the synthesized samples for later drawing
+ for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
+ for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
+}
+
+static void SawtoothCallback(void *framesOut, unsigned int frameCount)
+{
+ int wavelength = SAMPLE_RATE/waveFrequency;
+
+ // Synthesize the sawtooth wave
+ for (int i = 0; i < frameCount; i++)
+ {
+ ((float *)framesOut)[i] = -1 + 2.0f*waveIndex/wavelength;
+ waveIndex++;
+
+ if (waveIndex >= wavelength)
+ {
+ waveFrequency = newWaveFrequency;
+ waveIndex = 0;
+ }
+ }
+
+ // Save the synthesized samples for later drawing
+ for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
+ for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
+}
diff --git a/examples/core/core_clipboard_text.c b/examples/core/core_clipboard_text.c
index 59de6509c..6ced65654 100644
--- a/examples/core/core_clipboard_text.c
+++ b/examples/core/core_clipboard_text.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Ananth S (@Ananth1839) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/core/core_compute_hash.c b/examples/core/core_compute_hash.c
index f7d3ba9ac..890c14620 100644
--- a/examples/core/core_compute_hash.c
+++ b/examples/core/core_compute_hash.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
diff --git a/examples/core/core_delta_time.c b/examples/core/core_delta_time.c
index b77957ed6..26b0d13b1 100644
--- a/examples/core/core_delta_time.c
+++ b/examples/core/core_delta_time.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★☆☆☆] 1/4
*
-* Example originally created with raylib 5.5, last time updated with raylib 5.6-dev
+* Example originally created with raylib 5.5, last time updated with raylib 6.0
*
* Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/core/core_highdpi_testbed.c b/examples/core/core_highdpi_testbed.c
index cfff1f3c5..601d12e8c 100644
--- a/examples/core/core_highdpi_testbed.c
+++ b/examples/core/core_highdpi_testbed.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★☆☆☆] 1/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Ramon Santamaria (@raysan5) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/core/core_input_gestures_testbed.c b/examples/core/core_input_gestures_testbed.c
index e0ffeb13f..6cb09d0d2 100644
--- a/examples/core/core_input_gestures_testbed.c
+++ b/examples/core/core_input_gestures_testbed.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★★☆] 3/4
*
-* Example originally created with raylib 5.0, last time updated with raylib 5.6-dev
+* Example originally created with raylib 5.0, last time updated with raylib 6.0
*
* Example contributed by ubkp (@ubkp) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/core/core_render_texture.c b/examples/core/core_render_texture.c
index e30220a73..b11237ebc 100644
--- a/examples/core/core_render_texture.c
+++ b/examples/core/core_render_texture.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★☆☆☆] 1/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
diff --git a/examples/core/core_screen_recording.c b/examples/core/core_screen_recording.c
index 633ddcf81..33de31a5a 100644
--- a/examples/core/core_screen_recording.c
+++ b/examples/core/core_screen_recording.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
diff --git a/examples/examples_list.txt b/examples/examples_list.txt
index dc3312893..b5b27da1d 100644
--- a/examples/examples_list.txt
+++ b/examples/examples_list.txt
@@ -10,14 +10,14 @@
# This list is used as the main reference by [rexm] tool for examples collection validation and management
#
core;core_basic_window;★☆☆☆;1.0;1.0;2013;2025;"Ramon Santamaria";@raysan5
-core;core_delta_time;★☆☆☆;5.5;5.6-dev;2025;2025;"Robin";@RobinsAviary
+core;core_delta_time;★☆☆☆;5.5;6.0;2025;2025;"Robin";@RobinsAviary
core;core_input_keys;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
core;core_input_mouse;★☆☆☆;1.0;5.5;2014;2025;"Ramon Santamaria";@raysan5
core;core_input_mouse_wheel;★☆☆☆;1.1;1.3;2014;2025;"Ramon Santamaria";@raysan5
core;core_input_gamepad;★☆☆☆;1.1;4.2;2013;2025;"Ramon Santamaria";@raysan5
core;core_input_multitouch;★☆☆☆;2.1;2.5;2019;2025;"Berni";@Berni8k
core;core_input_gestures;★★☆☆;1.4;4.2;2016;2025;"Ramon Santamaria";@raysan5
-core;core_input_gestures_testbed;★★★☆;5.0;5.6-dev;2023;2025;"ubkp";@ubkp
+core;core_input_gestures_testbed;★★★☆;5.0;6.0;2023;2025;"ubkp";@ubkp
core;core_input_virtual_controls;★★☆☆;5.0;5.0;2024;2025;"GreenSnakeLinux";@GreenSnakeLinux
core;core_2d_camera;★★☆☆;1.5;3.0;2016;2025;"Ramon Santamaria";@raysan5
core;core_2d_camera_mouse_zoom;★★☆☆;4.2;4.2;2022;2025;"Jeffery Myers";@JeffM2501
@@ -46,16 +46,16 @@ core;core_smooth_pixelperfect;★★★☆;3.7;4.0;2021;2025;"Giancamillo Alessa
core;core_random_sequence;★☆☆☆;5.0;5.0;2023;2025;"Dalton Overmyer";@REDl3east
core;core_automation_events;★★★☆;5.0;5.0;2023;2025;"Ramon Santamaria";@raysan5
core;core_highdpi_demo;★★☆☆;5.0;5.5;2025;2025;"Jonathan Marler";@marler8997
-core;core_render_texture;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
+core;core_render_texture;★☆☆☆;6.0;6.0;2025;2025;"Ramon Santamaria";@raysan5
core;core_undo_redo;★★★☆;5.5;5.6;2025;2025;"Ramon Santamaria";@raysan5
core;core_viewport_scaling;★★☆☆;5.5;5.5;2025;2025;"Agnis Aldiņš";@nezvers
core;core_input_actions;★★☆☆;5.5;5.6;2025;2025;"Jett";@JettMonstersGoBoom
core;core_directory_files;★☆☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal
-core;core_highdpi_testbed;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
-core;core_screen_recording;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
-core;core_clipboard_text;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Ananth S";@Ananth1839
+core;core_highdpi_testbed;★☆☆☆;6.0;6.0;2025;2025;"Ramon Santamaria";@raysan5
+core;core_screen_recording;★★☆☆;6.0;6.0;2025;2025;"Ramon Santamaria";@raysan5
+core;core_clipboard_text;★★☆☆;6.0;6.0;2025;2025;"Ananth S";@Ananth1839
core;core_text_file_loading;★☆☆☆;5.5;5.6;0;0;"Aanjishnu Bhattacharyya";@NimComPoo-04
-core;core_compute_hash;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
+core;core_compute_hash;★★☆☆;6.0;6.0;2025;2025;"Ramon Santamaria";@raysan5
core;core_keyboard_testbed;★★☆☆;5.6;5.6;2026;2026;"Ramon Santamaria";@raysan5
core;core_window_web;★☆☆☆;1.3;5.5;2015;2025;"Ramon Santamaria";@raysan5
shapes;shapes_basic_shapes;★☆☆☆;1.0;4.2;2014;2025;"Ramon Santamaria";@raysan5
@@ -71,7 +71,7 @@ shapes;shapes_following_eyes;★★☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@
shapes;shapes_easings_ball;★★☆☆;2.5;2.5;2014;2025;"Ramon Santamaria";@raysan5
shapes;shapes_easings_box;★★☆☆;2.5;2.5;2014;2025;"Ramon Santamaria";@raysan5
shapes;shapes_easings_rectangles;★★★☆;2.0;2.5;2014;2025;"Ramon Santamaria";@raysan5
-shapes;shapes_recursive_tree;★★★☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe
+shapes;shapes_recursive_tree;★★★☆;6.0;6.0;2025;2025;"Jopestpe";@jopestpe
shapes;shapes_ring_drawing;★★★☆;2.5;2.5;2018;2025;"Vlad Adrian";@demizdor
shapes;shapes_circle_sector_drawing;★★★☆;2.5;2.5;2018;2025;"Vlad Adrian";@demizdor
shapes;shapes_rounded_rectangle_drawing;★★★☆;2.5;2.5;2018;2025;"Vlad Adrian";@demizdor
@@ -81,23 +81,25 @@ shapes;shapes_splines_drawing;★★★☆;5.0;5.0;2023;2025;"Ramon Santamaria";
shapes;shapes_digital_clock;★★★★;5.5;5.6;2025;2025;"Hamza RAHAL";@hmz-rhl
shapes;shapes_double_pendulum;★★☆☆;5.5;5.5;2025;2025;"JoeCheong";@Joecheong2006
shapes;shapes_dashed_line;★☆☆☆;5.5;5.5;2025;2025;"Luís Almeida";@luis605
-shapes;shapes_triangle_strip;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe
+shapes;shapes_triangle_strip;★★☆☆;6.0;6.0;2025;2025;"Jopestpe";@jopestpe
shapes;shapes_vector_angle;★★☆☆;1.0;5.0;2023;2025;"Ramon Santamaria";@raysan5
shapes;shapes_pie_chart;★★★☆;5.5;5.6;2025;2025;"Gideon Serfontein";@GideonSerf
shapes;shapes_kaleidoscope;★★☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal
-shapes;shapes_clock_of_clocks;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates
-shapes;shapes_math_sine_cosine;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe
-shapes;shapes_mouse_trail;★☆☆☆;5.6;5.6-dev;2025;2025;"Balamurugan R";@Bala050814
+shapes;shapes_clock_of_clocks;★★☆☆;5.5;6.0;2025;2025;"JP Mortiboys";@themushroompirates
+shapes;shapes_math_sine_cosine;★★☆☆;6.0;6.0;2025;2025;"Jopestpe";@jopestpe
+shapes;shapes_mouse_trail;★☆☆☆;5.6;6.0;2025;2025;"Balamurugan R";@Bala050814
shapes;shapes_simple_particles;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant
-shapes;shapes_starfield_effect;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates
-shapes;shapes_lines_drawing;★☆☆☆;5.6-dev;5.6;2025;2025;"Robin";@RobinsAviary
-shapes;shapes_math_angle_rotation;★☆☆☆;5.6-dev;5.6;2025;2025;"Kris";@krispy-snacc
-shapes;shapes_rlgl_color_wheel;★★★☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary
-shapes;shapes_rlgl_triangle;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary
-shapes;shapes_ball_physics;★★☆☆;5.6-dev;5.6-dev;2025;2025;"David Buzatto";@davidbuzatto
-shapes;shapes_penrose_tile;★★★★;5.5;5.6-dev;2025;2025;"David Buzatto";@davidbuzatto
+shapes;shapes_starfield_effect;★★☆☆;5.5;6.0;2025;2025;"JP Mortiboys";@themushroompirates
+shapes;shapes_lines_drawing;★☆☆☆;6.0;5.6;2025;2025;"Robin";@RobinsAviary
+shapes;shapes_math_angle_rotation;★☆☆☆;6.0;5.6;2025;2025;"Kris";@krispy-snacc
+shapes;shapes_rlgl_color_wheel;★★★☆;6.0;6.0;2025;2025;"Robin";@RobinsAviary
+shapes;shapes_rlgl_triangle;★★☆☆;6.0;6.0;2025;2025;"Robin";@RobinsAviary
+shapes;shapes_ball_physics;★★☆☆;6.0;6.0;2025;2025;"David Buzatto";@davidbuzatto
+shapes;shapes_penrose_tile;★★★★;5.5;6.0;2025;2025;"David Buzatto";@davidbuzatto
shapes;shapes_hilbert_curve;★★★☆;5.6;5.6;2025;2025;"Hamza RAHAL";@hmz-rhl
shapes;shapes_easings_testbed;★★★☆;2.5;2.5;2019;2025;"Juan Miguel López";@flashback-fx
+textures;textures_clipboard_image;★☆☆☆;6.0;6.0;2026;2026;"Maicon Santana";@maiconpintoabreu
+textures;textures_magnifying_glass;★★★☆;5.6;5.6;2026;2026;"Luke Vaughan";@badram
textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
textures;textures_srcrec_dstrec;★★★☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5
textures;textures_image_drawing;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5
@@ -125,7 +127,7 @@ textures;textures_image_channel;★★☆☆;5.5;5.5;2024;2025;"Bruno Cabral";@b
textures;textures_image_rotate;★★☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
textures;textures_screen_buffer;★★☆☆;5.5;5.5;2025;2025;"Agnis Aldiņš";@nezvers
textures;textures_textured_curve;★★★☆;4.5;4.5;2022;2025;"Jeffery Myers";@JeffM2501
-textures;textures_sprite_stacking;★★☆☆;5.6-dev;6.0;2025;2025;"Robin";@RobinsAviary
+textures;textures_sprite_stacking;★★☆☆;6.0;6.0;2025;2025;"Robin";@RobinsAviary
textures;textures_cellular_automata;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant
textures;textures_framebuffer_rendering;★★☆☆;5.6;5.6;2026;2026;"Jack Boakes";@jackboakes
text;text_sprite_fonts;★☆☆☆;1.7;3.7;2017;2025;"Ramon Santamaria";@raysan5
@@ -141,9 +143,9 @@ text;text_unicode_emojis;★★★★;2.5;4.0;2019;2025;"Vlad Adrian";@demizdor
text;text_unicode_ranges;★★★★;5.5;5.6;2025;2025;"Vadim Gunko";@GuvaCode
text;text_3d_drawing;★★★★;3.5;4.0;2021;2025;"Vlad Adrian";@demizdor
text;text_codepoints_loading;★★★☆;4.2;4.2;2022;2025;"Ramon Santamaria";@raysan5
-text;text_inline_styling;★★★☆;5.6-dev;5.6-dev;2025;2025;"Wagner Barongello";@SultansOfCode
-text;text_words_alignment;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates
-text;text_strings_management;★★★☆;5.6-dev;5.6-dev;2025;2025;"David Buzatto";@davidbuzatto
+text;text_inline_styling;★★★☆;6.0;6.0;2025;2025;"Wagner Barongello";@SultansOfCode
+text;text_words_alignment;★☆☆☆;6.0;6.0;2025;2025;"JP Mortiboys";@themushroompirates
+text;text_strings_management;★★★☆;6.0;6.0;2025;2025;"David Buzatto";@davidbuzatto
models;models_loading_iqm;★★☆☆;2.5;3.5;2019;2025;"Culacant";@culacant
models;models_billboard_rendering;★★★☆;1.3;3.5;2015;2025;"Ramon Santamaria";@raysan5
models;models_box_collisions;★☆☆☆;1.3;3.5;2015;2025;"Ramon Santamaria";@raysan5
@@ -166,15 +168,15 @@ models;models_skybox_rendering;★★☆☆;1.8;4.0;2017;2025;"Ramon Santamaria"
models;models_textured_cube;★★☆☆;4.5;4.5;2022;2025;"Ramon Santamaria";@raysan5
models;models_animation_gpu_skinning;★★★☆;4.5;4.5;2024;2025;"Daniel Holden";@orangeduck
models;models_bone_socket;★★★★;4.5;4.5;2024;2025;"iP";@ipzaur
-models;models_tesseract_view;★★☆☆;5.6-dev;5.6-dev;2024;2025;"Timothy van der Valk";@arceryz
+models;models_tesseract_view;★★☆☆;6.0;6.0;2024;2025;"Timothy van der Valk";@arceryz
models;models_basic_voxel;★★☆☆;5.5;5.5;2025;2025;"Tim Little";@timlittle
-models;models_rotating_cube;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe
-models;models_decals;★★★★;5.6-dev;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates
-models;models_directional_billboard;★★☆☆;5.6-dev;5.6;2025;2025;"Robin";@RobinsAviary
-models;models_animation_blend_custom;★★★★;5.5;5.5;2026;2026;"dmitrii-brand";@dmitrii-brand
-models;models_animation_blending;☆☆☆☆;5.5;5.6-dev;2024;2024;"Kirandeep";@Kirandeep-Singh-Khehra
-models;models_animation_timing;★★☆☆;5.6;5.6;2026;2026;"Ramon Santamaria";@raysan5
-shaders;shaders_ascii_rendering;★★☆☆;5.5;5.6;2025;2025;"Maicon Santana";@maiconpintoabreu
+models;models_rotating_cube;★☆☆☆;6.0;6.0;2025;2025;"Jopestpe";@jopestpe
+models;models_decals;★★★★;6.0;6.0;2025;2025;"JP Mortiboys";@themushroompirates
+models;models_directional_billboard;★★☆☆;6.0;6.0;2025;2025;"Robin";@RobinsAviary
+models;models_animation_blend_custom;★★★★;5.5;6.0;2026;2026;"dmitrii-brand";@dmitrii-brand
+models;models_animation_blending;★★★★;5.5;6.0;2024;2026;"Kirandeep";@Kirandeep-Singh-Khehra
+models;models_animation_timing;★★★☆;6.0;6.0;2026;2026;"Ramon Santamaria";@raysan5
+shaders;shaders_ascii_rendering;★★☆☆;5.5;6.0;2025;2025;"Maicon Santana";@maiconpintoabreu
shaders;shaders_basic_lighting;★★★★;3.0;4.2;2019;2025;"Chris Camacho";@chriscamacho
shaders;shaders_model_shader;★★☆☆;1.3;3.7;2014;2025;"Ramon Santamaria";@raysan5
shaders;shaders_shapes_textures;★★☆☆;1.7;3.7;2015;2025;"Ramon Santamaria";@raysan5
@@ -186,15 +188,15 @@ shaders;shaders_texture_rendering;★★☆☆;2.0;3.7;2019;2025;"Michał Ciesie
shaders;shaders_texture_outline;★★★☆;4.0;4.0;2021;2025;"Serenity Skiff";@GoldenThumbs
shaders;shaders_texture_waves;★★☆☆;2.5;3.7;2019;2025;"Anata";@anatagawa
shaders;shaders_julia_set;★★★☆;2.5;4.0;2019;2025;"Josh Colclough";@joshcol9232
-shaders;shaders_mandelbrot_set;★★★☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant
-shaders;shaders_color_correction;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant
+shaders;shaders_mandelbrot_set;★★★☆;6.0;6.0;2025;2025;"Jordi Santonja";@JordSant
+shaders;shaders_color_correction;★★☆☆;6.0;6.0;2025;2025;"Jordi Santonja";@JordSant
shaders;shaders_eratosthenes_sieve;★★★☆;2.5;4.0;2019;2025;"ProfJski";@ProfJski
shaders;shaders_fog_rendering;★★★☆;2.5;3.7;2019;2025;"Chris Camacho";@chriscamacho
shaders;shaders_simple_mask;★★☆☆;2.5;3.7;2019;2025;"Chris Camacho";@chriscamacho
shaders;shaders_hot_reloading;★★★☆;3.0;3.5;2020;2025;"Ramon Santamaria";@raysan5
shaders;shaders_mesh_instancing;★★★★;3.7;4.2;2020;2025;"seanpringle";@seanpringle
shaders;shaders_multi_sample2d;★★☆☆;3.5;3.5;2020;2025;"Ramon Santamaria";@raysan5
-shaders;shaders_normalmap_rendering;★★★★;5.6;5.6;2025;2025;"Jeremy Montgomery";@Sir_Irk
+shaders;shaders_normalmap_rendering;★★★★;6.0;6.0;2025;2025;"Jeremy Montgomery";@Sir_Irk
shaders;shaders_spotlight_rendering;★★☆☆;2.5;3.7;2019;2025;"Chris Camacho";@chriscamacho
shaders;shaders_deferred_rendering;★★★★;4.5;4.5;2023;2025;"Justin Andreas Lacoste";@27justin
shaders;shaders_hybrid_rendering;★★★★;4.2;4.2;2022;2025;"Buğra Alptekin Sarı";@BugraAlptekinSari
@@ -205,15 +207,17 @@ shaders;shaders_depth_writing;★★☆☆;4.2;4.2;2022;2025;"Buğra Alptekin Sa
shaders;shaders_basic_pbr;★★★★;5.0;5.5;2023;2025;"Afan OLOVCIC";@_DevDad
shaders;shaders_lightmap_rendering;★★★☆;4.5;4.5;2019;2025;"Jussi Viitala";@nullstare
shaders;shaders_rounded_rectangle;★★★☆;5.5;5.5;2025;2025;"Anstro Pleuton";@anstropleuton
-shaders;shaders_depth_rendering;★★★☆;5.6-dev;5.6-dev;2025;2025;"Luís Almeida";@luis605
-shaders;shaders_game_of_life;★★★☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant
+shaders;shaders_depth_rendering;★★★☆;6.0;6.0;2025;2025;"Luís Almeida";@luis605
+shaders;shaders_game_of_life;★★★☆;6.0;6.0;2025;2025;"Jordi Santonja";@JordSant
shaders;shaders_rlgl_compute;★★★★;4.0;4.0;2021;2025;"Teddy Astie";@tsnake41
+shaders;shaders_cel_shading;★★★☆;6.0;6.0;2026;2026;"Gleb A";@ggrizzly
audio;audio_module_playing;★☆☆☆;1.5;3.5;2016;2025;"Ramon Santamaria";@raysan5
audio;audio_music_stream;★☆☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5
-audio;audio_raw_stream;★★★☆;1.6;4.2;2015;2025;"Ramon Santamaria";@raysan5
+audio;audio_raw_stream;★★★☆;1.6;6.0;2015;2026;"Ramon Santamaria";@raysan5
audio;audio_sound_loading;★☆☆☆;1.1;3.5;2014;2025;"Ramon Santamaria";@raysan5
audio;audio_mixed_processor;★★★★;4.2;4.2;2023;2025;"hkc";@hatkidchan
audio;audio_stream_effects;★★★★;4.2;5.0;2022;2025;"Ramon Santamaria";@raysan5
audio;audio_sound_multi;★★☆☆;5.0;5.0;2023;2025;"Jeffery Myers";@JeffM2501
audio;audio_sound_positioning;★★☆☆;5.5;5.5;2025;2025;"Le Juez Victor";@Bigfoot71
-audio;audio_spectrum_visualizer;★★★☆;6.0;5.6-dev;2025;2025;"IANN";@meisei4
+audio;audio_spectrum_visualizer;★★★☆;6.0;6.0;2025;2025;"IANN";@meisei4
+audio;audio_stream_callback;★★★☆;6.0;6.0;2026;2026;"Dan Hoang";@dan-hoang
diff --git a/examples/models/models_animation_blend_custom.c b/examples/models/models_animation_blend_custom.c
index 005982ec6..8262f6ac2 100644
--- a/examples/models/models_animation_blend_custom.c
+++ b/examples/models/models_animation_blend_custom.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★★★] 4/4
*
-* Example originally created with raylib 5.5, last time updated with raylib 5.5
+* Example originally created with raylib 5.5, last time updated with raylib 6.0
*
* Example contributed by dmitrii-brand (@dmitrii-brand) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/models/models_animation_blending.c b/examples/models/models_animation_blending.c
index e44583299..e79067c3d 100644
--- a/examples/models/models_animation_blending.c
+++ b/examples/models/models_animation_blending.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★★★] 4/4
*
-* Example originally created with raylib 5.5, last time updated with raylib 5.6-dev
+* Example originally created with raylib 5.5, last time updated with raylib 6.0
*
* Example contributed by Kirandeep (@Kirandeep-Singh-Khehra) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/models/models_animation_timing.c b/examples/models/models_animation_timing.c
index 030ad81e1..a302322fe 100644
--- a/examples/models/models_animation_timing.c
+++ b/examples/models/models_animation_timing.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★★☆] 3/4
*
-* Example originally created with raylib 5.6, last time updated with raylib 5.6
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
diff --git a/examples/models/models_decals.c b/examples/models/models_decals.c
index 9eba33de6..6e80283f2 100644
--- a/examples/models/models_decals.c
+++ b/examples/models/models_decals.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★★★] 4/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by JP Mortiboys (@themushroompirates) and reviewed by Ramon Santamaria (@raysan5)
* Based on previous work by @mrdoob
diff --git a/examples/models/models_directional_billboard.c b/examples/models/models_directional_billboard.c
index caab94afb..56164943b 100644
--- a/examples/models/models_directional_billboard.c
+++ b/examples/models/models_directional_billboard.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/models/models_rlgl_solar_system.c b/examples/models/models_rlgl_solar_system.c
index 0988ede8d..1becc6348 100644
--- a/examples/models/models_rlgl_solar_system.c
+++ b/examples/models/models_rlgl_solar_system.c
@@ -66,8 +66,6 @@ int main(void)
{
// Update
//----------------------------------------------------------------------------------
- UpdateCamera(&camera, CAMERA_ORBITAL);
-
earthRotation += (5.0f*rotationSpeed);
earthOrbitRotation += (365/360.0f*(5.0f*rotationSpeed)*rotationSpeed);
moonRotation += (2.0f*rotationSpeed);
diff --git a/examples/models/models_rotating_cube.c b/examples/models/models_rotating_cube.c
index c5b633fea..7cfca1620 100644
--- a/examples/models/models_rotating_cube.c
+++ b/examples/models/models_rotating_cube.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★☆☆☆] 1/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Jopestpe (@jopestpe)
*
diff --git a/examples/models/models_tesseract_view.c b/examples/models/models_tesseract_view.c
index 1544873fb..9829d63e3 100644
--- a/examples/models/models_tesseract_view.c
+++ b/examples/models/models_tesseract_view.c
@@ -6,7 +6,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Timothy van der Valk (@arceryz) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shaders/resources/shaders/glsl330/fog.fs b/examples/shaders/resources/shaders/glsl330/fog.fs
index 67d0795ec..ac0132ff0 100644
--- a/examples/shaders/resources/shaders/glsl330/fog.fs
+++ b/examples/shaders/resources/shaders/glsl330/fog.fs
@@ -37,6 +37,7 @@ struct Light {
uniform Light lights[MAX_LIGHTS];
uniform vec4 ambient;
uniform vec3 viewPos;
+uniform vec4 fogColor;
uniform float fogDensity;
void main()
@@ -77,10 +78,6 @@ void main()
// Fog calculation
float dist = length(viewPos - fragPosition);
- // these could be parameters...
- const vec4 fogColor = vec4(0.5, 0.5, 0.5, 1.0);
- //const float fogDensity = 0.16;
-
// Exponential fog
float fogFactor = 1.0/exp((dist*fogDensity)*(dist*fogDensity));
diff --git a/examples/shaders/shaders_ascii_rendering.c b/examples/shaders/shaders_ascii_rendering.c
index d3302bf53..a4225abe3 100644
--- a/examples/shaders/shaders_ascii_rendering.c
+++ b/examples/shaders/shaders_ascii_rendering.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
-* Example originally created with raylib 5.5, last time updated with raylib 5.6
+* Example originally created with raylib 5.5, last time updated with raylib 6.0
*
* Example contributed by Maicon Santana (@maiconpintoabreu) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shaders/shaders_color_correction.c b/examples/shaders/shaders_color_correction.c
index 826baecc7..8a78066f1 100644
--- a/examples/shaders/shaders_color_correction.c
+++ b/examples/shaders/shaders_color_correction.c
@@ -7,7 +7,7 @@
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
*
-* Example originally created with raylib 5.6, last time updated with raylib 5.6
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Jordi Santonja (@JordSant) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shaders/shaders_depth_rendering.c b/examples/shaders/shaders_depth_rendering.c
index 866135020..0bec4eb35 100644
--- a/examples/shaders/shaders_depth_rendering.c
+++ b/examples/shaders/shaders_depth_rendering.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★★☆] 3/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Luís Almeida (@luis605) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shaders/shaders_fog_rendering.c b/examples/shaders/shaders_fog_rendering.c
index bc0e54ceb..a1044312d 100644
--- a/examples/shaders/shaders_fog_rendering.c
+++ b/examples/shaders/shaders_fog_rendering.c
@@ -72,8 +72,13 @@ int main(void)
shader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos");
// Ambient light level
+ Vector4 ambient = (Vector4){ 0.2f, 0.2f, 0.2f, 1.0f };
int ambientLoc = GetShaderLocation(shader, "ambient");
- SetShaderValue(shader, ambientLoc, (float[4]){ 0.2f, 0.2f, 0.2f, 1.0f }, SHADER_UNIFORM_VEC4);
+ SetShaderValue(shader, ambientLoc, &ambient, SHADER_UNIFORM_VEC4);
+
+ Vector4 fogColor = ColorNormalize(GRAY);
+ int fogColorLoc = GetShaderLocation(shader, "fogColor");
+ SetShaderValue(shader, fogColorLoc, &fogColor, SHADER_UNIFORM_VEC4);
float fogDensity = 0.15f;
int fogDensityLoc = GetShaderLocation(shader, "fogDensity");
diff --git a/examples/shaders/shaders_game_of_life.c b/examples/shaders/shaders_game_of_life.c
index 0ae91b756..251095e2b 100644
--- a/examples/shaders/shaders_game_of_life.c
+++ b/examples/shaders/shaders_game_of_life.c
@@ -7,7 +7,7 @@
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
*
-* Example originally created with raylib 5.6, last time updated with raylib 5.6
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Jordi Santonja (@JordSant) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shaders/shaders_mandelbrot_set.c b/examples/shaders/shaders_mandelbrot_set.c
index dc592b6e4..b5c8a8e94 100644
--- a/examples/shaders/shaders_mandelbrot_set.c
+++ b/examples/shaders/shaders_mandelbrot_set.c
@@ -9,7 +9,7 @@
*
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3)
*
-* Example originally created with raylib 5.6, last time updated with raylib 5.6
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Jordi Santonja (@JordSant)
* Based on previous work by Josh Colclough (@joshcol9232)
diff --git a/examples/shaders/shaders_normalmap_rendering.c b/examples/shaders/shaders_normalmap_rendering.c
index 07399a78e..6d39cc28e 100644
--- a/examples/shaders/shaders_normalmap_rendering.c
+++ b/examples/shaders/shaders_normalmap_rendering.c
@@ -7,7 +7,7 @@
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
*
-* Example originally created with raylib 5.6, last time updated with raylib 5.6
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Jeremy Montgomery (@Sir_Irk) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shapes/shapes_ball_physics.c b/examples/shapes/shapes_ball_physics.c
index b790c7e90..f01a7c8e1 100644
--- a/examples/shapes/shapes_ball_physics.c
+++ b/examples/shapes/shapes_ball_physics.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by David Buzatto (@davidbuzatto) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shapes/shapes_clock_of_clocks.c b/examples/shapes/shapes_clock_of_clocks.c
index d87ec6411..ad87411f9 100644
--- a/examples/shapes/shapes_clock_of_clocks.c
+++ b/examples/shapes/shapes_clock_of_clocks.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
-* Example originally created with raylib 5.5, last time updated with raylib 5.6-dev
+* Example originally created with raylib 5.5, last time updated with raylib 6.0
*
* Example contributed by JP Mortiboys (@themushroompirates) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shapes/shapes_lines_drawing.c b/examples/shapes/shapes_lines_drawing.c
index 76e81abb5..c3ea0fc7b 100644
--- a/examples/shapes/shapes_lines_drawing.c
+++ b/examples/shapes/shapes_lines_drawing.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★☆☆☆] 1/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6
+* Example originally created with raylib 6.0, last time updated with raylib 5.6
*
* Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shapes/shapes_math_angle_rotation.c b/examples/shapes/shapes_math_angle_rotation.c
index 63c9aaa91..bf7e84b86 100644
--- a/examples/shapes/shapes_math_angle_rotation.c
+++ b/examples/shapes/shapes_math_angle_rotation.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★☆☆☆] 1/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6
+* Example originally created with raylib 6.0, last time updated with raylib 5.6
*
* Example contributed by Kris (@krispy-snacc) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shapes/shapes_math_sine_cosine.c b/examples/shapes/shapes_math_sine_cosine.c
index c9964a9ff..7ffa1c217 100644
--- a/examples/shapes/shapes_math_sine_cosine.c
+++ b/examples/shapes/shapes_math_sine_cosine.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Jopestpe (@jopestpe) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shapes/shapes_penrose_tile.c b/examples/shapes/shapes_penrose_tile.c
index f94eae763..0221a10b3 100644
--- a/examples/shapes/shapes_penrose_tile.c
+++ b/examples/shapes/shapes_penrose_tile.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★★★] 4/4
*
-* Example originally created with raylib 5.5, last time updated with raylib 5.6-dev
+* Example originally created with raylib 5.5, last time updated with raylib 6.0
* Based on: https://processing.org/examples/penrosetile.html
*
* Example contributed by David Buzatto (@davidbuzatto) and reviewed by Ramon Santamaria (@raysan5)
diff --git a/examples/shapes/shapes_recursive_tree.c b/examples/shapes/shapes_recursive_tree.c
index f15758773..3977eecc6 100644
--- a/examples/shapes/shapes_recursive_tree.c
+++ b/examples/shapes/shapes_recursive_tree.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★★☆] 3/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Jopestpe (@jopestpe)
*
diff --git a/examples/shapes/shapes_rlgl_color_wheel.c b/examples/shapes/shapes_rlgl_color_wheel.c
index f02226a83..a03dcf2de 100644
--- a/examples/shapes/shapes_rlgl_color_wheel.c
+++ b/examples/shapes/shapes_rlgl_color_wheel.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★★☆] 3/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shapes/shapes_rlgl_triangle.c b/examples/shapes/shapes_rlgl_triangle.c
index 56cdc43bc..30920131c 100644
--- a/examples/shapes/shapes_rlgl_triangle.c
+++ b/examples/shapes/shapes_rlgl_triangle.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shapes/shapes_starfield_effect.c b/examples/shapes/shapes_starfield_effect.c
index 484f4fb78..f0d5d57e1 100644
--- a/examples/shapes/shapes_starfield_effect.c
+++ b/examples/shapes/shapes_starfield_effect.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
-* Example originally created with raylib 5.5, last time updated with raylib 5.6-dev
+* Example originally created with raylib 5.5, last time updated with raylib 6.0
*
* Example contributed by JP Mortiboys (@themushroompirates) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/shapes/shapes_triangle_strip.c b/examples/shapes/shapes_triangle_strip.c
index de712270c..aef0c0291 100644
--- a/examples/shapes/shapes_triangle_strip.c
+++ b/examples/shapes/shapes_triangle_strip.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Jopestpe (@jopestpe)
*
diff --git a/examples/text/text_inline_styling.c b/examples/text/text_inline_styling.c
index 8634ccc19..2d2b5e135 100644
--- a/examples/text/text_inline_styling.c
+++ b/examples/text/text_inline_styling.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★★☆] 3/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Wagner Barongello (@SultansOfCode) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/text/text_strings_management.c b/examples/text/text_strings_management.c
index db4540081..60f0941f3 100644
--- a/examples/text/text_strings_management.c
+++ b/examples/text/text_strings_management.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★★☆] 3/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by David Buzatto (@davidbuzatto) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/text/text_words_alignment.c b/examples/text/text_words_alignment.c
index 8017f33eb..f0ebc78a5 100644
--- a/examples/text/text_words_alignment.c
+++ b/examples/text/text_words_alignment.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★☆☆☆] 1/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by JP Mortiboys (@themushroompirates) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/examples/textures/textures_clipboard_image.c b/examples/textures/textures_clipboard_image.c
index aa955da2e..1e9ec0846 100644
--- a/examples/textures/textures_clipboard_image.c
+++ b/examples/textures/textures_clipboard_image.c
@@ -34,7 +34,7 @@ int main(void)
const int screenWidth = 800;
const int screenHeight = 450;
- InitWindow(screenWidth, screenHeight, "raylib [textures] example - clipboard_image");
+ InitWindow(screenWidth, screenHeight, "raylib [textures] example - clipboard image");
TextureCollection collection[MAX_TEXTURE_COLLECTION] = { 0 };
int currentCollectionIndex = 0;
diff --git a/examples/textures/textures_sprite_stacking.c b/examples/textures/textures_sprite_stacking.c
index b20474711..671e82461 100644
--- a/examples/textures/textures_sprite_stacking.c
+++ b/examples/textures/textures_sprite_stacking.c
@@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
-* Example originally created with raylib 5.6-dev, last time updated with raylib 6.0
+* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5)
*
diff --git a/projects/4coder/Makefile b/projects/4coder/Makefile
index 1b598eed5..ec0977aaf 100644
--- a/projects/4coder/Makefile
+++ b/projects/4coder/Makefile
@@ -2,7 +2,7 @@
#
# raylib makefile for Desktop platforms, Raspberry Pi, Android and HTML5
#
-# Copyright (c) 2013-2024 Ramon Santamaria (@raysan5)
+# Copyright (c) 2013-2026 Ramon Santamaria (@raysan5)
#
# This software is provided "as-is", without any express or implied warranty. In no event
# will the authors be held liable for any damages arising from the use of this software.
@@ -117,8 +117,8 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
EMSDK_PATH ?= C:/raylib/emsdk
EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten
CLANG_PATH = $(EMSDK_PATH)/upstream/bin
- PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit
- NODE_PATH = $(EMSDK_PATH)/node/20.18.0_64bit/bin
+ PYTHON_PATH = $(EMSDK_PATH)/python/3.13.3_64bit
+ NODE_PATH = $(EMSDK_PATH)/node/22.16.0_64bit/bin
export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH);C:\raylib\MinGW\bin:$$(PATH)
endif
@@ -163,7 +163,7 @@ ifeq ($(PLATFORM),PLATFORM_RPI)
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
# HTML5 emscripten compiler
- # WARNING: To compile to HTML5, code must be redesigned
+ # WARNING: To compile to HTML5, code must be redesigned
# to use emscripten.h and emscripten_set_main_loop()
CC = emcc
endif
@@ -297,12 +297,12 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
# Libraries for Debian GNU/Linux desktop compiling
# NOTE: Required packages: libegl1-mesa-dev
LDLIBS = -lraylib -lGL -lm -lpthread -ldl -lrt
-
+
# On X11 requires also below libraries
LDLIBS += -lX11
# NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them
#LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
-
+
# On Wayland windowing system, additional libraries requires
ifeq ($(USE_WAYLAND_DISPLAY),TRUE)
LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon
@@ -354,7 +354,7 @@ OBJS = main.c
# For Android platform we call a custom Makefile.Android
ifeq ($(PLATFORM),PLATFORM_ANDROID)
- MAKEFILE_PARAMS = -f Makefile.Android
+ MAKEFILE_PARAMS = -f Makefile.Android
export PROJECT_NAME
export SRC_DIR
else
diff --git a/projects/VS2022/examples/audio_stream_callback.vcxproj b/projects/VS2022/examples/audio_stream_callback.vcxproj
new file mode 100644
index 000000000..70d3daae5
--- /dev/null
+++ b/projects/VS2022/examples/audio_stream_callback.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}
+ Win32Proj
+ audio_stream_callback
+ 10.0
+ audio_stream_callback
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\audio
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\audio
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\audio
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\audio
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\audio
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\audio
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\audio
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\audio
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\audio
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\audio
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\audio
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\audio
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/examples/shaders_cel_shading.vcxproj b/projects/VS2022/examples/shaders_cel_shading.vcxproj
new file mode 100644
index 000000000..c37636be1
--- /dev/null
+++ b/projects/VS2022/examples/shaders_cel_shading.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}
+ Win32Proj
+ shaders_cel_shading
+ 10.0
+ shaders_cel_shading
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/examples/textures_clipboard_image.vcxproj b/projects/VS2022/examples/textures_clipboard_image.vcxproj
new file mode 100644
index 000000000..ed2c667a2
--- /dev/null
+++ b/projects/VS2022/examples/textures_clipboard_image.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}
+ Win32Proj
+ textures_clipboard_image
+ 10.0
+ textures_clipboard_image
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/examples/textures_magnifying_glass.vcxproj b/projects/VS2022/examples/textures_magnifying_glass.vcxproj
new file mode 100644
index 000000000..3abbd2d94
--- /dev/null
+++ b/projects/VS2022/examples/textures_magnifying_glass.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}
+ Win32Proj
+ textures_magnifying_glass
+ 10.0
+ textures_magnifying_glass
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\textures
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln
index 51782892c..c852d7855 100644
--- a/projects/VS2022/raylib.sln
+++ b/projects/VS2022/raylib.sln
@@ -437,6 +437,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_window_web", "examples
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_animation_timing", "examples\models_animation_timing.vcxproj", "{89D5A0E9-683C-465C-BF85-A880865175C8}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "textures_magnifying_glass", "examples\textures_magnifying_glass.vcxproj", "{099441CA-5A99-4E50-AA2E-EB397EF0A50A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "textures_clipboard_image", "examples\textures_clipboard_image.vcxproj", "{6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_cel_shading", "examples\shaders_cel_shading.vcxproj", "{D5556782-5113-403C-8E7A-2417B8CD0CC6}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "audio_stream_callback", "examples\audio_stream_callback.vcxproj", "{F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug.DLL|ARM64 = Debug.DLL|ARM64
@@ -5469,6 +5477,102 @@ Global
{89D5A0E9-683C-465C-BF85-A880865175C8}.Release|x64.Build.0 = Release|x64
{89D5A0E9-683C-465C-BF85-A880865175C8}.Release|x86.ActiveCfg = Release|Win32
{89D5A0E9-683C-465C-BF85-A880865175C8}.Release|x86.Build.0 = Release|Win32
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Debug|ARM64.Build.0 = Debug|ARM64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Debug|x64.ActiveCfg = Debug|x64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Debug|x64.Build.0 = Debug|x64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Debug|x86.ActiveCfg = Debug|Win32
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Debug|x86.Build.0 = Debug|Win32
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Release|ARM64.ActiveCfg = Release|ARM64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Release|ARM64.Build.0 = Release|ARM64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Release|x64.ActiveCfg = Release|x64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Release|x64.Build.0 = Release|x64
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Release|x86.ActiveCfg = Release|Win32
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A}.Release|x86.Build.0 = Release|Win32
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Debug|ARM64.Build.0 = Debug|ARM64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Debug|x64.ActiveCfg = Debug|x64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Debug|x64.Build.0 = Debug|x64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Debug|x86.ActiveCfg = Debug|Win32
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Debug|x86.Build.0 = Debug|Win32
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Release|ARM64.ActiveCfg = Release|ARM64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Release|ARM64.Build.0 = Release|ARM64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Release|x64.ActiveCfg = Release|x64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Release|x64.Build.0 = Release|x64
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Release|x86.ActiveCfg = Release|Win32
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654}.Release|x86.Build.0 = Release|Win32
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Debug|ARM64.Build.0 = Debug|ARM64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Debug|x64.ActiveCfg = Debug|x64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Debug|x64.Build.0 = Debug|x64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Debug|x86.ActiveCfg = Debug|Win32
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Debug|x86.Build.0 = Debug|Win32
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Release|ARM64.ActiveCfg = Release|ARM64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Release|ARM64.Build.0 = Release|ARM64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Release|x64.ActiveCfg = Release|x64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Release|x64.Build.0 = Release|x64
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Release|x86.ActiveCfg = Release|Win32
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6}.Release|x86.Build.0 = Release|Win32
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Debug|ARM64.Build.0 = Debug|ARM64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Debug|x64.ActiveCfg = Debug|x64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Debug|x64.Build.0 = Debug|x64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Debug|x86.ActiveCfg = Debug|Win32
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Debug|x86.Build.0 = Debug|Win32
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Release|ARM64.ActiveCfg = Release|ARM64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Release|ARM64.Build.0 = Release|ARM64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Release|x64.ActiveCfg = Release|x64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Release|x64.Build.0 = Release|x64
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Release|x86.ActiveCfg = Release|Win32
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -5631,7 +5735,7 @@ Global
{C54703BF-D68A-480D-BE27-49B62E45D582} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9}
{9CD8BCAD-F212-4BCC-BA98-899743CE3279} = {CC132A4D-D081-4C26-BFB9-AB11984054F8}
{0981CA28-E4A5-4DF1-987F-A41D09131EFC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
- {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {CC132A4D-D081-4C26-BFB9-AB11984054F8}
{6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9}
{6777EC3C-077C-42FC-B4AD-B799CE55CCE4} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A}
{A61DAD9C-271C-4E95-81AA-DB4CD58564D4} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
@@ -5689,6 +5793,10 @@ Global
{BB9C957D-34F1-46AE-B64A-9E0499C1746D} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C}
{4E7157E0-6CDB-47AE-A19A-FEC3876FA8A3} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{89D5A0E9-683C-465C-BF85-A880865175C8} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C}
+ {099441CA-5A99-4E50-AA2E-EB397EF0A50A} = {DA049009-21FF-4AC0-84E4-830DD1BCD0CE}
+ {6E6F4A8A-675A-42F2-8AD1-4BF2757C2654} = {DA049009-21FF-4AC0-84E4-830DD1BCD0CE}
+ {D5556782-5113-403C-8E7A-2417B8CD0CC6} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9}
+ {F94B1675-03AE-4EB0-BC0E-071F3C33B9ED} = {CC132A4D-D081-4C26-BFB9-AB11984054F8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29}
diff --git a/projects/VS2022/raylib/raylib.vcxproj b/projects/VS2022/raylib/raylib.vcxproj
index 8cc3fae7a..cf686e498 100644
--- a/projects/VS2022/raylib/raylib.vcxproj
+++ b/projects/VS2022/raylib/raylib.vcxproj
@@ -585,6 +585,9 @@
+
+
+
diff --git a/projects/VS2022/raylib/raylib.vcxproj.filters b/projects/VS2022/raylib/raylib.vcxproj.filters
index 75cc28a7e..444686eab 100644
--- a/projects/VS2022/raylib/raylib.vcxproj.filters
+++ b/projects/VS2022/raylib/raylib.vcxproj.filters
@@ -102,7 +102,13 @@
Header Files
-
+
+ Header Files
+
+
+ Header Files
+
+
Header Files
diff --git a/projects/VSCode/Makefile b/projects/VSCode/Makefile
index 219673670..4f6d03b31 100644
--- a/projects/VSCode/Makefile
+++ b/projects/VSCode/Makefile
@@ -120,8 +120,8 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
EMSDK_PATH ?= C:/raylib/emsdk
EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten
CLANG_PATH = $(EMSDK_PATH)/upstream/bin
- PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit
- NODE_PATH = $(EMSDK_PATH)/node/20.18.0_64bit/bin
+ PYTHON_PATH = $(EMSDK_PATH)/python/3.13.3_64bit
+ NODE_PATH = $(EMSDK_PATH)/node/22.16.0_64bit/bin
export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH):$$(PATH)
endif
diff --git a/src/Makefile b/src/Makefile
index e53514701..8f13b4355 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -122,7 +122,7 @@ USE_EXTERNAL_GLFW ?= FALSE
GLFW_LINUX_ENABLE_WAYLAND ?= FALSE
GLFW_LINUX_ENABLE_X11 ?= TRUE
-# Enable support for X11 by default on Linux when using GLFW
+# Enable support for X11 by default on Linux when using RGFW
# NOTE: Wayland is disabled by default, only enable if you are sure
RGFW_LINUX_ENABLE_WAYLAND ?= FALSE
RGFW_LINUX_ENABLE_X11 ?= TRUE
@@ -198,8 +198,8 @@ ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_R
EMSDK_PATH ?= C:/raylib/emsdk
EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten
CLANG_PATH := $(EMSDK_PATH)/upstream/bin
- PYTHON_PATH := $(EMSDK_PATH)/python/3.9.2-nuget_64bit
- NODE_PATH := $(EMSDK_PATH)/node/20.18.0_64bit/bin
+ PYTHON_PATH := $(EMSDK_PATH)/python/3.13.3_64bit
+ NODE_PATH := $(EMSDK_PATH)/node/22.16.0_64bit/bin
export PATH := $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH);C:/raylib/MinGW/bin;$(PATH)
endif
endif
@@ -246,7 +246,7 @@ endif
# NOTE: By default use OpenGL 3.3 on desktop platforms
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
GRAPHICS ?= GRAPHICS_API_OPENGL_33
- #GRAPHICS = GRAPHICS_API_OPENGL_11_SOFTWARE # Uncomment to use software rendering
+ #GRAPHICS = GRAPHICS_API_OPENGL_SOFTWARE # Uncomment to use software rendering
#GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1
#GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1
#GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3
@@ -257,7 +257,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL)
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW)
GRAPHICS ?= GRAPHICS_API_OPENGL_33
- #GRAPHICS = GRAPHICS_API_OPENGL_11_SOFTWARE # Uncomment to use software rendering
+ #GRAPHICS = GRAPHICS_API_OPENGL_SOFTWARE # Uncomment to use software rendering
#GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1
#GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1
#GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3
@@ -265,7 +265,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW)
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32)
GRAPHICS ?= GRAPHICS_API_OPENGL_33
- #GRAPHICS = GRAPHICS_API_OPENGL_11_SOFTWARE # Uncomment to use software rendering
+ #GRAPHICS = GRAPHICS_API_OPENGL_SOFTWARE # Uncomment to use software rendering
#GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1
#GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1
#GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3
@@ -273,7 +273,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32)
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
GRAPHICS ?= GRAPHICS_API_OPENGL_ES2
- #GRAPHICS = GRAPHICS_API_OPENGL_11_SOFTWARE # Uncomment to use software rendering
+ #GRAPHICS = GRAPHICS_API_OPENGL_SOFTWARE # Uncomment to use software rendering
endif
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
# On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0
@@ -709,7 +709,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32)
LDLIBS = -lgdi32 -lwinmm -lshcore
- ifneq ($(GRAPHICS),GRAPHICS_API_OPENGL_11_SOFTWARE)
+ ifneq ($(GRAPHICS),GRAPHICS_API_OPENGL_SOFTWARE)
LDLIBS += -lopengl32
endif
endif
@@ -959,6 +959,7 @@ ifeq ($(ROOT),root)
endif
rm --force --interactive --verbose $(RAYLIB_H_INSTALL_PATH)/raylib.h
rm --force --interactive --verbose $(RAYLIB_H_INSTALL_PATH)/raymath.h
+ rm --force --interactive --verbose $(RAYLIB_H_INSTALL_PATH)/rcamera.h
rm --force --interactive --verbose $(RAYLIB_H_INSTALL_PATH)/rlgl.h
@echo "raylib development files removed!"
else
diff --git a/src/external/rlsw.h b/src/external/rlsw.h
index 46cba4c74..8472b03e9 100644
--- a/src/external/rlsw.h
+++ b/src/external/rlsw.h
@@ -1,6 +1,6 @@
/**********************************************************************************************
*
-* rlsw v1.0 - An OpenGL 1.1-style software renderer implementation
+* rlsw v1.5 - An OpenGL 1.1-style software renderer implementation
*
* DESCRIPTION:
* rlsw is a custom OpenGL 1.1-style implementation on software, intended to provide all
@@ -51,10 +51,9 @@
* rlsw capabilities could be customized defining some internal
* values before library inclusion (default values listed):
*
-* #define SW_GL_FRAMEBUFFER_COPY_BGRA true
-* #define SW_GL_BINDING_COPY_TEXTURE true
-* #define SW_COLOR_BUFFER_BITS 24
-* #define SW_DEPTH_BUFFER_BITS 16
+* #define SW_FRAMEBUFFER_OUTPUT_BGRA true
+* #define SW_FRAMEBUFFER_COLOR_TYPE R8G8B8A8
+* #define SW_FRAMEBUFFER_DEPTH_TYPE D32
* #define SW_MAX_PROJECTION_STACK_SIZE 2
* #define SW_MAX_MODELVIEW_STACK_SIZE 8
* #define SW_MAX_TEXTURE_STACK_SIZE 2
@@ -88,6 +87,8 @@
#ifndef RLSW_H
#define RLSW_H
+#define RLSW_VERSION "1.5"
+
#include
#include
@@ -102,6 +103,9 @@
#ifndef SW_MALLOC
#define SW_MALLOC(sz) malloc(sz)
#endif
+#ifndef SW_CALLOC
+ #define SW_CALLOC(n,sz) calloc(n,sz)
+#endif
#ifndef SW_REALLOC
#define SW_REALLOC(ptr, newSz) realloc(ptr, newSz)
#endif
@@ -117,16 +121,16 @@
#endif
#endif
-#ifndef SW_GL_FRAMEBUFFER_COPY_BGRA
- #define SW_GL_FRAMEBUFFER_COPY_BGRA true
+#ifndef SW_FRAMEBUFFER_OUTPUT_BGRA
+ #define SW_FRAMEBUFFER_OUTPUT_BGRA true
#endif
-#ifndef SW_COLOR_BUFFER_BITS
- #define SW_COLOR_BUFFER_BITS 32 //< 32 (rgba), 16 (rgb packed) or 8 (rgb packed)
+#ifndef SW_FRAMEBUFFER_COLOR_TYPE
+ #define SW_FRAMEBUFFER_COLOR_TYPE R8G8B8A8 // Or R5G6B5, R3G3B2, etc; see `sw_pixelformat_t`
#endif
-#ifndef SW_DEPTH_BUFFER_BITS
- #define SW_DEPTH_BUFFER_BITS 16 //< 32, 24 or 16
+#ifndef SW_FRAMEBUFFER_DEPTH_TYPE
+ #define SW_FRAMEBUFFER_DEPTH_TYPE D32 // Or D16, D8
#endif
#ifndef SW_MAX_PROJECTION_STACK_SIZE
@@ -141,21 +145,23 @@
#define SW_MAX_TEXTURE_STACK_SIZE 2
#endif
+#ifndef SW_MAX_FRAMEBUFFERS
+ #define SW_MAX_FRAMEBUFFERS 8
+#endif
+
#ifndef SW_MAX_TEXTURES
#define SW_MAX_TEXTURES 128
#endif
-// Under normal circumstances, clipping a polygon can add at most one vertex per clipping plane
-// Considering the largest polygon involved is a quadrilateral (4 vertices),
-// and that clipping occurs against both the frustum (6 planes) and the scissors (4 planes),
-// the maximum number of vertices after clipping is:
-// 4 (original vertices) + 6 (frustum planes) + 4 (scissors planes) = 14
-#ifndef SW_MAX_CLIPPED_POLYGON_VERTICES
- #define SW_MAX_CLIPPED_POLYGON_VERTICES 14
-#endif
-
-#ifndef SW_CLIP_EPSILON
- #define SW_CLIP_EPSILON 1e-4f
+// Enables the use of a lookup table for uint8_t to float conversion
+// Requires an additional 1KB of global memory
+// Disabled when SIMD intrinsics are enabled
+#ifndef SW_USE_COLOR_LUT
+ #if RLSW_USE_SIMD_INTRINSICS
+ #define SW_USE_COLOR_LUT false
+ #else
+ #define SW_USE_COLOR_LUT true
+ #endif
#endif
//----------------------------------------------------------------------------------
@@ -294,6 +300,7 @@ typedef double GLclampd;
#define GL_LUMINANCE_ALPHA 0x190A
#define GL_RGB 0x1907
#define GL_RGBA 0x1908
+#define GL_DEPTH_COMPONENT 0x1902
#define GL_BYTE 0x1400
#define GL_UNSIGNED_BYTE 0x1401
@@ -302,6 +309,70 @@ typedef double GLclampd;
#define GL_INT 0x1404
#define GL_UNSIGNED_INT 0x1405
#define GL_FLOAT 0x1406
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+
+// OpenGL internal formats (not all are supported; see SWinternalformat)
+#define GL_ALPHA4 0x803B
+#define GL_ALPHA8 0x803C
+#define GL_ALPHA12 0x803D
+#define GL_ALPHA16 0x803E
+#define GL_LUMINANCE4 0x803F
+#define GL_LUMINANCE8 0x8040
+#define GL_LUMINANCE12 0x8041
+#define GL_LUMINANCE16 0x8042
+#define GL_LUMINANCE4_ALPHA4 0x8043
+#define GL_LUMINANCE6_ALPHA2 0x8044
+#define GL_LUMINANCE8_ALPHA8 0x8045
+#define GL_LUMINANCE12_ALPHA4 0x8046
+#define GL_LUMINANCE12_ALPHA12 0x8047
+#define GL_LUMINANCE16_ALPHA16 0x8048
+#define GL_INTENSITY 0x8049
+#define GL_INTENSITY4 0x804A
+#define GL_INTENSITY8 0x804B
+#define GL_INTENSITY12 0x804C
+#define GL_INTENSITY16 0x804D
+#define GL_R3_G3_B2 0x2A10
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB8 0x8051
+#define GL_RGB10 0x8052
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGBA2 0x8055
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGBA8 0x8058
+#define GL_RGB10_A2 0x8059
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+
+// OpenGL internal formats extension
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_R16F 0x822D
+#define GL_RGB16F 0x881B
+#define GL_RGBA16F 0x881A
+#define GL_R32F 0x822E
+#define GL_RGB32F 0x8815
+#define GL_RGBA32F 0x8814
+
+// OpenGL GL_EXT_framebuffer_object
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20 // WARNING: Not implemented (defined for RLGL)
// OpenGL Definitions NOT USED
#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
@@ -320,13 +391,21 @@ typedef double GLclampd;
#define GL_NOTEQUAL 0x0205
#define GL_GEQUAL 0x0206
#define GL_ALWAYS 0x0207
+#define GL_RENDERBUFFER 0x8D41
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
//----------------------------------------------------------------------------------
// OpenGL Bindings to rlsw
//----------------------------------------------------------------------------------
-#define glReadPixels(x, y, w, h, f, t, p) swCopyFramebuffer((x), (y), (w), (h), (f), (t), (p))
+#define glReadPixels(x, y, w, h, f, t, p) swReadPixels((x), (y), (w), (h), (f), (t), (p))
#define glEnable(state) swEnable((state))
#define glDisable(state) swDisable((state))
+#define glGetIntegerv(pname, params) swGetIntegerv((pname), (params))
#define glGetFloatv(pname, params) swGetFloatv((pname), (params))
#define glGetString(pname) swGetString((pname))
#define glGetError() swGetError()
@@ -381,23 +460,36 @@ typedef double GLclampd;
#define glDrawElements(m,c,t,i) swDrawElements((m),(c),(t),(i))
#define glGenTextures(c, v) swGenTextures((c), (v))
#define glDeleteTextures(c, v) swDeleteTextures((c), (v))
-#define glTexImage2D(tr, l, if, w, h, b, f, t, p) swTexImage2D((w), (h), (f), (t), (p))
-#define glTexParameteri(tr, pname, param) swTexParameteri((pname), (param))
#define glBindTexture(tr, id) swBindTexture((id))
+#define glTexImage2D(tr, l, if, w, h, b, f, t, p) swTexImage2D((w), (h), (f), (t), (p))
+#define glTexSubImage2D(tr, l, x, y, w, h, f, t, p) swTexSubImage2D((x), (y), (w), (h), (f), (t), (p));
+#define glTexParameteri(tr, pname, param) swTexParameteri((pname), (param))
+
+// OpenGL GL_EXT_framebuffer_object
+#define glGenFramebuffers(c, v) swGenFramebuffers((c), (v))
+#define glDeleteFramebuffers(c, v) swDeleteFramebuffers((c), (v))
+#define glBindFramebuffer(tr, id) swBindFramebuffer((id))
+#define glFramebufferTexture2D(tr, a, t, tex, ml) swFramebufferTexture2D((a), (tex))
+#define glFramebufferRenderbuffer(tr, a, rbtr, rb) swFramebufferTexture2D((a), (rb))
+#define glCheckFramebufferStatus(tr) swCheckFramebufferStatus()
+#define glGetFramebufferAttachmentParameteriv(tr, a, p, v) swGetFramebufferAttachmentParameteriv((a), (p), (v))
+#define glGenRenderbuffers(c, v) swGenTextures((c), (v))
+#define glDeleteRenderbuffers(c, v) swDeleteTextures((c), (v))
+#define glBindRenderbuffer(tr, rb) swBindTexture((rb))
+#define glRenderbufferStorage(tr, f, w, h) swTexStorage2D((w), (h), (f))
// OpenGL functions NOT IMPLEMENTED by rlsw
-#define glDepthMask(X) ((void)(X))
-#define glColorMask(X,Y,Z,W) ((void)(X),(void)(Y),(void)(Z),(void)(W))
-#define glPixelStorei(X,Y) ((void)(X),(void)(Y))
-#define glHint(X,Y) ((void)(X),(void)(Y))
-#define glShadeModel(X) ((void)(X))
-#define glFrontFace(X) ((void)(X))
-#define glDepthFunc(X) ((void)(X))
-#define glTexSubImage2D(X,Y,Z,W,A,B,C,D,E) ((void)(X),(void)(Y),(void)(Z),(void)(W),(void)(A),(void)(B),(void)(C),(void)(D),(void)(E))
-#define glGetTexImage(X,Y,Z,W,A) ((void)(X),(void)(Y),(void)(Z),(void)(W),(void)(A))
-#define glNormal3f(X,Y,Z) ((void)(X),(void)(Y),(void)(Z))
-#define glNormal3fv(X) ((void)(X))
-#define glNormalPointer(X,Y,Z) ((void)(X),(void)(Y),(void)(Z))
+#define glDepthMask(X) ((void)(X))
+#define glColorMask(X,Y,Z,W) ((void)(X),(void)(Y),(void)(Z),(void)(W))
+#define glPixelStorei(X,Y) ((void)(X),(void)(Y))
+#define glHint(X,Y) ((void)(X),(void)(Y))
+#define glShadeModel(X) ((void)(X))
+#define glFrontFace(X) ((void)(X))
+#define glDepthFunc(X) ((void)(X))
+#define glGetTexImage(X,Y,Z,W,A) ((void)(X),(void)(Y),(void)(Z),(void)(W),(void)(A))
+#define glNormal3f(X,Y,Z) ((void)(X),(void)(Y),(void)(Z))
+#define glNormal3fv(X) ((void)(X))
+#define glNormalPointer(X,Y,Z) ((void)(X),(void)(Y),(void)(Z))
//----------------------------------------------------------------------------------
// Types and Structures Definition
@@ -427,7 +519,8 @@ typedef enum {
SW_PROJECTION_STACK_DEPTH = GL_PROJECTION_STACK_DEPTH,
SW_TEXTURE_MATRIX = GL_TEXTURE_MATRIX,
SW_TEXTURE_STACK_DEPTH = GL_TEXTURE_STACK_DEPTH,
- SW_VIEWPORT = GL_VIEWPORT
+ SW_VIEWPORT = GL_VIEWPORT,
+ SW_DRAW_FRAMEBUFFER_BINDING = GL_DRAW_FRAMEBUFFER_BINDING,
} SWget;
typedef enum {
@@ -448,6 +541,7 @@ typedef enum {
} SWarray;
typedef enum {
+ SW_DRAW_INVALID = -1,
SW_POINTS = GL_POINTS,
SW_LINES = GL_LINES,
SW_TRIANGLES = GL_TRIANGLES,
@@ -484,21 +578,47 @@ typedef enum {
SW_LUMINANCE_ALPHA = GL_LUMINANCE_ALPHA,
SW_RGB = GL_RGB,
SW_RGBA = GL_RGBA,
+ SW_DEPTH_COMPONENT = GL_DEPTH_COMPONENT,
} SWformat;
typedef enum {
SW_UNSIGNED_BYTE = GL_UNSIGNED_BYTE,
+ SW_UNSIGNED_BYTE_3_3_2 = GL_UNSIGNED_BYTE_3_3_2,
SW_BYTE = GL_BYTE,
SW_UNSIGNED_SHORT = GL_UNSIGNED_SHORT,
+ SW_UNSIGNED_SHORT_5_6_5 = GL_UNSIGNED_SHORT_5_6_5,
+ SW_UNSIGNED_SHORT_4_4_4_4 = GL_UNSIGNED_SHORT_4_4_4_4,
+ SW_UNSIGNED_SHORT_5_5_5_1 = GL_UNSIGNED_SHORT_5_5_5_1,
SW_SHORT = GL_SHORT,
SW_UNSIGNED_INT = GL_UNSIGNED_INT,
SW_INT = GL_INT,
SW_FLOAT = GL_FLOAT
} SWtype;
+typedef enum {
+ SW_LUMINANCE8 = GL_LUMINANCE8,
+ SW_LUMINANCE8_ALPHA8 = GL_LUMINANCE8_ALPHA8,
+ SW_R3_G3_B2 = GL_R3_G3_B2,
+ SW_RGB8 = GL_RGB8,
+ SW_RGBA4 = GL_RGBA4,
+ SW_RGB5_A1 = GL_RGB5_A1,
+ SW_RGBA8 = GL_RGBA8,
+ SW_R16F = GL_R16F,
+ SW_RGB16F = GL_RGB16F,
+ SW_RGBA16F = GL_RGBA16F,
+ SW_R32F = GL_R32F,
+ SW_RGB32F = GL_RGB32F,
+ SW_RGBA32F = GL_RGBA32F,
+ SW_DEPTH_COMPONENT16 = GL_DEPTH_COMPONENT16,
+ SW_DEPTH_COMPONENT24 = GL_DEPTH_COMPONENT24,
+ SW_DEPTH_COMPONENT32 = GL_DEPTH_COMPONENT32,
+ SW_DEPTH_COMPONENT32F = GL_DEPTH_COMPONENT32F,
+ //SW_R5_G6_B5, // Not defined by OpenGL
+} SWinternalformat;
+
typedef enum {
SW_NEAREST = GL_NEAREST,
- SW_LINEAR = GL_LINEAR
+ SW_LINEAR = GL_LINEAR
} SWfilter;
typedef enum {
@@ -513,6 +633,23 @@ typedef enum {
SW_TEXTURE_WRAP_T = GL_TEXTURE_WRAP_T
} SWtexparam;
+typedef enum {
+ SW_COLOR_ATTACHMENT = GL_COLOR_ATTACHMENT0,
+ SW_DEPTH_ATTACHMENT = GL_DEPTH_ATTACHMENT,
+} SWattachment;
+
+typedef enum {
+ SW_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
+ SW_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
+} SWattachget;
+
+typedef enum {
+ SW_FRAMEBUFFER_COMPLETE = GL_FRAMEBUFFER_COMPLETE,
+ SW_FRAMEBUFFER_INCOMPLETE_ATTACHMENT = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ SW_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
+ SW_FRAMEBUFFER_INCOMPLETE_DIMENSIONS = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
+} SWfbstatus;
+
typedef enum {
SW_NO_ERROR = GL_NO_ERROR,
SW_INVALID_ENUM = GL_INVALID_ENUM,
@@ -520,6 +657,7 @@ typedef enum {
SW_STACK_OVERFLOW = GL_STACK_OVERFLOW,
SW_STACK_UNDERFLOW = GL_STACK_UNDERFLOW,
SW_INVALID_OPERATION = GL_INVALID_OPERATION,
+ SW_OUT_OF_MEMORY = GL_OUT_OF_MEMORY,
} SWerrcode;
//------------------------------------------------------------------------------------
@@ -528,9 +666,10 @@ typedef enum {
SWAPI bool swInit(int w, int h);
SWAPI void swClose(void);
-SWAPI bool swResizeFramebuffer(int w, int h);
-SWAPI void swCopyFramebuffer(int x, int y, int w, int h, SWformat format, SWtype type, void *pixels);
-SWAPI void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, SWformat format, SWtype type, void *pixels);
+SWAPI bool swResize(int w, int h);
+SWAPI void swReadPixels(int x, int y, int w, int h, SWformat format, SWtype type, void *pixels);
+SWAPI void swBlitPixels(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, SWformat format, SWtype type, void *pixels);
+SWAPI void *swGetColorBuffer(int *width, int *height); // Restored for ESP-IDF compatibility
SWAPI void swEnable(SWstate state);
SWAPI void swDisable(SWstate state);
@@ -595,10 +734,17 @@ SWAPI void swDrawElements(SWdraw mode, int count, int type, const void *indices)
SWAPI void swGenTextures(int count, uint32_t *textures);
SWAPI void swDeleteTextures(int count, uint32_t *textures);
-
-SWAPI void swTexImage2D(int width, int height, SWformat format, SWtype type, const void *data);
-SWAPI void swTexParameteri(int param, int value);
SWAPI void swBindTexture(uint32_t id);
+SWAPI void swTexImage2D(int width, int height, SWformat format, SWtype type, const void *data);
+SWAPI void swTexSubImage2D(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+SWAPI void swTexParameteri(int param, int value);
+
+SWAPI void swGenFramebuffers(int count, uint32_t *framebuffers);
+SWAPI void swDeleteFramebuffers(int count, uint32_t *framebuffers);
+SWAPI void swBindFramebuffer(uint32_t id);
+SWAPI void swFramebufferTexture2D(SWattachment attach, uint32_t texture);
+SWAPI SWfbstatus swCheckFramebufferStatus(void);
+SWAPI void swGetFramebufferAttachmentParameteriv(SWattachment attachment, SWattachget property, int *v);
#endif // RLSW_H
@@ -607,9 +753,10 @@ SWAPI void swBindTexture(uint32_t id);
* RLSW IMPLEMENTATION
*
************************************************************************************/
-#define RLSW_IMPLEMENTATION
#if defined(RLSW_IMPLEMENTATION)
+#undef RLSW_IMPLEMENTATION // Undef to allow template expanding without implementation redefinition
+
#include // Required for: malloc(), free()
#include // Required for: NULL, size_t, uint8_t, uint16_t, uint32_t...
#include // Required for: sinf(), cosf(), floorf(), fabsf(), sqrtf(), roundf()
@@ -711,80 +858,32 @@ SWAPI void swBindTexture(uint32_t id);
#define SW_DEG2RAD (SW_PI/180.0f)
#define SW_RAD2DEG (180.0f/SW_PI)
-#define SW_COLOR_PIXEL_SIZE (SW_COLOR_BUFFER_BITS >> 3)
-#define SW_DEPTH_PIXEL_SIZE (SW_DEPTH_BUFFER_BITS >> 3)
-#define SW_PIXEL_SIZE (SW_COLOR_PIXEL_SIZE + SW_DEPTH_PIXEL_SIZE)
+// When clipping a convex polygon against a plane, at most one vertex is added.
+// Starting from a quadrilateral (4 vertices), clipped sequentially against
+// the frustum (6 planes) then the scissor rectangle (4 planes):
+// 4 + 6 + 4 = 14 vertices maximum.
+#define SW_MAX_CLIPPED_POLYGON_VERTICES 14
+#define SW_CLIP_EPSILON 1e-4f
-#if (SW_PIXEL_SIZE <= 4)
- #define SW_PIXEL_ALIGNMENT 4
-#else // if (SW_PIXEL_SIZE <= 8)
- #define SW_PIXEL_ALIGNMENT 8
-#endif
+#define SW_HANDLE_NULL 0u
+#define SW_POOL_SLOT_LIVE 0x80u // bit7 of the generation byte
+#define SW_POOL_SLOT_VER_MASK 0x7Fu // bits6:0 = anti-ABA counter
-#if (SW_COLOR_BUFFER_BITS == 8)
- #define SW_COLOR_TYPE uint8_t
- #define SW_COLOR_IS_PACKED 1
- #define SW_COLOR_PACK_COMP 1
- #define SW_PACK_COLOR(r,g,b) ((((uint8_t)((r)*7+0.5f))&0x07)<<5 | (((uint8_t)((g)*7+0.5f))&0x07)<<2 | ((uint8_t)((b)*3+0.5f))&0x03)
- #define SW_UNPACK_R(p) (((p)>>5)&0x07)
- #define SW_UNPACK_G(p) (((p)>>2)&0x07)
- #define SW_UNPACK_B(p) ((p)&0x03)
- #define SW_SCALE_R(v) ((v)*255+3)/7
- #define SW_SCALE_G(v) ((v)*255+3)/7
- #define SW_SCALE_B(v) ((v)*255+1)/3
- #define SW_TO_FLOAT_R(v) ((v)*(1.0f/7.0f))
- #define SW_TO_FLOAT_G(v) ((v)*(1.0f/7.0f))
- #define SW_TO_FLOAT_B(v) ((v)*(1.0f/3.0f))
-#elif (SW_COLOR_BUFFER_BITS == 16)
- #define SW_COLOR_TYPE uint16_t
- #define SW_COLOR_IS_PACKED 1
- #define SW_COLOR_PACK_COMP 1
- #define SW_PACK_COLOR(r,g,b) ((((uint16_t)((r)*31+0.5f))&0x1F)<<11 | (((uint16_t)((g)*63+0.5f))&0x3F)<<5 | ((uint16_t)((b)*31+0.5f))&0x1F)
- #define SW_UNPACK_R(p) (((p)>>11)&0x1F)
- #define SW_UNPACK_G(p) (((p)>>5)&0x3F)
- #define SW_UNPACK_B(p) ((p)&0x1F)
- #define SW_SCALE_R(v) ((v)*255+15)/31
- #define SW_SCALE_G(v) ((v)*255+31)/63
- #define SW_SCALE_B(v) ((v)*255+15)/31
- #define SW_TO_FLOAT_R(v) ((v)*(1.0f/31.0f))
- #define SW_TO_FLOAT_G(v) ((v)*(1.0f/63.0f))
- #define SW_TO_FLOAT_B(v) ((v)*(1.0f/31.0f))
-#else // 32 bits
- #define SW_COLOR_TYPE uint8_t
- #define SW_COLOR_IS_PACKED 0
- #define SW_COLOR_PACK_COMP 4
-#endif
+#define SW_CONCAT(a, b) a##b
+#define SW_CONCATX(a, b) SW_CONCAT(a, b)
-#if (SW_DEPTH_BUFFER_BITS == 16)
- #define SW_DEPTH_TYPE uint16_t
- #define SW_DEPTH_IS_PACKED 1
- #define SW_DEPTH_PACK_COMP 1
- #define SW_DEPTH_MAX UINT16_MAX
- #define SW_DEPTH_SCALE (1.0f/UINT16_MAX)
- #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)((d)*SW_DEPTH_MAX))
- #define SW_UNPACK_DEPTH(p) (p)
-#elif (SW_DEPTH_BUFFER_BITS == 24)
- #define SW_DEPTH_TYPE uint8_t
- #define SW_DEPTH_IS_PACKED 0
- #define SW_DEPTH_PACK_COMP 3
- #define SW_DEPTH_MAX 0xFFFFFFU
- #define SW_DEPTH_SCALE (1.0f/0xFFFFFFU)
- #define SW_PACK_DEPTH_0(d) ((uint8_t)(((uint32_t)((d)*SW_DEPTH_MAX)>>16)&0xFFU))
- #define SW_PACK_DEPTH_1(d) ((uint8_t)(((uint32_t)((d)*SW_DEPTH_MAX)>>8)&0xFFU))
- #define SW_PACK_DEPTH_2(d) ((uint8_t)((uint32_t)((d)*SW_DEPTH_MAX)&0xFFU))
- #define SW_UNPACK_DEPTH(p) ((((uint32_t)(p)[0]<<16)|((uint32_t)(p)[1]<<8)|(uint32_t)(p)[2]))
-#else // 32 bits
- #define SW_DEPTH_TYPE float
- #define SW_DEPTH_IS_PACKED 1
- #define SW_DEPTH_PACK_COMP 1
- #define SW_DEPTH_MAX 1.0f
- #define SW_DEPTH_SCALE 1.0f
- #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)(d))
- #define SW_UNPACK_DEPTH(p) (p)
-#endif
+#define SW_FRAMEBUFFER_COLOR8_GET(c,p,o) SW_CONCATX(sw_pixel_read_color8_, SW_FRAMEBUFFER_COLOR_TYPE)((c),(p),(o))
+#define SW_FRAMEBUFFER_COLOR_GET(c,p,o) SW_CONCATX(sw_pixel_read_color_, SW_FRAMEBUFFER_COLOR_TYPE)((c),(p),(o))
+#define SW_FRAMEBUFFER_COLOR_SET(p,c,o) SW_CONCATX(sw_pixel_write_color_, SW_FRAMEBUFFER_COLOR_TYPE)((p),(c),(o))
-#define SW_STATE_CHECK(flags) (SW_STATE_CHECK_EX(RLSW.stateFlags, (flags)))
-#define SW_STATE_CHECK_EX(state, flags) (((state) & (flags)) == (flags))
+#define SW_FRAMEBUFFER_DEPTH_GET(p,o) SW_CONCATX(sw_pixel_read_depth_, SW_FRAMEBUFFER_DEPTH_TYPE)((p),(o))
+#define SW_FRAMEBUFFER_DEPTH_SET(p,d,o) SW_CONCATX(sw_pixel_write_depth_, SW_FRAMEBUFFER_DEPTH_TYPE)((p),(d),(o))
+
+#define SW_FRAMEBUFFER_COLOR_FORMAT SW_CONCATX(SW_PIXELFORMAT_COLOR_, SW_FRAMEBUFFER_COLOR_TYPE)
+#define SW_FRAMEBUFFER_DEPTH_FORMAT SW_CONCATX(SW_PIXELFORMAT_DEPTH_, SW_FRAMEBUFFER_DEPTH_TYPE)
+
+#define SW_FRAMEBUFFER_COLOR_SIZE SW_PIXELFORMAT_SIZE[SW_FRAMEBUFFER_COLOR_FORMAT]
+#define SW_FRAMEBUFFER_DEPTH_SIZE SW_PIXELFORMAT_SIZE[SW_FRAMEBUFFER_DEPTH_FORMAT]
#define SW_STATE_SCISSOR_TEST (1 << 0)
#define SW_STATE_TEXTURE_2D (1 << 1)
@@ -792,94 +891,132 @@ SWAPI void swBindTexture(uint32_t id);
#define SW_STATE_CULL_FACE (1 << 3)
#define SW_STATE_BLEND (1 << 4)
+#define SW_BLEND_FLAG_NOOP (1 << 0)
+#define SW_BLEND_FLAG_NEEDS_ALPHA (1 << 1)
+
//----------------------------------------------------------------------------------
// Module Types and Structures Definition
//----------------------------------------------------------------------------------
-// Pixel data format type
-// NOTE: Enum aligned with raylib PixelFormat
-typedef enum {
- SW_PIXELFORMAT_UNKNOWN = 0,
- SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE, // 8 bit per pixel (no alpha)
- SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels)
- SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5, // 16 bpp
- SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8, // 24 bpp
- SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
- SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
- SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, // 32 bpp
- SW_PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
- SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
- SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
- SW_PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float)
- SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float)
- SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float)
-} sw_pixelformat_t;
-
-typedef void (*sw_factor_f)(
- float *SW_RESTRICT factor,
- const float *SW_RESTRICT src,
- const float *SW_RESTRICT dst
-);
-
-typedef float sw_matrix_t[4*4];
+// Aliases types
+typedef uint32_t sw_handle_t;
typedef uint16_t sw_half_t;
-typedef struct {
- float position[4]; // Position coordinates
- float texcoord[2]; // Texture coordinates
- float color[4]; // Color value (RGBA)
+// Pixel data format type
+typedef enum {
+ SW_PIXELFORMAT_UNKNOWN = 0,
+ SW_PIXELFORMAT_COLOR_GRAYSCALE, // 8 bit per pixel (no alpha)
+ SW_PIXELFORMAT_COLOR_GRAYALPHA, // 8*2 bpp (2 channels)
+ SW_PIXELFORMAT_COLOR_R3G3B2, // 8 bpp
+ SW_PIXELFORMAT_COLOR_R5G6B5, // 16 bpp
+ SW_PIXELFORMAT_COLOR_R8G8B8, // 24 bpp
+ SW_PIXELFORMAT_COLOR_R5G5B5A1, // 16 bpp (1 bit alpha)
+ SW_PIXELFORMAT_COLOR_R4G4B4A4, // 16 bpp (4 bit alpha)
+ SW_PIXELFORMAT_COLOR_R8G8B8A8, // 32 bpp
+ SW_PIXELFORMAT_COLOR_R32, // 32 bpp (1 channel - float)
+ SW_PIXELFORMAT_COLOR_R32G32B32, // 32*3 bpp (3 channels - float)
+ SW_PIXELFORMAT_COLOR_R32G32B32A32, // 32*4 bpp (4 channels - float)
+ SW_PIXELFORMAT_COLOR_R16, // 16 bpp (1 channel - half float)
+ SW_PIXELFORMAT_COLOR_R16G16B16, // 16*3 bpp (3 channels - half float)
+ SW_PIXELFORMAT_COLOR_R16G16B16A16, // 16*4 bpp (4 channels - half float)
+ SW_PIXELFORMAT_DEPTH_D8, // 1 bpp
+ SW_PIXELFORMAT_DEPTH_D16, // 2 bpp
+ SW_PIXELFORMAT_DEPTH_D32, // 4 bpp
+ SW_PIXELFORMAT_COUNT
+} sw_pixelformat_t;
- float homogeneous[4]; // Homogeneous coordinates
- float screen[2]; // Screen coordinates
+typedef enum {
+ SW_PIXEL_ALPHA_NONE = 0, // No transparency
+ SW_PIXEL_ALPHA_BIN, // Binary transparency
+ SW_PIXEL_ALPHA_YES, // Contains transparency
+} sw_pixel_alpha_t;
+
+// Forward declarations
+typedef struct sw_vertex sw_vertex_t;
+
+// Pixel getter functions
+typedef void (*sw_pixel_read_color8_f)(uint8_t *SW_RESTRICT, const void *SW_RESTRICT, uint32_t);
+typedef void (*sw_pixel_read_color_f)(float *SW_RESTRICT, const void *SW_RESTRICT, uint32_t);
+
+// Pixel setter functions
+typedef void (*sw_pixel_write_color8_f)(void *SW_RESTRICT, const uint8_t *SW_RESTRICT, uint32_t);
+typedef void (*sw_pixel_write_color_f)(void *SW_RESTRICT, const float *SW_RESTRICT, uint32_t);
+
+// Color blending function
+typedef void (*sw_blend_f)(float *SW_RESTRICT, const float *SW_RESTRICT);
+
+// Rasterizer functions
+typedef void (*sw_raster_triangle_f)(const sw_vertex_t*, const sw_vertex_t*, const sw_vertex_t*);
+typedef void (*sw_raster_quad_f)(const sw_vertex_t*, const sw_vertex_t*, const sw_vertex_t*, const sw_vertex_t*);
+typedef void (*sw_raster_line_f)(const sw_vertex_t*, const sw_vertex_t*);
+typedef void (*sw_raster_point_f)(const sw_vertex_t*);
+
+typedef float sw_matrix_t[4*4];
+
+typedef struct sw_vertex {
+ float position[4]; // Clip space (x,y,z,w) -> NDC (after /w) -> screen space (x,y,z,1/w)
+ float color[4]; // Color value (RGBA)
+ float texcoord[2]; // Texture coordinates
} sw_vertex_t;
typedef struct {
- uint8_t *pixels; // Texture pixels (RGBA32)
-
- int width, height; // Dimensions of the texture
- int wMinus1, hMinus1; // Dimensions minus one
-
- SWfilter minFilter; // Minification filter
- SWfilter magFilter; // Magnification filter
-
- SWwrap sWrap; // texcoord.x wrap mode
- SWwrap tWrap; // texcoord.y wrap mode
-
- float tx; // Texel width
- float ty; // Texel height
+ void *pixels; // Texture pixels
+ sw_pixel_read_color8_f readColor8; // Texel read RGBA8
+ sw_pixel_read_color_f readColor; // Texel read RGBA32F
+ sw_pixelformat_t format; // Texture format
+ sw_pixel_alpha_t alpha; // Texture alpha mode
+ int width, height; // Dimensions of the texture
+ int wMinus1, hMinus1; // Dimensions minus one
+ int allocSz; // Allocated size
+ SWfilter minFilter; // Minification filter
+ SWfilter magFilter; // Magnification filter
+ SWwrap sWrap; // Wrap mode for texcoord.x
+ SWwrap tWrap; // Wrap mode for texcoord.y
+ float tx; // Texel width
+ float ty; // Texel height
} sw_texture_t;
-// Pixel data type
-typedef SW_ALIGN(SW_PIXEL_ALIGNMENT) struct {
- SW_COLOR_TYPE color[SW_COLOR_PACK_COMP];
- SW_DEPTH_TYPE depth[SW_DEPTH_PACK_COMP];
-#if (SW_PIXEL_SIZE % SW_PIXEL_ALIGNMENT != 0)
- uint8_t padding[SW_PIXEL_ALIGNMENT - SW_PIXEL_SIZE % SW_PIXEL_ALIGNMENT];
-#endif
-} sw_pixel_t;
+typedef struct {
+ sw_texture_t color; // Default framebuffer color texture
+ sw_texture_t depth; // Default framebuffer depth texture
+} sw_default_framebuffer_t;
typedef struct {
- sw_pixel_t *pixels;
- int width;
- int height;
- int allocSz;
+ sw_handle_t colorAttachment; // Framebuffer color attachment id
+ sw_handle_t depthAttachment; // Framebuffer depth attachment id
} sw_framebuffer_t;
typedef struct {
- sw_framebuffer_t framebuffer; // Main framebuffer
- sw_pixel_t clearValue; // Clear value of the framebuffer
+ void *data; // Flat storage [capacity*stride] bytes
+ uint8_t *gen; // Generation per slot [capacity]
+ uint32_t *freeList; // Free indices stack [capacity]
+ int freeCount;
+ int watermark; // Next blank index (starts at 1, skips 0)
+ int capacity;
+ size_t stride;
+} sw_pool_t;
- float vpCenter[2]; // Viewport center
- float vpHalf[2]; // Viewport half dimensions
- int vpSize[2]; // Viewport dimensions (minus one)
- int vpMin[2]; // Viewport minimum renderable point (top-left)
- int vpMax[2]; // Viewport maximum renderable point (bottom-right)
+// Graphic context data structure
+typedef struct {
+ sw_default_framebuffer_t framebuffer; // Default framebuffer
+ float clearColor[4]; // Clear color of the framebuffer
+ float clearDepth; // Clear depth of the framebuffer
- int scMin[2]; // Scissor rectangle minimum renderable point (top-left)
- int scMax[2]; // Scissor rectangle maximum renderable point (bottom-right)
- float scClipMin[2]; // Scissor rectangle minimum renderable point in clip space
- float scClipMax[2]; // Scissor rectangle maximum renderable point in clip space
+ float vpCenter[2]; // Viewport center
+ float vpHalf[2]; // Viewport half dimensions
+ int vpSize[2]; // Viewport dimensions
- uint32_t currentTexture; // Current active texture id
+ int scMin[2]; // Scissor rectangle minimum renderable point (top-left)
+ int scMax[2]; // Scissor rectangle maximum renderable point (bottom-right)
+ float scClipMin[2]; // Scissor rectangle minimum renderable point in clip space
+ float scClipMax[2]; // Scissor rectangle maximum renderable point in clip space
+
+ struct {
+ sw_vertex_t buffer[SW_MAX_CLIPPED_POLYGON_VERTICES]; // Buffer used for storing primitive vertices, used for processing and rendering
+ int vertexCount; // Number of vertices in the primtive buffer
+ float color[4]; // Current color for the next pushed vertex
+ float texcoord[2]; // Current texture coordinates for the next push vertex
+ bool hasColorAlpha; // Flag indicating whether the current primitive contains transparency
+ } primitive;
struct {
float *positions;
@@ -887,17 +1024,8 @@ typedef struct {
uint8_t *colors;
} array;
- struct {
- float texcoord[2];
- float color[4];
- } current;
-
- sw_vertex_t vertexBuffer[SW_MAX_CLIPPED_POLYGON_VERTICES]; // Buffer used for storing primitive vertices, used for processing and rendering
- int vertexCounter; // Number of vertices in 'ctx.vertexBuffer'
-
SWdraw drawMode; // Current primitive mode (e.g., lines, triangles)
SWpoly polyMode; // Current polygon filling mode (e.g., lines, triangles)
- int reqVertices; // Number of vertices required for the primitive being drawn
float pointRadius; // Rasterized point radius
float lineWidth; // Rasterized line width
@@ -912,22 +1040,24 @@ typedef struct {
sw_matrix_t matMVP; // Model view projection matrix, calculated and used internally
bool isDirtyMVP; // Indicates if the MVP matrix should be rebuilt
- SWfactor srcFactor;
- SWfactor dstFactor;
+ sw_handle_t boundFramebufferId; // Framebuffer currently bound
+ sw_texture_t *colorBuffer; // Color buffer currently bound
+ sw_texture_t *depthBuffer; // Depth buffer currently bound
+ sw_pool_t framebufferPool; // Framebuffer object pool
- sw_factor_f srcFactorFunc;
- sw_factor_f dstFactorFunc;
+ sw_texture_t *boundTexture; // Texture currently bound
+ sw_pool_t texturePool; // Texture object pool
+
+ SWfactor srcFactor; // Source blending factor
+ SWfactor dstFactor; // Destination bleending factor
+ uint32_t blendFlags; // Flags about the current blend mode
+ sw_blend_f blendFunc; // Source blend function
SWface cullFace; // Faces to cull
SWerrcode errCode; // Last error code
- sw_texture_t *loadedTextures;
- int loadedTextureCount;
-
- uint32_t *freeTextureIds;
- int freeTextureIdCount;
-
- uint32_t stateFlags;
+ uint32_t userState; // User-defined pipeline state
+ uint32_t rasterState; // Cleaned pipeline state for the rasterizer
} sw_context_t;
//----------------------------------------------------------------------------------
@@ -935,8 +1065,71 @@ typedef struct {
//----------------------------------------------------------------------------------
static sw_context_t RLSW = { 0 };
+#if SW_USE_COLOR_LUT
+static float SW_LUT_UINT8_TO_FLOAT[256] = { 0 };
+#endif
+
//----------------------------------------------------------------------------------
-// Module Functions Declaration
+// Internal Constants Definition
+//----------------------------------------------------------------------------------
+// Pixel formats that has an alpha channel
+static const sw_pixel_alpha_t SW_PIXELFORMAT_ALPHA[SW_PIXELFORMAT_COUNT] =
+{
+ [SW_PIXELFORMAT_COLOR_GRAYSCALE] = SW_PIXEL_ALPHA_NONE,
+ [SW_PIXELFORMAT_COLOR_GRAYALPHA] = SW_PIXEL_ALPHA_YES,
+ [SW_PIXELFORMAT_COLOR_R3G3B2] = SW_PIXEL_ALPHA_NONE,
+ [SW_PIXELFORMAT_COLOR_R5G6B5] = SW_PIXEL_ALPHA_NONE,
+ [SW_PIXELFORMAT_COLOR_R8G8B8] = SW_PIXEL_ALPHA_NONE,
+ [SW_PIXELFORMAT_COLOR_R5G5B5A1] = SW_PIXEL_ALPHA_BIN,
+ [SW_PIXELFORMAT_COLOR_R4G4B4A4] = SW_PIXEL_ALPHA_YES,
+ [SW_PIXELFORMAT_COLOR_R8G8B8A8] = SW_PIXEL_ALPHA_YES,
+ [SW_PIXELFORMAT_COLOR_R32] = SW_PIXEL_ALPHA_NONE,
+ [SW_PIXELFORMAT_COLOR_R32G32B32] = SW_PIXEL_ALPHA_NONE,
+ [SW_PIXELFORMAT_COLOR_R32G32B32A32] = SW_PIXEL_ALPHA_YES,
+ [SW_PIXELFORMAT_COLOR_R16] = SW_PIXEL_ALPHA_NONE,
+ [SW_PIXELFORMAT_COLOR_R16G16B16] = SW_PIXEL_ALPHA_NONE,
+ [SW_PIXELFORMAT_COLOR_R16G16B16A16] = SW_PIXEL_ALPHA_YES,
+ [SW_PIXELFORMAT_DEPTH_D8] = SW_PIXEL_ALPHA_NONE,
+ [SW_PIXELFORMAT_DEPTH_D16] = SW_PIXEL_ALPHA_NONE,
+ [SW_PIXELFORMAT_DEPTH_D32] = SW_PIXEL_ALPHA_NONE,
+};
+
+// Pixel formats sizes in bytes
+static const int SW_PIXELFORMAT_SIZE[SW_PIXELFORMAT_COUNT] =
+{
+ [SW_PIXELFORMAT_COLOR_GRAYSCALE] = 1,
+ [SW_PIXELFORMAT_COLOR_GRAYALPHA] = 2,
+ [SW_PIXELFORMAT_COLOR_R3G3B2] = 1,
+ [SW_PIXELFORMAT_COLOR_R5G6B5] = 2,
+ [SW_PIXELFORMAT_COLOR_R8G8B8] = 3,
+ [SW_PIXELFORMAT_COLOR_R5G5B5A1] = 2,
+ [SW_PIXELFORMAT_COLOR_R4G4B4A4] = 2,
+ [SW_PIXELFORMAT_COLOR_R8G8B8A8] = 4,
+ [SW_PIXELFORMAT_COLOR_R32] = 4,
+ [SW_PIXELFORMAT_COLOR_R32G32B32] = 12,
+ [SW_PIXELFORMAT_COLOR_R32G32B32A32] = 16,
+ [SW_PIXELFORMAT_COLOR_R16] = 2,
+ [SW_PIXELFORMAT_COLOR_R16G16B16] = 6,
+ [SW_PIXELFORMAT_COLOR_R16G16B16A16] = 8,
+ [SW_PIXELFORMAT_DEPTH_D8] = 1,
+ [SW_PIXELFORMAT_DEPTH_D16] = 2,
+ [SW_PIXELFORMAT_DEPTH_D32] = 4,
+};
+
+static const int SW_PRIMITIVE_VERTEX_COUNT[] =
+{
+ // Remember that this is acceptable; these are small indices
+ [SW_POINTS] = 1,
+ [SW_LINES] = 2,
+ [SW_TRIANGLES] = 3,
+ [SW_QUADS] = 4,
+};
+
+//----------------------------------------------------------------------------------
+// Internal Functions Definitions
+//----------------------------------------------------------------------------------
+
+// Math helper functions
//----------------------------------------------------------------------------------
static inline void sw_matrix_id(sw_matrix_t dst)
{
@@ -977,12 +1170,24 @@ static inline void sw_matrix_mul_rst(float *SW_RESTRICT dst, const float *SW_RES
static inline void sw_matrix_mul(sw_matrix_t dst, const sw_matrix_t left, const sw_matrix_t right)
{
float result[16];
-
sw_matrix_mul_rst(result, left, right);
-
for (int i = 0; i < 16; i++) dst[i] = result[i];
}
+static inline int sw_clamp_int(int v, int min, int max)
+{
+ if (v < min) return min;
+ if (v > max) return max;
+ return v;
+}
+
+static inline int sw_clamp(float v, float min, float max)
+{
+ if (v < min) return min;
+ if (v > max) return max;
+ return v;
+}
+
static inline float sw_saturate(float x)
{
union { float f; uint32_t u; } fb;
@@ -1005,14 +1210,17 @@ static inline float sw_fract(float x)
return (x - floorf(x));
}
-static inline int sw_clampi(int v, int min, int max)
+static inline uint8_t sw_luminance8(const uint8_t *color)
{
- if (v < min) return min;
- if (v > max) return max;
- return v;
+ return (uint8_t)((color[0]*77 + color[1]*150 + color[2]*29) >> 8);
}
-static inline void sw_lerp_vertex_PTCH(sw_vertex_t *SW_RESTRICT out, const sw_vertex_t *SW_RESTRICT a, const sw_vertex_t *SW_RESTRICT b, float t)
+static inline float sw_luminance(const float *color)
+{
+ return color[0]*0.299f + color[1]*0.587f + color[2]*0.114f;
+}
+
+static inline void sw_lerp_vertex_PCT(sw_vertex_t *SW_RESTRICT out, const sw_vertex_t *SW_RESTRICT a, const sw_vertex_t *SW_RESTRICT b, float t)
{
const float tInv = 1.0f - t;
@@ -1022,24 +1230,18 @@ static inline void sw_lerp_vertex_PTCH(sw_vertex_t *SW_RESTRICT out, const sw_ve
out->position[2] = a->position[2]*tInv + b->position[2]*t;
out->position[3] = a->position[3]*tInv + b->position[3]*t;
- // Texture coordinate interpolation (2 components)
- out->texcoord[0] = a->texcoord[0]*tInv + b->texcoord[0]*t;
- out->texcoord[1] = a->texcoord[1]*tInv + b->texcoord[1]*t;
-
// Color interpolation (4 components)
out->color[0] = a->color[0]*tInv + b->color[0]*t;
out->color[1] = a->color[1]*tInv + b->color[1]*t;
out->color[2] = a->color[2]*tInv + b->color[2]*t;
out->color[3] = a->color[3]*tInv + b->color[3]*t;
- // Homogeneous coordinate interpolation (4 components)
- out->homogeneous[0] = a->homogeneous[0]*tInv + b->homogeneous[0]*t;
- out->homogeneous[1] = a->homogeneous[1]*tInv + b->homogeneous[1]*t;
- out->homogeneous[2] = a->homogeneous[2]*tInv + b->homogeneous[2]*t;
- out->homogeneous[3] = a->homogeneous[3]*tInv + b->homogeneous[3]*t;
+ // Texture coordinate interpolation (2 components)
+ out->texcoord[0] = a->texcoord[0]*tInv + b->texcoord[0]*t;
+ out->texcoord[1] = a->texcoord[1]*tInv + b->texcoord[1]*t;
}
-static inline void sw_get_vertex_grad_PTCH(sw_vertex_t *SW_RESTRICT out, const sw_vertex_t *SW_RESTRICT a, const sw_vertex_t *SW_RESTRICT b, float scale)
+static inline void sw_get_vertex_grad_PCT(sw_vertex_t *SW_RESTRICT out, const sw_vertex_t *SW_RESTRICT a, const sw_vertex_t *SW_RESTRICT b, float scale)
{
// Calculate gradients for Position
out->position[0] = (b->position[0] - a->position[0])*scale;
@@ -1047,24 +1249,18 @@ static inline void sw_get_vertex_grad_PTCH(sw_vertex_t *SW_RESTRICT out, const s
out->position[2] = (b->position[2] - a->position[2])*scale;
out->position[3] = (b->position[3] - a->position[3])*scale;
- // Calculate gradients for Texture coordinates
- out->texcoord[0] = (b->texcoord[0] - a->texcoord[0])*scale;
- out->texcoord[1] = (b->texcoord[1] - a->texcoord[1])*scale;
-
// Calculate gradients for Color
out->color[0] = (b->color[0] - a->color[0])*scale;
out->color[1] = (b->color[1] - a->color[1])*scale;
out->color[2] = (b->color[2] - a->color[2])*scale;
out->color[3] = (b->color[3] - a->color[3])*scale;
- // Calculate gradients for Homogeneous coordinates
- out->homogeneous[0] = (b->homogeneous[0] - a->homogeneous[0])*scale;
- out->homogeneous[1] = (b->homogeneous[1] - a->homogeneous[1])*scale;
- out->homogeneous[2] = (b->homogeneous[2] - a->homogeneous[2])*scale;
- out->homogeneous[3] = (b->homogeneous[3] - a->homogeneous[3])*scale;
+ // Calculate gradients for Texture coordinates
+ out->texcoord[0] = (b->texcoord[0] - a->texcoord[0])*scale;
+ out->texcoord[1] = (b->texcoord[1] - a->texcoord[1])*scale;
}
-static inline void sw_add_vertex_grad_PTCH(sw_vertex_t *SW_RESTRICT out, const sw_vertex_t *SW_RESTRICT gradients)
+static inline void sw_add_vertex_grad_PCT(sw_vertex_t *SW_RESTRICT out, const sw_vertex_t *SW_RESTRICT gradients)
{
// Add gradients to Position
out->position[0] += gradients->position[0];
@@ -1072,27 +1268,18 @@ static inline void sw_add_vertex_grad_PTCH(sw_vertex_t *SW_RESTRICT out, const s
out->position[2] += gradients->position[2];
out->position[3] += gradients->position[3];
- // Add gradients to Texture coordinates
- out->texcoord[0] += gradients->texcoord[0];
- out->texcoord[1] += gradients->texcoord[1];
-
// Add gradients to Color
out->color[0] += gradients->color[0];
out->color[1] += gradients->color[1];
out->color[2] += gradients->color[2];
out->color[3] += gradients->color[3];
- // Add gradients to Homogeneous coordinates
- out->homogeneous[0] += gradients->homogeneous[0];
- out->homogeneous[1] += gradients->homogeneous[1];
- out->homogeneous[2] += gradients->homogeneous[2];
- out->homogeneous[3] += gradients->homogeneous[3];
+ // Add gradients to Texture coordinates
+ out->texcoord[0] += gradients->texcoord[0];
+ out->texcoord[1] += gradients->texcoord[1];
}
-static inline void sw_add_vertex_grad_scaled_PTCH(
- sw_vertex_t *SW_RESTRICT out,
- const sw_vertex_t *SW_RESTRICT gradients,
- float scale)
+static inline void sw_add_vertex_grad_scaled_PCT(sw_vertex_t *SW_RESTRICT out, const sw_vertex_t *SW_RESTRICT gradients, float scale)
{
// Add gradients to Position
out->position[0] += gradients->position[0]*scale;
@@ -1100,145 +1287,64 @@ static inline void sw_add_vertex_grad_scaled_PTCH(
out->position[2] += gradients->position[2]*scale;
out->position[3] += gradients->position[3]*scale;
- // Add gradients to Texture coordinates
- out->texcoord[0] += gradients->texcoord[0]*scale;
- out->texcoord[1] += gradients->texcoord[1]*scale;
-
// Add gradients to Color
out->color[0] += gradients->color[0]*scale;
out->color[1] += gradients->color[1]*scale;
out->color[2] += gradients->color[2]*scale;
out->color[3] += gradients->color[3]*scale;
- // Add gradients to Homogeneous coordinates
- out->homogeneous[0] += gradients->homogeneous[0]*scale;
- out->homogeneous[1] += gradients->homogeneous[1]*scale;
- out->homogeneous[2] += gradients->homogeneous[2]*scale;
- out->homogeneous[3] += gradients->homogeneous[3]*scale;
+ // Add gradients to Texture coordinates
+ out->texcoord[0] += gradients->texcoord[0]*scale;
+ out->texcoord[1] += gradients->texcoord[1]*scale;
}
-static inline void sw_float_to_unorm8_simd(uint8_t dst[4], const float src[4])
+static inline void sw_get_vertex_grad_PC(sw_vertex_t *SW_RESTRICT out, const sw_vertex_t *SW_RESTRICT a, const sw_vertex_t *SW_RESTRICT b, float scale)
{
-#if defined(SW_HAS_NEON)
- float32x4_t values = vld1q_f32(src);
- float32x4_t scaled = vmulq_n_f32(values, 255.0f);
- int32x4_t clamped_s32 = vcvtq_s32_f32(scaled); // f32 -> s32 (truncated)
- int16x4_t narrow16_s = vqmovn_s32(clamped_s32);
- int16x8_t combined16_s = vcombine_s16(narrow16_s, narrow16_s);
- uint8x8_t narrow8_u = vqmovun_s16(combined16_s);
- vst1_lane_u32((uint32_t*)dst, vreinterpret_u32_u8(narrow8_u), 0);
-#elif defined(SW_HAS_SSE41)
- __m128 values = _mm_loadu_ps(src);
- __m128 scaled = _mm_mul_ps(values, _mm_set1_ps(255.0f));
- __m128i clamped = _mm_cvtps_epi32(scaled); // f32 -> s32 (truncated)
- clamped = _mm_packus_epi32(clamped, clamped); // s32 -> u16 (saturated < 0 to 0)
- clamped = _mm_packus_epi16(clamped, clamped); // u16 -> u8 (saturated > 255 to 255)
- *(uint32_t*)dst = _mm_cvtsi128_si32(clamped);
-#elif defined(SW_HAS_SSE2)
- __m128 values = _mm_loadu_ps(src);
- __m128 scaled = _mm_mul_ps(values, _mm_set1_ps(255.0f));
- __m128i clamped = _mm_cvtps_epi32(scaled); // f32 -> s32 (truncated)
- clamped = _mm_packs_epi32(clamped, clamped); // s32 -> s16 (saturated)
- clamped = _mm_packus_epi16(clamped, clamped); // s16 -> u8 (saturated < 0 to 0)
- *(uint32_t*)dst = _mm_cvtsi128_si32(clamped);
-#elif defined(SW_HAS_RVV)
- // TODO: Sample code generated by AI, needs testing and review
- // NOTE: RVV 1.0 specs define the use of __riscv_ prefix for instrinsic functions
- size_t vl = __riscv_vsetvl_e32m1(4); // Load up to 4 floats into a vector register
- vfloat32m1_t vsrc = __riscv_vle32_v_f32m1(src, vl); // Load float32 values
+ // Calculate gradients for Position
+ out->position[0] = (b->position[0] - a->position[0])*scale;
+ out->position[1] = (b->position[1] - a->position[1])*scale;
+ out->position[2] = (b->position[2] - a->position[2])*scale;
+ out->position[3] = (b->position[3] - a->position[3])*scale;
- // Clamp to [0.0f, 1.0f]
- vfloat32m1_t vzero = __riscv_vfmv_v_f_f32m1(0.0f, vl);
- vfloat32m1_t vone = __riscv_vfmv_v_f_f32m1(1.0f, vl);
- vsrc = __riscv_vfmin_vv_f32m1(vsrc, vone, vl);
- vsrc = __riscv_vfmax_vv_f32m1(vsrc, vzero, vl);
-
- // Multiply by 255.0f and add 0.5f for rounding
- vfloat32m1_t vscaled = __riscv_vfmul_vf_f32m1(vsrc, 255.0f, vl);
- vscaled = __riscv_vfadd_vf_f32m1(vscaled, 0.5f, vl);
-
- // Convert to unsigned integer (truncate toward zero)
- vuint32m1_t vu32 = __riscv_vfcvt_xu_f_v_u32m1(vscaled, vl);
-
- // Narrow from u32 -> u8
- vuint8m1_t vu8 = __riscv_vnclipu_wx_u8m1(vu32, 0, vl); // Round toward zero
- __riscv_vse8_v_u8m1(dst, vu8, vl); // Store result
-#else
- for (int i = 0; i < 4; i++)
- {
- float val = src[i]*255.0f;
- val = (val > 255.0f)? 255.0f : val;
- val = (val < 0.0f)? 0.0f : val;
- dst[i] = (uint8_t)val;
- }
-#endif
+ // Calculate gradients for Color
+ out->color[0] = (b->color[0] - a->color[0])*scale;
+ out->color[1] = (b->color[1] - a->color[1])*scale;
+ out->color[2] = (b->color[2] - a->color[2])*scale;
+ out->color[3] = (b->color[3] - a->color[3])*scale;
}
-static inline void sw_float_from_unorm8_simd(float dst[4], const uint8_t src[4])
+static inline void sw_add_vertex_grad_PC(sw_vertex_t *SW_RESTRICT out, const sw_vertex_t *SW_RESTRICT gradients)
{
-#if defined(SW_HAS_NEON)
- uint8x8_t bytes8 = vld1_u8(src); // Reading 8 bytes, faster, but let's hope not hitting the end of the page (unlikely)...
- uint16x8_t bytes16 = vmovl_u8(bytes8);
- uint32x4_t ints = vmovl_u16(vget_low_u16(bytes16));
- float32x4_t floats = vcvtq_f32_u32(ints);
- floats = vmulq_n_f32(floats, SW_INV_255);
- vst1q_f32(dst, floats);
-#elif defined(SW_HAS_SSE41)
- __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t *)src);
- __m128i ints = _mm_cvtepu8_epi32(bytes);
- __m128 floats = _mm_cvtepi32_ps(ints);
- floats = _mm_mul_ps(floats, _mm_set1_ps(SW_INV_255));
- _mm_storeu_ps(dst, floats);
-#elif defined(SW_HAS_SSE2)
- __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t *)src);
- bytes = _mm_unpacklo_epi8(bytes, _mm_setzero_si128());
- __m128i ints = _mm_unpacklo_epi16(bytes, _mm_setzero_si128());
- __m128 floats = _mm_cvtepi32_ps(ints);
- floats = _mm_mul_ps(floats, _mm_set1_ps(SW_INV_255));
- _mm_storeu_ps(dst, floats);
-#elif defined(SW_HAS_RVV)
- // TODO: Sample code generated by AI, needs testing and review
- size_t vl = __riscv_vsetvl_e8m1(4); // Set vector length for 8-bit input elements
- vuint8m1_t vsrc_u8 = __riscv_vle8_v_u8m1(src, vl); // Load 4 unsigned 8-bit integers
- vuint32m1_t vsrc_u32 = __riscv_vwcvt_xu_u_v_u32m1(vsrc_u8, vl); // Widen to 32-bit unsigned integers
- vfloat32m1_t vsrc_f32 = __riscv_vfcvt_f_xu_v_f32m1(vsrc_u32, vl); // Convert to float32
- vfloat32m1_t vnorm = __riscv_vfmul_vf_f32m1(vsrc_f32, SW_INV_255, vl); // Multiply by 1/255.0 to normalize
- __riscv_vse32_v_f32m1(dst, vnorm, vl); // Store result
-#else
- dst[0] = (float)src[0]*SW_INV_255;
- dst[1] = (float)src[1]*SW_INV_255;
- dst[2] = (float)src[2]*SW_INV_255;
- dst[3] = (float)src[3]*SW_INV_255;
-#endif
+ // Add gradients to Position
+ out->position[0] += gradients->position[0];
+ out->position[1] += gradients->position[1];
+ out->position[2] += gradients->position[2];
+ out->position[3] += gradients->position[3];
+
+ // Add gradients to Color
+ out->color[0] += gradients->color[0];
+ out->color[1] += gradients->color[1];
+ out->color[2] += gradients->color[2];
+ out->color[3] += gradients->color[3];
+}
+
+static inline void sw_add_vertex_grad_scaled_PC(sw_vertex_t *SW_RESTRICT out, const sw_vertex_t *SW_RESTRICT gradients, float scale)
+{
+ // Add gradients to Position
+ out->position[0] += gradients->position[0]*scale;
+ out->position[1] += gradients->position[1]*scale;
+ out->position[2] += gradients->position[2]*scale;
+ out->position[3] += gradients->position[3]*scale;
+
+ // Add gradients to Color
+ out->color[0] += gradients->color[0]*scale;
+ out->color[1] += gradients->color[1]*scale;
+ out->color[2] += gradients->color[2]*scale;
+ out->color[3] += gradients->color[3]*scale;
}
// Half conversion functions
-static inline uint32_t sw_half_to_float_ui(uint16_t h)
-{
- uint32_t s = (uint32_t)(h & 0x8000) << 16;
- int32_t em = h & 0x7fff;
-
- // bias exponent and pad mantissa with 0; 112 is relative exponent bias (127-15)
- int32_t r = (em + (112 << 10)) << 13;
-
- // denormal: flush to zero
- r = (em < (1 << 10))? 0 : r;
-
- // NOTE: infinity/NaN; NaN payload is preserved as a byproduct of unifying inf/nan cases
- // 112 is an exponent bias fixup; since it is already applied once, applying it twice converts 31 to 255
- r += (em >= (31 << 10))? (112 << 23) : 0;
-
- return s | r;
-}
-
-static inline float sw_half_to_float(sw_half_t y)
-{
- union { float f; uint32_t i; } v = { .i = sw_half_to_float_ui(y) };
-
- return v.f;
-}
-
-static inline uint16_t sw_half_from_float_ui(uint32_t ui)
+static inline uint16_t sw_float_to_half_ui(uint32_t ui)
{
int32_t s = (ui >> 16) & 0x8000;
int32_t em = ui & 0x7fffffff;
@@ -1252,469 +1358,331 @@ static inline uint16_t sw_half_from_float_ui(uint32_t ui)
// Overflow: infinity; 143 encodes exponent 16
h = (em >= (143 << 23))? 0x7c00 : h;
- // NOTE: NaN; all types of NaN aree converted to qNaN
+ // NaN; note that all types of NaN are converted to qNaN
h = (em > (255 << 23))? 0x7e00 : h;
return (uint16_t)(s | h);
}
-static inline sw_half_t sw_half_from_float(float i)
+static inline uint32_t sw_half_to_float_ui(uint16_t h)
+{
+ uint32_t s = (unsigned)(h & 0x8000) << 16;
+ int32_t em = h & 0x7fff;
+
+ // Bias exponent and pad mantissa with 0; 112 is relative exponent bias (127-15)
+ int32_t r = (em + (112 << 10)) << 13;
+
+ // Denormal: flush to zero
+ r = (em < (1 << 10))? 0 : r;
+
+ // Infinity/NaN; note that NaN payload is preeserved as a byproduct of unifying inf/nan cases
+ // 112 is an exponent bias fixup; since it was already applied once, applying it twice converts 31 to 255
+ r += (em >= (31 << 10))? (112 << 23) : 0;
+
+ return s | r;
+}
+
+static inline sw_half_t sw_float_to_half(float i)
{
union { float f; uint32_t i; } v;
v.f = i;
- return sw_half_from_float_ui(v.i);
+ return sw_float_to_half_ui(v.i);
}
-// Framebuffer management functions
-//-------------------------------------------------------------------------------------------
-static inline bool sw_framebuffer_load(int w, int h)
+static inline float sw_half_to_float(sw_half_t y)
{
- int size = w*h;
+ union { float f; uint32_t i; } v;
+ v.i = sw_half_to_float_ui(y);
+ return v.f;
+}
- RLSW.framebuffer.pixels = SW_MALLOC(sizeof(sw_pixel_t)*size);
- if (RLSW.framebuffer.pixels == NULL) return false;
+static inline uint8_t sw_expand_1to8(uint32_t v) { return v? 255 : 0; }
+static inline uint8_t sw_expand_2to8(uint32_t v) { return (uint8_t)(v*85); }
+static inline uint8_t sw_expand_3to8(uint32_t v) { return (uint8_t)((v << 5) | (v << 2) | (v >> 1)); }
+static inline uint8_t sw_expand_4to8(uint32_t v) { return (uint8_t)((v << 4) | v); }
+static inline uint8_t sw_expand_5to8(uint32_t v) { return (uint8_t)((v << 3) | (v >> 2)); }
+static inline uint8_t sw_expand_6to8(uint32_t v) { return (uint8_t)((v << 2) | (v >> 4)); }
- RLSW.framebuffer.width = w;
- RLSW.framebuffer.height = h;
- RLSW.framebuffer.allocSz = size;
+static inline uint32_t sw_compress_8to1(uint8_t v) { return v >> 7; }
+static inline uint32_t sw_compress_8to2(uint8_t v) { return v >> 6; }
+static inline uint32_t sw_compress_8to3(uint8_t v) { return v >> 5; }
+static inline uint32_t sw_compress_8to4(uint8_t v) { return v >> 4; }
+static inline uint32_t sw_compress_8to5(uint8_t v) { return v >> 3; }
+static inline uint32_t sw_compress_8to6(uint8_t v) { return v >> 2; }
+
+static inline void sw_color8_to_color(float *SW_RESTRICT dst, const uint8_t *SW_RESTRICT src)
+{
+#if defined(SW_HAS_NEON)
+ uint8x8_t bytes = vreinterpret_u8_u32(vld1_dup_u32((const uint32_t *)src));
+ uint16x8_t words = vmovl_u8(bytes);
+ uint32x4_t dwords = vmovl_u16(vget_low_u16(words));
+ float32x4_t fvals = vmulq_f32(vcvtq_f32_u32(dwords), vdupq_n_f32(SW_INV_255));
+ vst1q_f32(dst, fvals);
+
+#elif defined(SW_HAS_SSE41)
+ __m128i bytes = _mm_loadu_si32(src);
+ __m128 fvals = _mm_mul_ps(_mm_cvtepi32_ps(_mm_cvtepu8_epi32(bytes)), _mm_set1_ps(SW_INV_255));
+ _mm_storeu_ps(dst, fvals);
+
+#elif defined(SW_HAS_SSE2)
+ __m128i zero = _mm_setzero_si128();
+ __m128i bytes = _mm_loadu_si32(src);
+ __m128i words = _mm_unpacklo_epi8(bytes, zero);
+ __m128i dwords = _mm_unpacklo_epi16(words, zero);
+ __m128 fvals = _mm_mul_ps(_mm_cvtepi32_ps(dwords), _mm_set1_ps(SW_INV_255));
+ _mm_storeu_ps(dst, fvals);
+
+#elif defined(SW_HAS_RVV)
+ // TODO: WARNING: Sample code generated by AI, needs testing and review
+ size_t vl = __riscv_vsetvl_e8m1(4); // Set vector length for 8-bit input elements
+ vuint8m1_t vsrc_u8 = __riscv_vle8_v_u8m1(src, vl); // Load 4 unsigned 8-bit integers
+ vuint32m1_t vsrc_u32 = __riscv_vwcvt_xu_u_v_u32m1(vsrc_u8, vl); // Widen to 32-bit unsigned integers
+ vfloat32m1_t vsrc_f32 = __riscv_vfcvt_f_xu_v_f32m1(vsrc_u32, vl); // Convert to float32
+ vfloat32m1_t vnorm = __riscv_vfmul_vf_f32m1(vsrc_f32, SW_INV_255, vl); // Multiply by 1/255.0 to normalize
+ __riscv_vse32_v_f32m1(dst, vnorm, vl); // Store result
+
+#elif SW_USE_COLOR_LUT
+ dst[0] = SW_LUT_UINT8_TO_FLOAT[src[0]];
+ dst[1] = SW_LUT_UINT8_TO_FLOAT[src[1]];
+ dst[2] = SW_LUT_UINT8_TO_FLOAT[src[2]];
+ dst[3] = SW_LUT_UINT8_TO_FLOAT[src[3]];
+
+#else
+ dst[0] = (float)src[0]*SW_INV_255;
+ dst[1] = (float)src[1]*SW_INV_255;
+ dst[2] = (float)src[2]*SW_INV_255;
+ dst[3] = (float)src[3]*SW_INV_255;
+#endif
+}
+
+static inline void sw_color_to_color8(uint8_t *SW_RESTRICT dst, const float *SW_RESTRICT src)
+{
+#if defined(SW_HAS_NEON)
+ float32x4_t fvals = vmulq_f32(vld1q_f32(src), vdupq_n_f32(255.0f));
+ uint32x4_t i32 = vcvtq_u32_f32(fvals);
+ uint16x4_t i16 = vmovn_u32(i32);
+ uint8x8_t i8 = vmovn_u16(vcombine_u16(i16, i16));
+ vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(i8), 0);
+
+#elif defined(SW_HAS_SSE41)
+ __m128 fvals = _mm_mul_ps(_mm_loadu_ps(src), _mm_set1_ps(255.0f));
+ __m128i i32 = _mm_cvttps_epi32(fvals);
+ __m128i i16 = _mm_packus_epi32(i32, i32);
+ __m128i i8 = _mm_packus_epi16(i16, i16);
+ _mm_storeu_si32(dst, i8);
+
+#elif defined(SW_HAS_SSE2)
+ __m128 fvals = _mm_mul_ps(_mm_loadu_ps(src), _mm_set1_ps(255.0f));
+ __m128i i32 = _mm_cvttps_epi32(fvals);
+ __m128i i16 = _mm_packs_epi32(i32, i32);
+ __m128i i8 = _mm_packus_epi16(i16, i16);
+ _mm_storeu_si32(dst, i8);
+
+#elif defined(SW_HAS_RVV)
+ // TODO: WARNING: Sample code generated by AI, needs testing and review
+ // REVIEW: It shouldn't perform so many operations; take inspiration from other versions
+ // NOTE: RVV 1.0 specs define the use of __riscv_ prefix for instrinsic functions
+ size_t vl = __riscv_vsetvl_e32m1(4); // Load up to 4 floats into a vector register
+ vfloat32m1_t vsrc = __riscv_vle32_v_f32m1(src, vl); // Load float32 values
+
+ // Multiply by 255.0f and add 0.5f for rounding
+ vfloat32m1_t vscaled = __riscv_vfmul_vf_f32m1(vsrc, 255.0f, vl);
+ vscaled = __riscv_vfadd_vf_f32m1(vscaled, 0.5f, vl);
+
+ // Convert to unsigned integer (truncate toward zero)
+ vuint32m1_t vu32 = __riscv_vfcvt_xu_f_v_u32m1(vscaled, vl);
+
+ // Narrow from u32 -> u8
+ vuint8m1_t vu8 = __riscv_vnclipu_wx_u8m1(vu32, 0, vl); // Round toward zero
+ __riscv_vse8_v_u8m1(dst, vu8, vl); // Store result
+
+#else
+ dst[0] = (uint8_t)(src[0]*255.0f);
+ dst[1] = (uint8_t)(src[1]*255.0f);
+ dst[2] = (uint8_t)(src[2]*255.0f);
+ dst[3] = (uint8_t)(src[3]*255.0f);
+#endif
+}
+//-------------------------------------------------------------------------------------------
+
+// Object pool functions
+//-------------------------------------------------------------------------------------------
+static bool sw_pool_init(sw_pool_t *pool, int capacity, size_t stride)
+{
+ *pool = (sw_pool_t) { 0 };
+
+ pool->data = SW_CALLOC(capacity, stride);
+ pool->gen = SW_CALLOC(capacity, sizeof(uint8_t));
+ pool->freeList = SW_MALLOC(capacity*sizeof(uint32_t));
+
+ if (!pool->data || !pool->gen || !pool->freeList)
+ {
+ SW_FREE(pool->data);
+ SW_FREE(pool->gen);
+ SW_FREE(pool->freeList);
+ return false;
+ }
+
+ pool->watermark = 1;
+ pool->capacity = capacity;
+ pool->stride = stride;
return true;
}
-static inline bool sw_framebuffer_resize(int w, int h)
+static void sw_pool_destroy(sw_pool_t *pool)
{
- int newSize = w*h;
+ SW_FREE(pool->data);
+ SW_FREE(pool->gen);
+ SW_FREE(pool->freeList);
+ *pool = (sw_pool_t) { 0 };
+}
- if (newSize <= RLSW.framebuffer.allocSz)
+static sw_handle_t sw_pool_alloc(sw_pool_t *pool)
+{
+ uint32_t index;
+
+ if (pool->freeCount > 0)
{
- RLSW.framebuffer.width = w;
- RLSW.framebuffer.height = h;
- return true;
+ index = pool->freeList[--pool->freeCount];
+ }
+ else
+ {
+ if (pool->watermark >= pool->capacity) return SW_HANDLE_NULL;
+ index = (uint32_t)pool->watermark++;
}
- void *newPixels = SW_REALLOC(RLSW.framebuffer.pixels, sizeof(sw_pixel_t)*newSize);
- if (newPixels == NULL) return false;
+ uint8_t ver = ((pool->gen[index] & SW_POOL_SLOT_VER_MASK) + 1) & SW_POOL_SLOT_VER_MASK;
+ if (ver == 0) ver = 1;
+ pool->gen[index] = SW_POOL_SLOT_LIVE | ver;
- RLSW.framebuffer.pixels = newPixels;
+ uint8_t *slot = (uint8_t *)pool->data + index*pool->stride;
+ for (size_t i = 0; i < pool->stride; i++) slot[i] = 0;
- RLSW.framebuffer.width = w;
- RLSW.framebuffer.height = h;
- RLSW.framebuffer.allocSz = newSize;
+ return (sw_handle_t)index;
+}
+static void *sw_pool_get(const sw_pool_t *pool, sw_handle_t handle)
+{
+ if (handle == SW_HANDLE_NULL) return NULL;
+ if ((int)handle >= pool->capacity) return NULL;
+ if (!(pool->gen[handle] & SW_POOL_SLOT_LIVE)) return NULL;
+
+ return (char *)pool->data + handle*pool->stride;
+}
+
+static bool sw_pool_valid(const sw_pool_t *pool, sw_handle_t handle)
+{
+ return sw_pool_get(pool, handle) != NULL;
+}
+
+static bool sw_pool_free(sw_pool_t *pool, sw_handle_t handle)
+{
+ if (!sw_pool_valid(pool, handle)) return false;
+
+ pool->gen[handle] &= SW_POOL_SLOT_VER_MASK; // delete live flag
+ pool->freeList[pool->freeCount++] = handle;
return true;
}
-
-static inline void sw_framebuffer_read_color(float dst[4], const sw_pixel_t *src)
-{
-#if SW_COLOR_IS_PACKED
- SW_COLOR_TYPE pixel = src->color[0];
- dst[0] = SW_TO_FLOAT_R(SW_UNPACK_R(pixel));
- dst[1] = SW_TO_FLOAT_G(SW_UNPACK_G(pixel));
- dst[2] = SW_TO_FLOAT_B(SW_UNPACK_B(pixel));
- dst[3] = 1.0f;
-#else
- sw_float_from_unorm8_simd(dst, src->color);
-#endif
-}
-
-static inline void sw_framebuffer_read_color8(uint8_t dst[4], const sw_pixel_t *src)
-{
-#if SW_COLOR_IS_PACKED
- SW_COLOR_TYPE pixel = src->color[0];
- dst[0] = SW_SCALE_R(SW_UNPACK_R(pixel));
- dst[1] = SW_SCALE_G(SW_UNPACK_G(pixel));
- dst[2] = SW_SCALE_B(SW_UNPACK_B(pixel));
- dst[3] = 255;
-#else
- const SW_COLOR_TYPE *p = src->color;
- dst[0] = p[0];
- dst[1] = p[1];
- dst[2] = p[2];
- dst[3] = p[3];
-#endif
-}
-
-static inline float sw_framebuffer_read_depth(const sw_pixel_t *src)
-{
-#if SW_DEPTH_IS_PACKED
- return src->depth[0]*SW_DEPTH_SCALE;
-#else
- return SW_UNPACK_DEPTH(src->depth)*SW_DEPTH_SCALE;
-#endif
-}
-
-static inline void sw_framebuffer_write_color(sw_pixel_t *dst, const float src[4])
-{
-#if SW_COLOR_IS_PACKED
- dst->color[0] = SW_PACK_COLOR(src[0], src[1], src[2]);
-#else
- sw_float_to_unorm8_simd(dst->color, src);
-#endif
-}
-
-static inline void sw_framebuffer_write_depth(sw_pixel_t *dst, float depth)
-{
- depth = sw_saturate(depth); // REVIEW: An overflow can occur in certain circumstances with clipping, and needs to be reviewed...
-
-#if SW_DEPTH_IS_PACKED
- dst->depth[0] = SW_PACK_DEPTH(depth);
-#else
- dst->depth[0] = SW_PACK_DEPTH_0(depth);
- dst->depth[1] = SW_PACK_DEPTH_1(depth);
- dst->depth[2] = SW_PACK_DEPTH_2(depth);
-#endif
-}
-
-static inline void sw_framebuffer_fill_color(sw_pixel_t *ptr, int size, const SW_COLOR_TYPE color[SW_COLOR_PACK_COMP])
-{
- if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
- {
- int w = RLSW.scMax[0] - RLSW.scMin[0] + 1;
- for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++)
- {
- sw_pixel_t *row = ptr + y*RLSW.framebuffer.width + RLSW.scMin[0];
- for (int x = 0; x < w; x++, row++)
- {
- for (int i = 0; i < SW_COLOR_PACK_COMP; i++) row->color[i] = color[i];
- }
- }
- }
- else
- {
- for (int i = 0; i < size; i++, ptr++)
- {
- for (int j = 0; j < SW_COLOR_PACK_COMP; j++) ptr->color[j] = color[j];
- }
- }
-}
-
-static inline void sw_framebuffer_fill_depth(sw_pixel_t *ptr, int size, const SW_DEPTH_TYPE depth[SW_DEPTH_PACK_COMP])
-{
- if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
- {
- int w = RLSW.scMax[0] - RLSW.scMin[0] + 1;
- for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++)
- {
- sw_pixel_t *row = ptr + y*RLSW.framebuffer.width + RLSW.scMin[0];
- for (int x = 0; x < w; x++, row++)
- {
- for (int i = 0; i < SW_DEPTH_PACK_COMP; i++) row->depth[i] = depth[i];
- }
- }
- }
- else
- {
- for (int i = 0; i < size; i++, ptr++)
- {
- for (int j = 0; j < SW_DEPTH_PACK_COMP; j++) ptr->depth[j] = depth[j];
- }
- }
-}
-
-static inline void sw_framebuffer_fill(sw_pixel_t *ptr, int size, sw_pixel_t value)
-{
- if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
- {
- int w = RLSW.scMax[0] - RLSW.scMin[0] + 1;
- for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++)
- {
- sw_pixel_t *row = ptr + y*RLSW.framebuffer.width + RLSW.scMin[0];
- for (int x = 0; x < w; x++, row++) *row = value;
- }
- }
- else
- {
- for (int i = 0; i < size; i++, ptr++) *ptr = value;
- }
-}
-
-static inline void sw_framebuffer_copy_fast(void* dst)
-{
- int size = RLSW.framebuffer.width*RLSW.framebuffer.height;
- const sw_pixel_t *pixels = RLSW.framebuffer.pixels;
-
-#if SW_COLOR_BUFFER_BITS == 8
- uint8_t *dst8 = (uint8_t*)dst;
- for (int i = 0; i < size; i++) dst8[i] = pixels[i].color[0];
-#elif SW_COLOR_BUFFER_BITS == 16
- uint16_t *dst16 = (uint16_t*)dst;
- for (int i = 0; i < size; i++) dst16[i] = *(uint16_t*)pixels[i].color;
-#else // 32 bits
- uint32_t *dst32 = (uint32_t*)dst;
- #if SW_GL_FRAMEBUFFER_COPY_BGRA
- for (int i = 0; i < size; i++)
- {
- const uint8_t *c = pixels[i].color;
- dst32[i] = (uint32_t)c[2] | ((uint32_t)c[1] << 8) | ((uint32_t)c[0] << 16) | ((uint32_t)c[3] << 24);
- }
- #else // RGBA
- for (int i = 0; i < size; i++) dst32[i] = *(uint32_t*)pixels[i].color;
- #endif
-#endif
-}
-
-#define DEFINE_FRAMEBUFFER_COPY_BEGIN(name, DST_PTR_T) \
-static inline void sw_framebuffer_copy_to_##name(int x, int y, int w, int h, DST_PTR_T *dst) \
-{ \
- const int stride = RLSW.framebuffer.width; \
- const sw_pixel_t *src = RLSW.framebuffer.pixels + (y*stride + x); \
- \
- for (int iy = 0; iy < h; iy++) { \
- const sw_pixel_t *line = src; \
- for (int ix = 0; ix < w; ix++) { \
- uint8_t color[4]; \
- sw_framebuffer_read_color8(color, line); \
-
-#define DEFINE_FRAMEBUFFER_COPY_END() \
- ++line; \
- } \
- src += stride; \
- } \
-}
-
-DEFINE_FRAMEBUFFER_COPY_BEGIN(GRAYSCALE, uint8_t)
-{
- // NTSC grayscale conversion: Y = 0.299R + 0.587G + 0.114B
- uint8_t gray = (uint8_t)((color[0]*299 + color[1]*587 + color[2]*114 + 500)/1000);
- *dst++ = gray;
-}
-DEFINE_FRAMEBUFFER_COPY_END()
-
-DEFINE_FRAMEBUFFER_COPY_BEGIN(GRAYALPHA, uint8_t)
-{
- // Convert RGB to grayscale using NTSC formula
- uint8_t gray = (uint8_t)((color[0]*299 + color[1]*587 + color[2]*114 + 500)/1000);
-
- dst[0] = gray;
- dst[1] = color[3]; // alpha
-
- dst += 2;
-}
-DEFINE_FRAMEBUFFER_COPY_END()
-
-DEFINE_FRAMEBUFFER_COPY_BEGIN(R5G6B5, uint16_t)
-{
- // Convert 8-bit RGB to 5:6:5 format
- uint8_t r5 = (color[0]*31 + 127)/255;
- uint8_t g6 = (color[1]*63 + 127)/255;
- uint8_t b5 = (color[2]*31 + 127)/255;
-
-#if SW_GL_FRAMEBUFFER_COPY_BGRA
- uint16_t rgb565 = (b5 << 11) | (g6 << 5) | r5;
-#else // RGBA
- uint16_t rgb565 = (r5 << 11) | (g6 << 5) | b5;
-#endif
-
- *dst++ = rgb565;
-}
-DEFINE_FRAMEBUFFER_COPY_END()
-
-DEFINE_FRAMEBUFFER_COPY_BEGIN(R8G8B8, uint8_t)
-{
-#if SW_GL_FRAMEBUFFER_COPY_BGRA
- dst[0] = color[2];
- dst[1] = color[1];
- dst[2] = color[0];
-#else // RGBA
- dst[0] = color[0];
- dst[1] = color[1];
- dst[2] = color[2];
-#endif
-
- dst += 3;
-}
-DEFINE_FRAMEBUFFER_COPY_END()
-
-DEFINE_FRAMEBUFFER_COPY_BEGIN(R5G5B5A1, uint16_t)
-{
- uint8_t r5 = (color[0]*31 + 127)/255;
- uint8_t g5 = (color[1]*31 + 127)/255;
- uint8_t b5 = (color[2]*31 + 127)/255;
- uint8_t a1 = (color[3] >= 128)? 1 : 0;
-
-#if SW_GL_FRAMEBUFFER_COPY_BGRA
- uint16_t pixel = (b5 << 11) | (g5 << 6) | (r5 << 1) | a1;
-#else // RGBA
- uint16_t pixel = (r5 << 11) | (g5 << 6) | (b5 << 1) | a1;
-#endif
-
- *dst++ = pixel;
-}
-DEFINE_FRAMEBUFFER_COPY_END()
-
-DEFINE_FRAMEBUFFER_COPY_BEGIN(R4G4B4A4, uint16_t)
-{
- uint8_t r4 = (color[0]*15 + 127)/255;
- uint8_t g4 = (color[1]*15 + 127)/255;
- uint8_t b4 = (color[2]*15 + 127)/255;
- uint8_t a4 = (color[3]*15 + 127)/255;
-
-#if SW_GL_FRAMEBUFFER_COPY_BGRA
- uint16_t pixel = (b4 << 12) | (g4 << 8) | (r4 << 4) | a4;
-#else // RGBA
- uint16_t pixel = (r4 << 12) | (g4 << 8) | (b4 << 4) | a4;
-#endif
-
- *dst++ = pixel;
-}
-DEFINE_FRAMEBUFFER_COPY_END()
-
-DEFINE_FRAMEBUFFER_COPY_BEGIN(R8G8B8A8, uint8_t)
-{
-#if SW_GL_FRAMEBUFFER_COPY_BGRA
- dst[0] = color[2];
- dst[1] = color[1];
- dst[2] = color[0];
-#else // RGBA
- dst[0] = color[0];
- dst[1] = color[1];
- dst[2] = color[2];
-#endif
- dst[3] = color[3];
-
- dst += 4;
-}
-DEFINE_FRAMEBUFFER_COPY_END()
-
-#define DEFINE_FRAMEBUFFER_BLIT_BEGIN(name, DST_PTR_T) \
-static inline void sw_framebuffer_blit_to_##name( \
- int xDst, int yDst, int wDst, int hDst, \
- int xSrc, int ySrc, int wSrc, int hSrc, \
- DST_PTR_T *dst) \
-{ \
- const sw_pixel_t *srcBase = RLSW.framebuffer.pixels; \
- const int fbWidth = RLSW.framebuffer.width; \
- \
- const uint32_t xScale = ((uint32_t)wSrc << 16)/(uint32_t)wDst; \
- const uint32_t yScale = ((uint32_t)hSrc << 16)/(uint32_t)hDst; \
- \
- for (int dy = 0; dy < hDst; dy++) { \
- uint32_t yFix = ((uint32_t)ySrc << 16) + dy*yScale; \
- int sy = yFix >> 16; \
- const sw_pixel_t *srcLine = srcBase + sy*fbWidth + xSrc; \
- \
- const sw_pixel_t *srcPtr = srcLine; \
- for (int dx = 0; dx < wDst; dx++) { \
- uint32_t xFix = dx*xScale; \
- int sx = xFix >> 16; \
- const sw_pixel_t *pixel = srcPtr + sx; \
- uint8_t color[4]; \
- sw_framebuffer_read_color8(color, pixel);
-
-#define DEFINE_FRAMEBUFFER_BLIT_END() \
- } \
- } \
-}
-
-DEFINE_FRAMEBUFFER_BLIT_BEGIN(GRAYSCALE, uint8_t)
-{
- uint8_t gray = (uint8_t)((color[0]*299 + color[1]*587 + color[2]*114 + 500)/1000);
- *dst++ = gray;
-}
-DEFINE_FRAMEBUFFER_BLIT_END()
-
-DEFINE_FRAMEBUFFER_BLIT_BEGIN(GRAYALPHA, uint8_t)
-{
- uint8_t gray = (uint8_t)((color[0]*299 + color[1]*587 + color[2]*114 + 500)/1000);
-
- dst[0] = gray;
- dst[1] = color[3]; // alpha
-
- dst += 2;
-}
-DEFINE_FRAMEBUFFER_BLIT_END()
-
-DEFINE_FRAMEBUFFER_BLIT_BEGIN(R5G6B5, uint16_t)
-{
- uint8_t r5 = (color[0]*31 + 127)/255;
- uint8_t g6 = (color[1]*63 + 127)/255;
- uint8_t b5 = (color[2]*31 + 127)/255;
-
-#if SW_GL_FRAMEBUFFER_COPY_BGRA
- uint16_t rgb565 = (b5 << 11) | (g6 << 5) | r5;
-#else // RGBA
- uint16_t rgb565 = (r5 << 11) | (g6 << 5) | b5;
-#endif
-
- *dst++ = rgb565;
-}
-DEFINE_FRAMEBUFFER_BLIT_END()
-
-DEFINE_FRAMEBUFFER_BLIT_BEGIN(R8G8B8, uint8_t)
-{
-#if SW_GL_FRAMEBUFFER_COPY_BGRA
- dst[0] = color[2];
- dst[1] = color[1];
- dst[2] = color[0];
-#else // RGBA
- dst[0] = color[0];
- dst[1] = color[1];
- dst[2] = color[2];
-#endif
-
- dst += 3;
-}
-DEFINE_FRAMEBUFFER_BLIT_END()
-
-DEFINE_FRAMEBUFFER_BLIT_BEGIN(R5G5B5A1, uint16_t)
-{
- uint8_t r5 = (color[0]*31 + 127)/255;
- uint8_t g5 = (color[1]*31 + 127)/255;
- uint8_t b5 = (color[2]*31 + 127)/255;
- uint8_t a1 = (color[3] >= 128)? 1 : 0;
-
-#if SW_GL_FRAMEBUFFER_COPY_BGRA
- uint16_t pixel = (b5 << 11) | (g5 << 6) | (r5 << 1) | a1;
-#else // RGBA
- uint16_t pixel = (r5 << 11) | (g5 << 6) | (b5 << 1) | a1;
-#endif
-
- *dst++ = pixel;
-}
-DEFINE_FRAMEBUFFER_BLIT_END()
-
-DEFINE_FRAMEBUFFER_BLIT_BEGIN(R4G4B4A4, uint16_t)
-{
- uint8_t r4 = (color[0]*15 + 127)/255;
- uint8_t g4 = (color[1]*15 + 127)/255;
- uint8_t b4 = (color[2]*15 + 127)/255;
- uint8_t a4 = (color[3]*15 + 127)/255;
-
-#if SW_GL_FRAMEBUFFER_COPY_BGRA
- uint16_t pixel = (b4 << 12) | (g4 << 8) | (r4 << 4) | a4;
-#else // RGBA
- uint16_t pixel = (r4 << 12) | (g4 << 8) | (b4 << 4) | a4;
-#endif
-
- *dst++ = pixel;
-}
-DEFINE_FRAMEBUFFER_BLIT_END()
-
-DEFINE_FRAMEBUFFER_BLIT_BEGIN(R8G8B8A8, uint8_t)
-{
-#if SW_GL_FRAMEBUFFER_COPY_BGRA
- dst[0] = color[2];
- dst[1] = color[1];
- dst[2] = color[0];
-#else // RGBA
- dst[0] = color[0];
- dst[1] = color[1];
- dst[2] = color[2];
-#endif
- dst[3] = color[3];
-
- dst += 4;
-}
-DEFINE_FRAMEBUFFER_BLIT_END()
//-------------------------------------------------------------------------------------------
-// Pixel format management functions
+// Validity check helper functions
//-------------------------------------------------------------------------------------------
-static inline int sw_get_pixel_format(SWformat format, SWtype type)
+static inline bool sw_is_texture_valid(sw_handle_t id)
+{
+ return sw_pool_valid(&RLSW.texturePool, id);
+}
+
+static inline bool sw_is_texture_complete(sw_texture_t *tex)
+{
+ return (tex != NULL) && (tex->pixels != NULL);
+}
+
+static inline bool sw_is_texture_filter_valid(int filter)
+{
+ return ((filter == SW_NEAREST) || (filter == SW_LINEAR));
+}
+
+static inline bool sw_is_texture_wrap_valid(int wrap)
+{
+ return ((wrap == SW_REPEAT) || (wrap == SW_CLAMP));
+}
+
+static inline bool sw_is_draw_mode_valid(int mode)
+{
+ bool result = false;
+
+ switch (mode)
+ {
+ case SW_POINTS:
+ case SW_LINES:
+ case SW_TRIANGLES:
+ case SW_QUADS: result = true; break;
+ default: break;
+ }
+
+ return result;
+}
+
+static inline bool sw_is_poly_mode_valid(int mode)
+{
+ bool result = false;
+
+ switch (mode)
+ {
+ case SW_POINT:
+ case SW_LINE:
+ case SW_FILL: result = true; break;
+ default: break;
+ }
+
+ return result;
+}
+
+static inline bool sw_is_face_valid(int face)
+{
+ return (face == SW_FRONT || face == SW_BACK);
+}
+
+static inline bool sw_is_ready_to_render(void)
+{
+ return (swCheckFramebufferStatus() == SW_FRAMEBUFFER_COMPLETE);
+}
+//-------------------------------------------------------------------------------------------
+
+// Pixel management functions
+//-------------------------------------------------------------------------------------------
+static inline int sw_pixel_get_format(SWformat format, SWtype type)
{
int channels = 0;
int bitsPerChannel = 8; // Default: 8 bits per channel
+ // Handle case where format is a depth component
+ if (format == SW_DEPTH_COMPONENT)
+ {
+ switch (type)
+ {
+ case SW_UNSIGNED_BYTE: return SW_PIXELFORMAT_DEPTH_D8;
+ case SW_BYTE: return SW_PIXELFORMAT_DEPTH_D8;
+ case SW_UNSIGNED_SHORT: return SW_PIXELFORMAT_DEPTH_D16;
+ case SW_SHORT: return SW_PIXELFORMAT_DEPTH_D16;
+ case SW_UNSIGNED_INT: return SW_PIXELFORMAT_DEPTH_D32;
+ case SW_INT: return SW_PIXELFORMAT_DEPTH_D32;
+ case SW_FLOAT: return SW_PIXELFORMAT_DEPTH_D32;
+ default: return SW_PIXELFORMAT_UNKNOWN;
+ }
+ }
+
+ // Handle case where the type is a packed color
+ switch (type)
+ {
+ case SW_UNSIGNED_BYTE_3_3_2: return SW_PIXELFORMAT_COLOR_R3G3B2;
+ case SW_UNSIGNED_SHORT_5_6_5: return SW_PIXELFORMAT_COLOR_R5G6B5;
+ case SW_UNSIGNED_SHORT_4_4_4_4: return SW_PIXELFORMAT_COLOR_R4G4B4A4;
+ case SW_UNSIGNED_SHORT_5_5_5_1: return SW_PIXELFORMAT_COLOR_R5G5B5A1;
+ default: break;
+ }
+
// Determine the number of channels (format)
switch (format)
{
@@ -1741,171 +1709,701 @@ static inline int sw_get_pixel_format(SWformat format, SWtype type)
// Map the format and type to the correct internal format
if (bitsPerChannel == 8)
{
- if (channels == 1) return SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
- if (channels == 2) return SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
- if (channels == 3) return SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8;
- if (channels == 4) return SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
+ if (channels == 1) return SW_PIXELFORMAT_COLOR_GRAYSCALE;
+ if (channels == 2) return SW_PIXELFORMAT_COLOR_GRAYALPHA;
+ if (channels == 3) return SW_PIXELFORMAT_COLOR_R8G8B8;
+ if (channels == 4) return SW_PIXELFORMAT_COLOR_R8G8B8A8;
}
else if (bitsPerChannel == 16)
{
- if (channels == 1) return SW_PIXELFORMAT_UNCOMPRESSED_R16;
- if (channels == 3) return SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16;
- if (channels == 4) return SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16;
+ if (channels == 1) return SW_PIXELFORMAT_COLOR_R16;
+ if (channels == 3) return SW_PIXELFORMAT_COLOR_R16G16B16;
+ if (channels == 4) return SW_PIXELFORMAT_COLOR_R16G16B16A16;
}
else if (bitsPerChannel == 32)
{
- if (channels == 1) return SW_PIXELFORMAT_UNCOMPRESSED_R32;
- if (channels == 3) return SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32;
- if (channels == 4) return SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32;
+ if (channels == 1) return SW_PIXELFORMAT_COLOR_R32;
+ if (channels == 3) return SW_PIXELFORMAT_COLOR_R32G32B32;
+ if (channels == 4) return SW_PIXELFORMAT_COLOR_R32G32B32A32;
}
return SW_PIXELFORMAT_UNKNOWN;
}
-static inline void sw_get_pixel(uint8_t *color, const void *pixels, uint32_t offset, sw_pixelformat_t format)
+static inline bool sw_pixel_is_depth_format(sw_pixelformat_t format)
{
switch (format)
{
- case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
- {
- uint8_t gray = ((const uint8_t*)pixels)[offset];
- color[0] = gray;
- color[1] = gray;
- color[2] = gray;
- color[3] = 255;
- break;
- }
- case SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
- {
- const uint8_t *src = &((const uint8_t*)pixels)[offset*2];
- color[0] = src[0];
- color[1] = src[0];
- color[2] = src[0];
- color[3] = src[1];
- break;
- }
- case SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5:
- {
- uint16_t pixel = ((const uint16_t*)pixels)[offset];
- color[0] = ((pixel >> 11) & 0x1F)*255/31; // R (5 bits)
- color[1] = ((pixel >> 5) & 0x3F)*255/63; // G (6 bits)
- color[2] = (pixel & 0x1F)*255/31; // B (5 bits)
- color[3] = 255;
- break;
- }
- case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8:
- {
- const uint8_t *src = &((const uint8_t*)pixels)[offset*3];
- color[0] = src[0];
- color[1] = src[1];
- color[2] = src[2];
- color[3] = 255;
- break;
- }
- case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
- {
- uint16_t pixel = ((const uint16_t*)pixels)[offset];
- color[0] = ((pixel >> 11) & 0x1F)*255/31; // R (5 bits)
- color[1] = ((pixel >> 6) & 0x1F)*255/31; // G (5 bits)
- color[2] = ((pixel >> 1) & 0x1F)*255/31; // B (5 bits)
- color[3] = (pixel & 0x01)*255; // A (1 bit)
- break;
- }
- case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
- {
- uint16_t pixel = ((const uint16_t*)pixels)[offset];
- color[0] = ((pixel >> 12) & 0x0F)*255/15; // R (4 bits)
- color[1] = ((pixel >> 8) & 0x0F)*255/15; // G (4 bits)
- color[2] = ((pixel >> 4) & 0x0F)*255/15; // B (4 bits)
- color[3] = (pixel & 0x0F)*255/15; // A (4 bits)
- break;
- }
- case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
- {
- const uint8_t *src = &((const uint8_t*)pixels)[offset*4];
- color[0] = src[0];
- color[1] = src[1];
- color[2] = src[2];
- color[3] = src[3];
- break;
- }
- case SW_PIXELFORMAT_UNCOMPRESSED_R32:
- {
- float val = ((const float*)pixels)[offset];
- uint8_t gray = (uint8_t)(val*255.0f);
- color[0] = gray;
- color[1] = gray;
- color[2] = gray;
- color[3] = 255;
- break;
- }
- case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32:
- {
- const float *src = &((const float*)pixels)[offset*3];
- color[0] = (uint8_t)(src[0]*255.0f);
- color[1] = (uint8_t)(src[1]*255.0f);
- color[2] = (uint8_t)(src[2]*255.0f);
- color[3] = 255;
- break;
- }
- case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
- {
- const float *src = &((const float*)pixels)[offset*4];
- color[0] = (uint8_t)(src[0]*255.0f);
- color[1] = (uint8_t)(src[1]*255.0f);
- color[2] = (uint8_t)(src[2]*255.0f);
- color[3] = (uint8_t)(src[3]*255.0f);
- break;
- }
- case SW_PIXELFORMAT_UNCOMPRESSED_R16:
- {
- uint16_t val = ((const uint16_t*)pixels)[offset];
- uint8_t gray = sw_half_to_float(val)*SW_INV_255;
- color[0] = gray;
- color[1] = gray;
- color[2] = gray;
- color[3] = 255;
- break;
- }
- case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16:
- {
- const uint16_t *src = &((const uint16_t*)pixels)[offset*3];
- color[0] = sw_half_to_float(src[0])*SW_INV_255;
- color[1] = sw_half_to_float(src[1])*SW_INV_255;
- color[2] = sw_half_to_float(src[2])*SW_INV_255;
- color[3] = 255;
- break;
- }
- case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:
- {
- const uint16_t *src = &((const uint16_t*)pixels)[offset*4];
- color[0] = sw_half_to_float(src[0])*SW_INV_255;
- color[1] = sw_half_to_float(src[1])*SW_INV_255;
- color[2] = sw_half_to_float(src[2])*SW_INV_255;
- color[3] = sw_half_to_float(src[3])*SW_INV_255;
- break;
- }
+ case SW_PIXELFORMAT_DEPTH_D8:
+ case SW_PIXELFORMAT_DEPTH_D16:
+ case SW_PIXELFORMAT_DEPTH_D32: return true;
+ default: break;
+ }
+
+ return false;
+}
+
+static inline void sw_pixel_read_color8_GRAYSCALE(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ uint8_t gray = ((const uint8_t *)pixels)[offset];
+ color[0] = gray;
+ color[1] = gray;
+ color[2] = gray;
+ color[3] = 255;
+}
+
+static inline void sw_pixel_read_color8_GRAYALPHA(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ const uint8_t *src = &((const uint8_t *)pixels)[offset*2];
+ color[0] = src[0];
+ color[1] = src[0];
+ color[2] = src[0];
+ color[3] = src[1];
+}
+
+static inline void sw_pixel_read_color8_R3G3B2(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ uint8_t pixel = ((const uint8_t *)pixels)[offset];
+ color[0] = sw_expand_3to8((pixel >> 5) & 0x07);
+ color[1] = sw_expand_3to8((pixel >> 2) & 0x07);
+ color[2] = sw_expand_2to8( pixel & 0x03);
+ color[3] = 255;
+}
+
+static inline void sw_pixel_read_color8_R5G6B5(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ uint16_t pixel = ((const uint16_t *)pixels)[offset];
+ color[0] = sw_expand_5to8((pixel >> 11) & 0x1F);
+ color[1] = sw_expand_6to8((pixel >> 5) & 0x3F);
+ color[2] = sw_expand_5to8( pixel & 0x1F);
+ color[3] = 255;
+}
+
+static inline void sw_pixel_read_color8_R8G8B8(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ const uint8_t *src = &((const uint8_t *)pixels)[offset*3];
+ color[0] = src[0];
+ color[1] = src[1];
+ color[2] = src[2];
+ color[3] = 255;
+}
+
+static inline void sw_pixel_read_color8_R5G5B5A1(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ uint16_t pixel = ((const uint16_t *)pixels)[offset];
+ color[0] = sw_expand_5to8((pixel >> 11) & 0x1F);
+ color[1] = sw_expand_5to8((pixel >> 6) & 0x1F);
+ color[2] = sw_expand_5to8((pixel >> 1) & 0x1F);
+ color[3] = sw_expand_1to8( pixel & 0x01);
+}
+
+static inline void sw_pixel_read_color8_R4G4B4A4(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ uint16_t pixel = ((const uint16_t *)pixels)[offset];
+ color[0] = sw_expand_4to8((pixel >> 12) & 0x0F);
+ color[1] = sw_expand_4to8((pixel >> 8) & 0x0F);
+ color[2] = sw_expand_4to8((pixel >> 4) & 0x0F);
+ color[3] = sw_expand_4to8( pixel & 0x0F);
+}
+
+static inline void sw_pixel_read_color8_R8G8B8A8(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ const uint8_t *src = &((const uint8_t *)pixels)[offset*4];
+ color[0] = src[0];
+ color[1] = src[1];
+ color[2] = src[2];
+ color[3] = src[3];
+}
+
+static inline void sw_pixel_read_color8_R32(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ uint8_t gray = (uint8_t)(((const float *)pixels)[offset]*255.0f);
+ color[0] = gray;
+ color[1] = gray;
+ color[2] = gray;
+ color[3] = 255;
+}
+
+static inline void sw_pixel_read_color8_R32G32B32(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ const float *src = &((const float *)pixels)[offset*3];
+ color[0] = (uint8_t)(src[0]*255.0f);
+ color[1] = (uint8_t)(src[1]*255.0f);
+ color[2] = (uint8_t)(src[2]*255.0f);
+ color[3] = 255;
+}
+
+static inline void sw_pixel_read_color8_R32G32B32A32(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ const float *src = &((const float *)pixels)[offset*4];
+ color[0] = (uint8_t)(src[0]*255.0f);
+ color[1] = (uint8_t)(src[1]*255.0f);
+ color[2] = (uint8_t)(src[2]*255.0f);
+ color[3] = (uint8_t)(src[3]*255.0f);
+}
+
+static inline void sw_pixel_read_color8_R16(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ uint8_t gray = (uint8_t)(sw_half_to_float(((const uint16_t *)pixels)[offset])*255.0f);
+ color[0] = gray;
+ color[1] = gray;
+ color[2] = gray;
+ color[3] = 255;
+}
+
+static inline void sw_pixel_read_color8_R16G16B16(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ const uint16_t *src = &((const uint16_t *)pixels)[offset*3];
+ color[0] = (uint8_t)(sw_half_to_float(src[0])*255.0f);
+ color[1] = (uint8_t)(sw_half_to_float(src[1])*255.0f);
+ color[2] = (uint8_t)(sw_half_to_float(src[2])*255.0f);
+ color[3] = 255;
+}
+
+static inline void sw_pixel_read_color8_R16G16B16A16(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ const uint16_t *src = &((const uint16_t *)pixels)[offset*4];
+ color[0] = (uint8_t)(sw_half_to_float(src[0])*255.0f);
+ color[1] = (uint8_t)(sw_half_to_float(src[1])*255.0f);
+ color[2] = (uint8_t)(sw_half_to_float(src[2])*255.0f);
+ color[3] = (uint8_t)(sw_half_to_float(src[3])*255.0f);
+}
+
+static inline sw_pixel_read_color8_f sw_pixel_get_read_color8_func(sw_pixelformat_t format)
+{
+ switch (format)
+ {
+ case SW_PIXELFORMAT_COLOR_GRAYSCALE: return sw_pixel_read_color8_GRAYSCALE;
+ case SW_PIXELFORMAT_COLOR_GRAYALPHA: return sw_pixel_read_color8_GRAYALPHA;
+ case SW_PIXELFORMAT_COLOR_R3G3B2: return sw_pixel_read_color8_R3G3B2;
+ case SW_PIXELFORMAT_COLOR_R5G6B5: return sw_pixel_read_color8_R5G6B5;
+ case SW_PIXELFORMAT_COLOR_R8G8B8: return sw_pixel_read_color8_R8G8B8;
+ case SW_PIXELFORMAT_COLOR_R5G5B5A1: return sw_pixel_read_color8_R5G5B5A1;
+ case SW_PIXELFORMAT_COLOR_R4G4B4A4: return sw_pixel_read_color8_R4G4B4A4;
+ case SW_PIXELFORMAT_COLOR_R8G8B8A8: return sw_pixel_read_color8_R8G8B8A8;
+ case SW_PIXELFORMAT_COLOR_R32: return sw_pixel_read_color8_R32;
+ case SW_PIXELFORMAT_COLOR_R32G32B32: return sw_pixel_read_color8_R32G32B32;
+ case SW_PIXELFORMAT_COLOR_R32G32B32A32: return sw_pixel_read_color8_R32G32B32A32;
+ case SW_PIXELFORMAT_COLOR_R16: return sw_pixel_read_color8_R16;
+ case SW_PIXELFORMAT_COLOR_R16G16B16: return sw_pixel_read_color8_R16G16B16;
+ case SW_PIXELFORMAT_COLOR_R16G16B16A16: return sw_pixel_read_color8_R16G16B16A16;
+
case SW_PIXELFORMAT_UNKNOWN:
- default:
+ case SW_PIXELFORMAT_DEPTH_D8:
+ case SW_PIXELFORMAT_DEPTH_D16:
+ case SW_PIXELFORMAT_DEPTH_D32:
+ case SW_PIXELFORMAT_COUNT:
+ default: break;
+ }
+
+ return NULL;
+}
+
+static inline void sw_pixel_write_color8_GRAYSCALE(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ ((uint8_t *)pixels)[offset] = sw_luminance8(color);
+}
+
+static inline void sw_pixel_write_color8_GRAYALPHA(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ uint8_t *dst = &((uint8_t *)pixels)[offset*2];
+ dst[0] = sw_luminance8(color);
+ dst[1] = color[3];
+}
+
+static inline void sw_pixel_write_color8_R3G3B2(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ uint8_t pixel = (sw_compress_8to3(color[0]) << 5)
+ | (sw_compress_8to3(color[1]) << 2)
+ | sw_compress_8to2(color[2]);
+ ((uint8_t *)pixels)[offset] = pixel;
+}
+
+static inline void sw_pixel_write_color8_R5G6B5(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ uint16_t pixel = (sw_compress_8to5(color[0]) << 11)
+ | (sw_compress_8to6(color[1]) << 5)
+ | sw_compress_8to5(color[2]);
+ ((uint16_t *)pixels)[offset] = pixel;
+}
+
+static inline void sw_pixel_write_color8_R8G8B8(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ uint8_t *dst = &((uint8_t *)pixels)[offset*3];
+ dst[0] = color[0];
+ dst[1] = color[1];
+ dst[2] = color[2];
+}
+
+static inline void sw_pixel_write_color8_R5G5B5A1(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ uint16_t pixel = (sw_compress_8to5(color[0]) << 11)
+ | (sw_compress_8to5(color[1]) << 6)
+ | (sw_compress_8to5(color[2]) << 1)
+ | sw_compress_8to1(color[3]);
+ ((uint16_t *)pixels)[offset] = pixel;
+}
+
+static inline void sw_pixel_write_color8_R4G4B4A4(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ uint16_t pixel = (sw_compress_8to4(color[0]) << 12)
+ | (sw_compress_8to4(color[1]) << 8)
+ | (sw_compress_8to4(color[2]) << 4)
+ | sw_compress_8to4(color[3]);
+ ((uint16_t *)pixels)[offset] = pixel;
+}
+
+static inline void sw_pixel_write_color8_R8G8B8A8(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ uint8_t *dst = &((uint8_t *)pixels)[offset*4];
+ dst[0] = color[0];
+ dst[1] = color[1];
+ dst[2] = color[2];
+ dst[3] = color[3];
+}
+
+static inline void sw_pixel_write_color8_R32(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ ((float *)pixels)[offset] = sw_luminance8(color)*SW_INV_255;
+}
+
+static inline void sw_pixel_write_color8_R32G32B32(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ float *dst = &((float *)pixels)[offset*3];
+ dst[0] = color[0]*SW_INV_255;
+ dst[1] = color[1]*SW_INV_255;
+ dst[2] = color[2]*SW_INV_255;
+}
+
+static inline void sw_pixel_write_color8_R32G32B32A32(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ float *dst = &((float *)pixels)[offset*4];
+ dst[0] = color[0]*SW_INV_255;
+ dst[1] = color[1]*SW_INV_255;
+ dst[2] = color[2]*SW_INV_255;
+ dst[3] = color[3]*SW_INV_255;
+}
+
+static inline void sw_pixel_write_color8_R16(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ ((uint16_t *)pixels)[offset] = sw_float_to_half(sw_luminance8(color)*SW_INV_255);
+}
+
+static inline void sw_pixel_write_color8_R16G16B16(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ uint16_t *dst = &((uint16_t *)pixels)[offset*3];
+ dst[0] = sw_float_to_half(color[0]*SW_INV_255);
+ dst[1] = sw_float_to_half(color[1]*SW_INV_255);
+ dst[2] = sw_float_to_half(color[2]*SW_INV_255);
+}
+
+static inline void sw_pixel_write_color8_R16G16B16A16(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
+{
+ uint16_t *dst = &((uint16_t *)pixels)[offset*4];
+ dst[0] = sw_float_to_half(color[0]*SW_INV_255);
+ dst[1] = sw_float_to_half(color[1]*SW_INV_255);
+ dst[2] = sw_float_to_half(color[2]*SW_INV_255);
+ dst[3] = sw_float_to_half(color[3]*SW_INV_255);
+}
+
+static inline sw_pixel_write_color8_f sw_pixel_get_write_color8_func(sw_pixelformat_t format)
+{
+ switch (format)
+ {
+ case SW_PIXELFORMAT_COLOR_GRAYSCALE: return sw_pixel_write_color8_GRAYSCALE;
+ case SW_PIXELFORMAT_COLOR_GRAYALPHA: return sw_pixel_write_color8_GRAYALPHA;
+ case SW_PIXELFORMAT_COLOR_R3G3B2: return sw_pixel_write_color8_R3G3B2;
+ case SW_PIXELFORMAT_COLOR_R5G6B5: return sw_pixel_write_color8_R5G6B5;
+ case SW_PIXELFORMAT_COLOR_R8G8B8: return sw_pixel_write_color8_R8G8B8;
+ case SW_PIXELFORMAT_COLOR_R5G5B5A1: return sw_pixel_write_color8_R5G5B5A1;
+ case SW_PIXELFORMAT_COLOR_R4G4B4A4: return sw_pixel_write_color8_R4G4B4A4;
+ case SW_PIXELFORMAT_COLOR_R8G8B8A8: return sw_pixel_write_color8_R8G8B8A8;
+ case SW_PIXELFORMAT_COLOR_R32: return sw_pixel_write_color8_R32;
+ case SW_PIXELFORMAT_COLOR_R32G32B32: return sw_pixel_write_color8_R32G32B32;
+ case SW_PIXELFORMAT_COLOR_R32G32B32A32: return sw_pixel_write_color8_R32G32B32A32;
+ case SW_PIXELFORMAT_COLOR_R16: return sw_pixel_write_color8_R16;
+ case SW_PIXELFORMAT_COLOR_R16G16B16: return sw_pixel_write_color8_R16G16B16;
+ case SW_PIXELFORMAT_COLOR_R16G16B16A16: return sw_pixel_write_color8_R16G16B16A16;
+
+ case SW_PIXELFORMAT_UNKNOWN:
+ case SW_PIXELFORMAT_DEPTH_D8:
+ case SW_PIXELFORMAT_DEPTH_D16:
+ case SW_PIXELFORMAT_DEPTH_D32:
+ case SW_PIXELFORMAT_COUNT:
+ default: break;
+ }
+
+ return NULL;
+}
+
+static inline void sw_pixel_read_color_GRAYSCALE(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ float gray = ((const uint8_t *)pixels)[offset]*SW_INV_255;
+ color[0] = gray;
+ color[1] = gray;
+ color[2] = gray;
+ color[3] = 1.0f;
+}
+
+static inline void sw_pixel_read_color_GRAYALPHA(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ const uint8_t *src = &((const uint8_t *)pixels)[offset*2];
+ float gray = src[0]*SW_INV_255;
+ color[0] = gray;
+ color[1] = gray;
+ color[2] = gray;
+ color[3] = src[1]*SW_INV_255;
+}
+
+static inline void sw_pixel_read_color_R3G3B2(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ uint8_t unpack[4];
+ sw_pixel_read_color8_R3G3B2(unpack, pixels, offset);
+ sw_color8_to_color(color, unpack);
+}
+
+static inline void sw_pixel_read_color_R5G6B5(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ uint8_t unpack[4];
+ sw_pixel_read_color8_R5G6B5(unpack, pixels, offset);
+ sw_color8_to_color(color, unpack);
+}
+
+static inline void sw_pixel_read_color_R8G8B8(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ uint8_t unpack[4];
+ sw_pixel_read_color8_R8G8B8(unpack, pixels, offset);
+ sw_color8_to_color(color, unpack);
+}
+
+static inline void sw_pixel_read_color_R5G5B5A1(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ uint8_t unpack[4];
+ sw_pixel_read_color8_R5G5B5A1(unpack, pixels, offset);
+ sw_color8_to_color(color, unpack);
+}
+
+static inline void sw_pixel_read_color_R4G4B4A4(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ uint8_t unpack[4];
+ sw_pixel_read_color8_R4G4B4A4(unpack, pixels, offset);
+ sw_color8_to_color(color, unpack);
+}
+
+static inline void sw_pixel_read_color_R8G8B8A8(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ sw_color8_to_color(color, &((const uint8_t *)pixels)[offset*4]);
+}
+
+static inline void sw_pixel_read_color_R32(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ float val = ((const float *)pixels)[offset];
+ color[0] = val;
+ color[1] = val;
+ color[2] = val;
+ color[3] = 1.0f;
+}
+
+static inline void sw_pixel_read_color_R32G32B32(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ const float *src = &((const float *)pixels)[offset*3];
+ color[0] = src[0];
+ color[1] = src[1];
+ color[2] = src[2];
+ color[3] = 1.0f;
+}
+
+static inline void sw_pixel_read_color_R32G32B32A32(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ const float *src = &((const float *)pixels)[offset*4];
+ color[0] = src[0];
+ color[1] = src[1];
+ color[2] = src[2];
+ color[3] = src[3];
+}
+
+static inline void sw_pixel_read_color_R16(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ float val = sw_half_to_float(((const uint16_t *)pixels)[offset]);
+ color[0] = val;
+ color[1] = val;
+ color[2] = val;
+ color[3] = 1.0f;
+}
+
+static inline void sw_pixel_read_color_R16G16B16(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ const uint16_t *src = &((const uint16_t *)pixels)[offset*3];
+ color[0] = sw_half_to_float(src[0]);
+ color[1] = sw_half_to_float(src[1]);
+ color[2] = sw_half_to_float(src[2]);
+ color[3] = 1.0f;
+}
+
+static inline void sw_pixel_read_color_R16G16B16A16(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
+{
+ const uint16_t *src = &((const uint16_t *)pixels)[offset*4];
+ color[0] = sw_half_to_float(src[0]);
+ color[1] = sw_half_to_float(src[1]);
+ color[2] = sw_half_to_float(src[2]);
+ color[3] = sw_half_to_float(src[3]);
+}
+
+static inline sw_pixel_read_color_f sw_pixel_get_read_color_func(sw_pixelformat_t format)
+{
+ switch (format)
+ {
+ case SW_PIXELFORMAT_COLOR_GRAYSCALE: return sw_pixel_read_color_GRAYSCALE;
+ case SW_PIXELFORMAT_COLOR_GRAYALPHA: return sw_pixel_read_color_GRAYALPHA;
+ case SW_PIXELFORMAT_COLOR_R3G3B2: return sw_pixel_read_color_R3G3B2;
+ case SW_PIXELFORMAT_COLOR_R5G6B5: return sw_pixel_read_color_R5G6B5;
+ case SW_PIXELFORMAT_COLOR_R8G8B8: return sw_pixel_read_color_R8G8B8;
+ case SW_PIXELFORMAT_COLOR_R5G5B5A1: return sw_pixel_read_color_R5G5B5A1;
+ case SW_PIXELFORMAT_COLOR_R4G4B4A4: return sw_pixel_read_color_R4G4B4A4;
+ case SW_PIXELFORMAT_COLOR_R8G8B8A8: return sw_pixel_read_color_R8G8B8A8;
+ case SW_PIXELFORMAT_COLOR_R32: return sw_pixel_read_color_R32;
+ case SW_PIXELFORMAT_COLOR_R32G32B32: return sw_pixel_read_color_R32G32B32;
+ case SW_PIXELFORMAT_COLOR_R32G32B32A32: return sw_pixel_read_color_R32G32B32A32;
+ case SW_PIXELFORMAT_COLOR_R16: return sw_pixel_read_color_R16;
+ case SW_PIXELFORMAT_COLOR_R16G16B16: return sw_pixel_read_color_R16G16B16;
+ case SW_PIXELFORMAT_COLOR_R16G16B16A16: return sw_pixel_read_color_R16G16B16A16;
+
+ case SW_PIXELFORMAT_UNKNOWN:
+ case SW_PIXELFORMAT_DEPTH_D8:
+ case SW_PIXELFORMAT_DEPTH_D16:
+ case SW_PIXELFORMAT_DEPTH_D32:
+ case SW_PIXELFORMAT_COUNT:
+ default: break;
+ }
+
+ return NULL;
+}
+
+static inline void sw_pixel_write_color_GRAYSCALE(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ ((uint8_t *)pixels)[offset] = (uint8_t)(sw_luminance(color)*255.0f);
+}
+
+static inline void sw_pixel_write_color_GRAYALPHA(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ uint8_t *dst = &((uint8_t *)pixels)[offset*2];
+ dst[0] = (uint8_t)(sw_luminance(color)*255.0f);
+ dst[1] = (uint8_t)(color[3]*255.0f);
+}
+
+static inline void sw_pixel_write_color_R3G3B2(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ uint8_t color8[4];
+ sw_color_to_color8(color8, color);
+ sw_pixel_write_color8_R3G3B2(pixels, color8, offset);
+}
+
+static inline void sw_pixel_write_color_R5G6B5(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ uint8_t color8[4];
+ sw_color_to_color8(color8, color);
+ sw_pixel_write_color8_R5G6B5(pixels, color8, offset);
+}
+
+static inline void sw_pixel_write_color_R8G8B8(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ uint8_t color8[4];
+ sw_color_to_color8(color8, color);
+ sw_pixel_write_color8_R8G8B8(pixels, color8, offset);
+}
+
+static inline void sw_pixel_write_color_R5G5B5A1(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ uint8_t color8[4];
+ sw_color_to_color8(color8, color);
+ sw_pixel_write_color8_R5G5B5A1(pixels, color8, offset);
+}
+
+static inline void sw_pixel_write_color_R4G4B4A4(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ uint8_t color8[4];
+ sw_color_to_color8(color8, color);
+ sw_pixel_write_color8_R4G4B4A4(pixels, color8, offset);
+}
+
+static inline void sw_pixel_write_color_R8G8B8A8(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ sw_color_to_color8(&((uint8_t *)pixels)[offset*4], color);
+}
+
+static inline void sw_pixel_write_color_R32(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ ((float *)pixels)[offset] = sw_luminance(color);
+}
+
+static inline void sw_pixel_write_color_R32G32B32(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ float *dst = &((float *)pixels)[offset*3];
+ dst[0] = color[0];
+ dst[1] = color[1];
+ dst[2] = color[2];
+}
+
+static inline void sw_pixel_write_color_R32G32B32A32(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ float *dst = &((float *)pixels)[offset*4];
+ dst[0] = color[0];
+ dst[1] = color[1];
+ dst[2] = color[2];
+ dst[3] = color[3];
+}
+
+static inline void sw_pixel_write_color_R16(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ ((uint16_t *)pixels)[offset] = sw_float_to_half(sw_luminance(color));
+}
+
+static inline void sw_pixel_write_color_R16G16B16(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ uint16_t *dst = &((uint16_t *)pixels)[offset*3];
+ dst[0] = sw_float_to_half(color[0]);
+ dst[1] = sw_float_to_half(color[1]);
+ dst[2] = sw_float_to_half(color[2]);
+}
+
+static inline void sw_pixel_write_color_R16G16B16A16(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
+{
+ uint16_t *dst = &((uint16_t *)pixels)[offset*4];
+ dst[0] = sw_float_to_half(color[0]);
+ dst[1] = sw_float_to_half(color[1]);
+ dst[2] = sw_float_to_half(color[2]);
+ dst[3] = sw_float_to_half(color[3]);
+}
+
+static inline sw_pixel_write_color_f sw_pixel_get_write_color_func(sw_pixelformat_t format)
+{
+ switch (format)
+ {
+ case SW_PIXELFORMAT_COLOR_GRAYSCALE: return sw_pixel_write_color_GRAYSCALE;
+ case SW_PIXELFORMAT_COLOR_GRAYALPHA: return sw_pixel_write_color_GRAYALPHA;
+ case SW_PIXELFORMAT_COLOR_R3G3B2: return sw_pixel_write_color_R3G3B2;
+ case SW_PIXELFORMAT_COLOR_R5G6B5: return sw_pixel_write_color_R5G6B5;
+ case SW_PIXELFORMAT_COLOR_R8G8B8: return sw_pixel_write_color_R8G8B8;
+ case SW_PIXELFORMAT_COLOR_R5G5B5A1: return sw_pixel_write_color_R5G5B5A1;
+ case SW_PIXELFORMAT_COLOR_R4G4B4A4: return sw_pixel_write_color_R4G4B4A4;
+ case SW_PIXELFORMAT_COLOR_R8G8B8A8: return sw_pixel_write_color_R8G8B8A8;
+ case SW_PIXELFORMAT_COLOR_R32: return sw_pixel_write_color_R32;
+ case SW_PIXELFORMAT_COLOR_R32G32B32: return sw_pixel_write_color_R32G32B32;
+ case SW_PIXELFORMAT_COLOR_R32G32B32A32: return sw_pixel_write_color_R32G32B32A32;
+ case SW_PIXELFORMAT_COLOR_R16: return sw_pixel_write_color_R16;
+ case SW_PIXELFORMAT_COLOR_R16G16B16: return sw_pixel_write_color_R16G16B16;
+ case SW_PIXELFORMAT_COLOR_R16G16B16A16: return sw_pixel_write_color_R16G16B16A16;
+
+ case SW_PIXELFORMAT_UNKNOWN:
+ case SW_PIXELFORMAT_DEPTH_D8:
+ case SW_PIXELFORMAT_DEPTH_D16:
+ case SW_PIXELFORMAT_DEPTH_D32:
+ case SW_PIXELFORMAT_COUNT:
+ default: break;
+ }
+
+ return NULL;
+}
+
+static inline float sw_pixel_read_depth_D8(const void *pixels, uint32_t offset)
+{
+ return (float)((uint8_t *)pixels)[offset]*SW_INV_255;
+}
+
+static inline float sw_pixel_read_depth_D16(const void *pixels, uint32_t offset)
+{
+ return (float)((uint16_t *)pixels)[offset]/UINT16_MAX;
+}
+
+static inline float sw_pixel_read_depth_D32(const void *pixels, uint32_t offset)
+{
+ return ((float *)pixels)[offset];
+}
+
+static inline void sw_pixel_write_depth_D8(void *pixels, float depth, uint32_t offset)
+{
+ ((uint8_t *)pixels)[offset] = (uint8_t)(depth*UINT8_MAX);
+}
+
+static inline void sw_pixel_write_depth_D16(void *pixels, float depth, uint32_t offset)
+{
+ ((uint16_t *)pixels)[offset] = (uint16_t)(depth*UINT16_MAX);
+}
+
+static inline void sw_pixel_write_depth_D32(void *pixels, float depth, uint32_t offset)
+{
+ ((float *)pixels)[offset] = depth;
+}
+//-------------------------------------------------------------------------------------------
+
+// Texture functionality
+//-------------------------------------------------------------------------------------------
+static inline bool sw_texture_alloc(sw_texture_t *texture, const void *data, int w, int h, sw_pixelformat_t format)
+{
+ bool isDepth = sw_pixel_is_depth_format(format);
+ int bpp = SW_PIXELFORMAT_SIZE[format];
+ int newSize = w*h*bpp;
+
+ if (newSize > texture->allocSz)
+ {
+ void *ptr = SW_REALLOC(texture->pixels, newSize);
+ if (!ptr) { RLSW.errCode = SW_OUT_OF_MEMORY; return false; }
+ texture->allocSz = newSize;
+ texture->pixels = ptr;
+ }
+
+ uint8_t *dst = texture->pixels;
+ const uint8_t *src = data;
+
+ sw_pixel_read_color8_f readColor8 = NULL;
+ sw_pixel_read_color_f readColor = NULL;
+ if (!isDepth) {
+ readColor8 = sw_pixel_get_read_color8_func(format);
+ readColor = sw_pixel_get_read_color_func(format);
+ }
+
+ sw_pixel_alpha_t pixelAlpha = SW_PIXELFORMAT_ALPHA[format];
+ bool alphaFound = !data; // No data: assume transparency
+
+ if (data && !isDepth)
+ {
+ for (int i = 0; i < newSize; i++) dst[i] = src[i];
+
+ if (pixelAlpha != SW_PIXEL_ALPHA_NONE)
{
- color[0] = 0;
- color[1] = 0;
- color[2] = 0;
- color[3] = 0;
- break;
+ for (int i = 0; i < newSize; i += bpp)
+ {
+ uint8_t color[4] = { 0 };
+ readColor8(color, &src[i], 0);
+ if (color[3] < 255) { alphaFound = true; break; }
+ }
}
}
-}
-//-------------------------------------------------------------------------------------------
+ else
+ {
+ for (int i = 0; i < newSize; i++) dst[i] = 0;
+ }
-// Texture sampling functionality
-//-------------------------------------------------------------------------------------------
-static inline void sw_texture_fetch(float* color, const sw_texture_t* tex, int x, int y)
+ texture->readColor8 = readColor8;
+ texture->readColor = readColor;
+ texture->format = format;
+ texture->alpha = alphaFound? pixelAlpha : SW_PIXEL_ALPHA_NONE;
+ texture->width = w;
+ texture->height = h;
+ texture->wMinus1 = w - 1;
+ texture->hMinus1 = h - 1;
+ texture->tx = 1.0f/w;
+ texture->ty = 1.0f/h;
+
+ return true;
+}
+
+static inline void sw_texture_free(sw_texture_t *texture)
{
- sw_float_from_unorm8_simd(color, &tex->pixels[4*(y*tex->width + x)]);
+ SW_FREE(texture->pixels);
}
-static inline void sw_texture_sample_nearest(float *color, const sw_texture_t *tex, float u, float v)
+static inline void sw_texture_sample_nearest(float *SW_RESTRICT color, const sw_texture_t *SW_RESTRICT tex, float u, float v)
{
u = (tex->sWrap == SW_REPEAT)? sw_fract(u) : sw_saturate(u);
v = (tex->tWrap == SW_REPEAT)? sw_fract(v) : sw_saturate(v);
@@ -1913,10 +2411,10 @@ static inline void sw_texture_sample_nearest(float *color, const sw_texture_t *t
int x = u*tex->width;
int y = v*tex->height;
- sw_texture_fetch(color, tex, x, y);
+ tex->readColor(color, tex->pixels, y*tex->width + x);
}
-static inline void sw_texture_sample_linear(float *color, const sw_texture_t *tex, float u, float v)
+static inline void sw_texture_sample_linear(float *SW_RESTRICT color, const sw_texture_t *SW_RESTRICT tex, float u, float v)
{
// TODO: With a bit more cleverness thee number of operations can
// be clearly reduced, but for now it works fine
@@ -1958,10 +2456,10 @@ static inline void sw_texture_sample_linear(float *color, const sw_texture_t *te
}
float c00[4], c10[4], c01[4], c11[4];
- sw_texture_fetch(c00, tex, x0, y0);
- sw_texture_fetch(c10, tex, x1, y0);
- sw_texture_fetch(c01, tex, x0, y1);
- sw_texture_fetch(c11, tex, x1, y1);
+ tex->readColor(c00, tex->pixels, y0*tex->width + x0);
+ tex->readColor(c10, tex->pixels, y0*tex->width + x1);
+ tex->readColor(c01, tex->pixels, y1*tex->width + x0);
+ tex->readColor(c11, tex->pixels, y1*tex->width + x1);
for (int i = 0; i < 4; i++)
{
@@ -1971,10 +2469,12 @@ static inline void sw_texture_sample_linear(float *color, const sw_texture_t *te
}
}
-static inline void sw_texture_sample(float *color, const sw_texture_t *tex, float u, float v, float dUdx, float dUdy, float dVdx, float dVdy)
+static inline void sw_texture_sample(float *SW_RESTRICT color, const sw_texture_t *SW_RESTRICT tex,
+ float u, float v, float dUdx, float dUdy, float dVdx, float dVdy)
{
- // Previous method: There is no need to compute the square root
- // because using the squared value, the comparison remains (L2 > 1.0f*1.0f)
+ // NOTE: Commented there is the previous method used
+ // There was no need to compute the square root because
+ // using the squared value, the comparison remains (L2 > 1.0f*1.0f)
//float du = sqrtf(dUdx*dUdx + dUdy*dUdy);
//float dv = sqrtf(dVdx*dVdx + dVdy*dVdy);
//float L = (du > dv)? du : dv;
@@ -1995,111 +2495,386 @@ static inline void sw_texture_sample(float *color, const sw_texture_t *tex, floa
}
//-------------------------------------------------------------------------------------------
+// Framebuffer management functions
+//-------------------------------------------------------------------------------------------
+static inline bool sw_default_framebuffer_alloc(sw_default_framebuffer_t *fb, int w, int h)
+{
+ if (!sw_texture_alloc(&fb->color, NULL, w, h, SW_FRAMEBUFFER_COLOR_FORMAT))
+ {
+ return false;
+ }
+
+ if (!sw_texture_alloc(&fb->depth, NULL, w, h, SW_FRAMEBUFFER_DEPTH_FORMAT))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+static inline void sw_default_framebuffer_free(sw_default_framebuffer_t *fb)
+{
+ sw_texture_free(&fb->color);
+ sw_texture_free(&fb->depth);
+}
+
+static inline void sw_framebuffer_fill_color(sw_texture_t *colorBuffer, const float color[4])
+{
+ // NOTE: MSVC doesn't support VLA, so the largest possible size is allocated: 16 bytes
+ //uint8_t pixel[SW_FRAMEBUFFER_COLOR_SIZE] = { 0 };
+ uint8_t pixel[16] = { 0 };
+ SW_FRAMEBUFFER_COLOR_SET(pixel, color, 0);
+
+ uint8_t *dst = (uint8_t *)colorBuffer->pixels;
+
+ if (RLSW.userState & SW_STATE_SCISSOR_TEST)
+ {
+ int xMin = sw_clamp_int(RLSW.scMin[0], 0, colorBuffer->width - 1);
+ int xMax = sw_clamp_int(RLSW.scMax[0], 0, colorBuffer->width - 1);
+ int yMin = sw_clamp_int(RLSW.scMin[1], 0, colorBuffer->height - 1);
+ int yMax = sw_clamp_int(RLSW.scMax[1], 0, colorBuffer->height - 1);
+
+ int w = xMax - xMin;
+ for (int y = yMin; y <= yMax; y++)
+ {
+ uint8_t *row = dst + (y*colorBuffer->width + xMin)*SW_FRAMEBUFFER_COLOR_SIZE;
+ for (int x = 0; x <= w; x++, row += SW_FRAMEBUFFER_COLOR_SIZE)
+ {
+ for (int b = 0; b < SW_FRAMEBUFFER_COLOR_SIZE; b++) row[b] = pixel[b];
+ }
+ }
+ }
+ else
+ {
+ int size = colorBuffer->width*colorBuffer->height;
+ for (int i = 0; i < size; i++)
+ {
+ for (int b = 0; b < SW_FRAMEBUFFER_COLOR_SIZE; b++)
+ {
+ dst[i*SW_FRAMEBUFFER_COLOR_SIZE + b] = pixel[b];
+ }
+ }
+ }
+}
+
+static inline void sw_framebuffer_fill_depth(sw_texture_t *depthBuffer, float depth)
+{
+ // NOTE: MSVC doesn't support VLA, so the largest possible size is allocated: 4 bytes
+ //uint8_t pixel[SW_FRAMEBUFFER_DEPTH_SIZE] = { 0 };
+ uint8_t pixel[4] = { 0 };
+ SW_FRAMEBUFFER_DEPTH_SET(pixel, depth, 0);
+
+ uint8_t *dst = (uint8_t *)depthBuffer->pixels;
+
+ if (RLSW.userState & SW_STATE_SCISSOR_TEST)
+ {
+ int xMin = sw_clamp_int(RLSW.scMin[0], 0, depthBuffer->width - 1);
+ int xMax = sw_clamp_int(RLSW.scMax[0], 0, depthBuffer->width - 1);
+ int yMin = sw_clamp_int(RLSW.scMin[1], 0, depthBuffer->height - 1);
+ int yMax = sw_clamp_int(RLSW.scMax[1], 0, depthBuffer->height - 1);
+
+ int w = xMax - xMin;
+ for (int y = yMin; y <= yMax; y++)
+ {
+ uint8_t *row = dst + (y*depthBuffer->width + xMin)*SW_FRAMEBUFFER_DEPTH_SIZE;
+ for (int x = 0; x <= w; x++, row += SW_FRAMEBUFFER_DEPTH_SIZE)
+ {
+ for (int b = 0; b < SW_FRAMEBUFFER_DEPTH_SIZE; b++) row[b] = pixel[b];
+ }
+ }
+ }
+ else
+ {
+ int size = depthBuffer->width*depthBuffer->height;
+ for (int i = 0; i < size; i++)
+ {
+ for (int b = 0; b < SW_FRAMEBUFFER_DEPTH_SIZE; b++)
+ {
+ dst[i*SW_FRAMEBUFFER_DEPTH_SIZE + b] = pixel[b];
+ }
+ }
+ }
+}
+
+static inline void sw_framebuffer_output_fast(void *dst, const sw_texture_t *buffer)
+{
+ int width = buffer->width;
+ int height = buffer->height;
+
+ uint8_t *d = (uint8_t *)dst;
+
+#if SW_FRAMEBUFFER_OUTPUT_BGRA && (SW_FRAMEBUFFER_COLOR_FORMAT == SW_PIXELFORMAT_COLOR_R8G8B8A8)
+ for (int y = height - 1; y >= 0; y--)
+ {
+ const uint8_t *src = (uint8_t *)(buffer->pixels) + y*width*4;
+ for (int x = 0; x < width; x++, src += 4, d += 4)
+ {
+ d[0] = src[2];
+ d[1] = src[1];
+ d[2] = src[0];
+ d[3] = src[3];
+ }
+ }
+#elif SW_FRAMEBUFFER_OUTPUT_BGRA && (SW_FRAMEBUFFER_COLOR_FORMAT == SW_PIXELFORMAT_COLOR_R8G8B8)
+ for (int y = height - 1; y >= 0; y--)
+ {
+ const uint8_t *src = (uint8_t *)(buffer->pixels) + y*width*3;
+ for (int x = 0; x < width; x++, src += 3, d += 3)
+ {
+ d[0] = src[2];
+ d[1] = src[1];
+ d[2] = src[0];
+ }
+ }
+#else
+ int rowBytes = width*SW_FRAMEBUFFER_COLOR_SIZE;
+ for (int y = height - 1; y >= 0; y--)
+ {
+ const uint8_t *src = (uint8_t *)(buffer->pixels) + y*rowBytes;
+ for (int i = 0; i < rowBytes; i++) d[i] = src[i];
+ d += rowBytes;
+ }
+#endif
+}
+
+static inline void sw_framebuffer_output_copy(void *dst, const sw_texture_t *buffer, int x, int y, int w, int h, sw_pixelformat_t format)
+{
+ int stride = buffer->width;
+ int dstPixelSize = SW_PIXELFORMAT_SIZE[format];
+ sw_pixel_write_color8_f setColor8 = sw_pixel_get_write_color8_func(format);
+
+ const uint8_t *src = (uint8_t *)(buffer->pixels) + ((y + h - 1)*stride + x)*SW_FRAMEBUFFER_COLOR_SIZE;
+ uint8_t *d = dst;
+
+ for (int iy = 0; iy < h; iy++)
+ {
+ const uint8_t *line = src;
+ uint8_t *dline = d;
+
+ for (int ix = 0; ix < w; ix++)
+ {
+ uint8_t color[4];
+ SW_FRAMEBUFFER_COLOR8_GET(color, line, 0);
+
+ #if SW_FRAMEBUFFER_OUTPUT_BGRA
+ if (format == SW_PIXELFORMAT_COLOR_R8G8B8A8 || format == SW_PIXELFORMAT_COLOR_R8G8B8)
+ {
+ uint8_t tmp = color[0]; color[0] = color[2]; color[2] = tmp;
+ }
+ #endif
+
+ setColor8(dline, color, 0);
+ line += SW_FRAMEBUFFER_COLOR_SIZE;
+ dline += dstPixelSize;
+ }
+
+ src -= stride*SW_FRAMEBUFFER_COLOR_SIZE;
+ d += w*dstPixelSize;
+ }
+}
+
+static inline void sw_framebuffer_output_blit(void *dst, const sw_texture_t *buffer,
+ int xDst, int yDst, int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, sw_pixelformat_t format)
+{
+ const uint8_t *srcBase = buffer->pixels;
+
+ int fbWidth = buffer->width;
+ int dstPixelSize = SW_PIXELFORMAT_SIZE[format];
+ sw_pixel_write_color8_f setColor8 = sw_pixel_get_write_color8_func(format);
+
+ uint32_t xScale = ((uint32_t)wSrc << 16)/(uint32_t)wDst;
+ uint32_t yScale = ((uint32_t)hSrc << 16)/(uint32_t)hDst;
+
+ int ySrcLast = ySrc + hSrc - 1;
+ uint8_t *d = (uint8_t *)dst;
+
+ for (int dy = 0; dy < hDst; dy++)
+ {
+ int sy = ySrcLast - (int)(dy*yScale >> 16);
+ const uint8_t *srcLine = srcBase + (sy*fbWidth + xSrc)*SW_FRAMEBUFFER_COLOR_SIZE;
+ uint8_t *dline = d;
+
+ for (int dx = 0; dx < wDst; dx++)
+ {
+ int sx = (int)(dx*xScale >> 16);
+ const uint8_t *pixel = srcLine + sx*SW_FRAMEBUFFER_COLOR_SIZE;
+
+ uint8_t color[4];
+ SW_FRAMEBUFFER_COLOR8_GET(color, pixel, 0);
+
+ #if SW_FRAMEBUFFER_OUTPUT_BGRA
+ if (format == SW_PIXELFORMAT_COLOR_R8G8B8A8 || format == SW_PIXELFORMAT_COLOR_R8G8B8)
+ {
+ uint8_t tmp = color[0]; color[0] = color[2]; color[2] = tmp;
+ }
+ #endif
+
+ setColor8(dline, color, 0);
+ dline += dstPixelSize;
+ }
+
+ d += wDst*dstPixelSize;
+ }
+}
+//-------------------------------------------------------------------------------------------
+
// Color blending functionality
//-------------------------------------------------------------------------------------------
-static inline void sw_factor_zero(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
-{
- factor[0] = factor[1] = factor[2] = factor[3] = 0.0f;
+// Blend factor component macros: SW_BF_XXX(src, dst, component_index)
+// Each expands to the scalar factor value for one RGBA channel
+#define SW_BF_ZERO(s,d,i) 0.0f
+#define SW_BF_ONE(s,d,i) 1.0f
+#define SW_BF_SRC_COLOR(s,d,i) (s)[i]
+#define SW_BF_ONE_MINUS_SRC_COLOR(s,d,i) (1.0f-(s)[i])
+#define SW_BF_SRC_ALPHA(s,d,i) (s)[3]
+#define SW_BF_ONE_MINUS_SRC_ALPHA(s,d,i) (1.0f-(s)[3])
+#define SW_BF_DST_ALPHA(s,d,i) (d)[3]
+#define SW_BF_ONE_MINUS_DST_ALPHA(s,d,i) (1.0f-(d)[3])
+#define SW_BF_DST_COLOR(s,d,i) (d)[i]
+#define SW_BF_ONE_MINUS_DST_COLOR(s,d,i) (1.0f-(d)[i])
+#define SW_BF_SRC_ALPHA_SATURATE(s,d,i) (((i)<3)? 1.0f : (((s)[3]<1.0f)?(s)[3]:1.0f))
+
+// Generates one specialized blend function for a (sfactor, dfactor) pair
+#define DEFINE_BLEND_FUNC(sn, dn, SF, DF) \
+static void sw_blend_##sn##_##dn(float *SW_RESTRICT dst, const float *SW_RESTRICT src) \
+{ \
+ dst[0] = SF(src,dst,0)*src[0] + DF(src,dst,0)*dst[0]; \
+ dst[1] = SF(src,dst,1)*src[1] + DF(src,dst,1)*dst[1]; \
+ dst[2] = SF(src,dst,2)*src[2] + DF(src,dst,2)*dst[2]; \
+ dst[3] = SF(src,dst,3)*src[3] + DF(src,dst,3)*dst[3]; \
}
-static inline void sw_factor_one(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+// Master factor list: X(c_name, gl_enum, compact_index, SW_BF_macro)
+// compact_index is used to index SW_BLEND_TABLE (GL enums are non contiguous)
+#define FOREACH_FACTOR(X) \
+ X(ZERO, SW_ZERO, 0, SW_BF_ZERO ) \
+ X(ONE, SW_ONE, 1, SW_BF_ONE ) \
+ X(SRC_COLOR, SW_SRC_COLOR, 2, SW_BF_SRC_COLOR ) \
+ X(ONE_MINUS_SRC_COLOR, SW_ONE_MINUS_SRC_COLOR, 3, SW_BF_ONE_MINUS_SRC_COLOR) \
+ X(SRC_ALPHA, SW_SRC_ALPHA, 4, SW_BF_SRC_ALPHA ) \
+ X(ONE_MINUS_SRC_ALPHA, SW_ONE_MINUS_SRC_ALPHA, 5, SW_BF_ONE_MINUS_SRC_ALPHA) \
+ X(DST_ALPHA, SW_DST_ALPHA, 6, SW_BF_DST_ALPHA ) \
+ X(ONE_MINUS_DST_ALPHA, SW_ONE_MINUS_DST_ALPHA, 7, SW_BF_ONE_MINUS_DST_ALPHA) \
+ X(DST_COLOR, SW_DST_COLOR, 8, SW_BF_DST_COLOR ) \
+ X(ONE_MINUS_DST_COLOR, SW_ONE_MINUS_DST_COLOR, 9, SW_BF_ONE_MINUS_DST_COLOR) \
+ X(SRC_ALPHA_SATURATE, SW_SRC_ALPHA_SATURATE, 10, SW_BF_SRC_ALPHA_SATURATE )
+
+// Same list but forwards 3 extra args (A, B, C) to X
+#define FOREACH_FACTOR_WITH(X, A, B, C) \
+ X(ZERO, SW_ZERO, 0, SW_BF_ZERO, A,B,C) \
+ X(ONE, SW_ONE, 1, SW_BF_ONE, A,B,C) \
+ X(SRC_COLOR, SW_SRC_COLOR, 2, SW_BF_SRC_COLOR, A,B,C) \
+ X(ONE_MINUS_SRC_COLOR, SW_ONE_MINUS_SRC_COLOR, 3, SW_BF_ONE_MINUS_SRC_COLOR,A,B,C) \
+ X(SRC_ALPHA, SW_SRC_ALPHA, 4, SW_BF_SRC_ALPHA, A,B,C) \
+ X(ONE_MINUS_SRC_ALPHA, SW_ONE_MINUS_SRC_ALPHA, 5, SW_BF_ONE_MINUS_SRC_ALPHA,A,B,C) \
+ X(DST_ALPHA, SW_DST_ALPHA, 6, SW_BF_DST_ALPHA, A,B,C) \
+ X(ONE_MINUS_DST_ALPHA, SW_ONE_MINUS_DST_ALPHA, 7, SW_BF_ONE_MINUS_DST_ALPHA,A,B,C) \
+ X(DST_COLOR, SW_DST_COLOR, 8, SW_BF_DST_COLOR, A,B,C) \
+ X(ONE_MINUS_DST_COLOR, SW_ONE_MINUS_DST_COLOR, 9, SW_BF_ONE_MINUS_DST_COLOR,A,B,C) \
+ X(SRC_ALPHA_SATURATE, SW_SRC_ALPHA_SATURATE, 10, SW_BF_SRC_ALPHA_SATURATE, A,B,C)
+
+// Inner loop: receives dst factor + forwarded (sn, si, sf) from outer loop
+#define GEN_COMBO(dn, de, di, df, sn, si, sf) DEFINE_BLEND_FUNC(sn, dn, sf, df)
+
+// Outer loop: for each src factor, iterate all dst factors
+#define GEN_ROW(sn, se, si, sf) FOREACH_FACTOR_WITH(GEN_COMBO, sn, si, sf)
+
+// Generates all 121 sw_blend_SFACTOR_DFACTOR functions
+FOREACH_FACTOR(GEN_ROW)
+
+#undef GEN_COMBO
+#undef GEN_ROW
+
+// Inner loop: emits one table entry using compact indices (not GL enum values)
+#define GEN_TABLE_ENTRY(dn, de, di, df, sn, si, sf) [si][di] = sw_blend_##sn##_##dn,
+
+// Outer loop: fills one row of the table for a given src factor
+#define GEN_TABLE_ROW(sn, se, si, sf) FOREACH_FACTOR_WITH(GEN_TABLE_ENTRY, sn, si, sf)
+
+// 2D dispatch table indexed by compact src/dst factor indices
+#define SW_BLEND_FACTOR_COUNT 11
+static const sw_blend_f SW_BLEND_TABLE[SW_BLEND_FACTOR_COUNT][SW_BLEND_FACTOR_COUNT] = {
+ FOREACH_FACTOR(GEN_TABLE_ROW)
+};
+
+#undef GEN_TABLE_ENTRY
+#undef GEN_TABLE_ROW
+
+// Maps a GL blend factor enum to its compact table index
+static inline int sw_blend_factor_index(SWfactor f)
{
- factor[0] = factor[1] = factor[2] = factor[3] = 1.0f;
+ switch (f) {
+ case SW_ZERO: return 0;
+ case SW_ONE: return 1;
+ case SW_SRC_COLOR: return 2;
+ case SW_ONE_MINUS_SRC_COLOR: return 3;
+ case SW_SRC_ALPHA: return 4;
+ case SW_ONE_MINUS_SRC_ALPHA: return 5;
+ case SW_DST_ALPHA: return 6;
+ case SW_ONE_MINUS_DST_ALPHA: return 7;
+ case SW_DST_COLOR: return 8;
+ case SW_ONE_MINUS_DST_COLOR: return 9;
+ case SW_SRC_ALPHA_SATURATE: return 10;
+ default: return -1;
+ }
}
-static inline void sw_factor_src_color(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+static bool sw_blend_factor_needs_alpha(SWfactor f)
{
- factor[0] = src[0]; factor[1] = src[1]; factor[2] = src[2]; factor[3] = src[3];
+ switch (f) {
+ case SW_SRC_ALPHA:
+ case SW_ONE_MINUS_SRC_ALPHA:
+ case SW_DST_ALPHA:
+ case SW_ONE_MINUS_DST_ALPHA:
+ case SW_SRC_ALPHA_SATURATE: return true;
+ default: break;
+ }
+ return false;
}
-static inline void sw_factor_one_minus_src_color(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+static uint32_t sw_blend_compute_flags(SWfactor src, SWfactor dst)
{
- factor[0] = 1.0f - src[0]; factor[1] = 1.0f - src[1];
- factor[2] = 1.0f - src[2]; factor[3] = 1.0f - src[3];
-}
+ uint32_t flags = 0;
-static inline void sw_factor_src_alpha(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
-{
- factor[0] = factor[1] = factor[2] = factor[3] = src[3];
-}
+ // Blend is a no-op: result = src*1 + dst*0 = src
+ if (src == SW_ONE && dst == SW_ZERO) flags |= SW_BLEND_FLAG_NOOP;
-static inline void sw_factor_one_minus_src_alpha(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
-{
- float invAlpha = 1.0f - src[3];
- factor[0] = factor[1] = factor[2] = factor[3] = invAlpha;
-}
+ // Factors that depend on the alpha channel
+ if (sw_blend_factor_needs_alpha(src) || sw_blend_factor_needs_alpha(dst)) flags |= SW_BLEND_FLAG_NEEDS_ALPHA;
-static inline void sw_factor_dst_alpha(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
-{
- factor[0] = factor[1] = factor[2] = factor[3] = dst[3];
-}
-
-static inline void sw_factor_one_minus_dst_alpha(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
-{
- float invAlpha = 1.0f - dst[3];
- factor[0] = factor[1] = factor[2] = factor[3] = invAlpha;
-}
-
-static inline void sw_factor_dst_color(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
-{
- factor[0] = dst[0]; factor[1] = dst[1]; factor[2] = dst[2]; factor[3] = dst[3];
-}
-
-static inline void sw_factor_one_minus_dst_color(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
-{
- factor[0] = 1.0f - dst[0]; factor[1] = 1.0f - dst[1];
- factor[2] = 1.0f - dst[2]; factor[3] = 1.0f - dst[3];
-}
-
-static inline void sw_factor_src_alpha_saturate(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
-{
- factor[0] = factor[1] = factor[2] = 1.0f;
- factor[3] = (src[3] < 1.0f)? src[3] : 1.0f;
-}
-
-static inline void sw_blend_colors(float *SW_RESTRICT dst/*[4]*/, const float *SW_RESTRICT src/*[4]*/)
-{
- float srcFactor[4], dstFactor[4];
-
- RLSW.srcFactorFunc(srcFactor, src, dst);
- RLSW.dstFactorFunc(dstFactor, src, dst);
-
- dst[0] = srcFactor[0]*src[0] + dstFactor[0]*dst[0];
- dst[1] = srcFactor[1]*src[1] + dstFactor[1]*dst[1];
- dst[2] = srcFactor[2]*src[2] + dstFactor[2]*dst[2];
- dst[3] = srcFactor[3]*src[3] + dstFactor[3]*dst[3];
+ return flags;
}
//-------------------------------------------------------------------------------------------
// Projection helper functions
//-------------------------------------------------------------------------------------------
-static inline void sw_project_ndc_to_screen(float screen[2], const float ndc[4])
+static inline void sw_project_ndc_to_screen(float ndc[4])
{
- screen[0] = RLSW.vpCenter[0] + ndc[0]*RLSW.vpHalf[0] + 0.5f;
- screen[1] = RLSW.vpCenter[1] - ndc[1]*RLSW.vpHalf[1] + 0.5f;
+ ndc[0] = RLSW.vpCenter[0] + ndc[0]*RLSW.vpHalf[0] + 0.5f;
+ ndc[1] = RLSW.vpCenter[1] + ndc[1]*RLSW.vpHalf[1] + 0.5f;
}
//-------------------------------------------------------------------------------------------
// Polygon clipping management
//-------------------------------------------------------------------------------------------
#define DEFINE_CLIP_FUNC(name, FUNC_IS_INSIDE, FUNC_COMPUTE_T) \
-static inline int sw_clip_##name( \
+static int sw_clip_##name( \
sw_vertex_t output[SW_MAX_CLIPPED_POLYGON_VERTICES], \
const sw_vertex_t input[SW_MAX_CLIPPED_POLYGON_VERTICES], \
int n) \
{ \
const sw_vertex_t *prev = &input[n - 1]; \
- int prevInside = FUNC_IS_INSIDE(prev->homogeneous); \
+ int prevInside = FUNC_IS_INSIDE(prev->position); \
int outputCount = 0; \
\
for (int i = 0; i < n; i++) { \
const sw_vertex_t *curr = &input[i]; \
- int currInside = FUNC_IS_INSIDE(curr->homogeneous); \
+ int currInside = FUNC_IS_INSIDE(curr->position); \
\
/* If transition between interior/exterior, calculate intersection point */ \
if (prevInside != currInside) { \
- float t = FUNC_COMPUTE_T(prev->homogeneous, curr->homogeneous); \
- sw_lerp_vertex_PTCH(&output[outputCount++], prev, curr, t); \
+ float t = FUNC_COMPUTE_T(prev->position, curr->position); \
+ sw_lerp_vertex_PCT(&output[outputCount++], prev, curr, t); \
} \
\
/* If current vertex inside, add it */ \
@@ -2161,7 +2936,7 @@ DEFINE_CLIP_FUNC(scissor_y_max, IS_INSIDE_SCISSOR_Y_MAX, COMPUTE_T_SCISSOR_Y_MAX
//-------------------------------------------------------------------------------------------
// Main polygon clip function
-static inline bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES], int *vertexCounter)
+static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES], int *vertexCounter)
{
static sw_vertex_t tmp[SW_MAX_CLIPPED_POLYGON_VERTICES];
@@ -2186,7 +2961,7 @@ static inline bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VE
CLIP_AGAINST_PLANE(sw_clip_z_pos);
CLIP_AGAINST_PLANE(sw_clip_z_neg);
- if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
+ if (RLSW.userState & SW_STATE_SCISSOR_TEST)
{
CLIP_AGAINST_PLANE(sw_clip_scissor_x_min);
CLIP_AGAINST_PLANE(sw_clip_scissor_x_max);
@@ -2199,58 +2974,384 @@ static inline bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VE
return (n >= 3);
}
+// Triangle rasterizer variant dispatch
+//-------------------------------------------------------------------------------------------
+#ifndef RLSW_TEMPLATE_RASTER_TRIANGLE_EXPANDING
+#define RLSW_TEMPLATE_RASTER_TRIANGLE_EXPANDING
+
+ // State mask to apply before indexing the dispatch table
+ #define SW_RASTER_TRIANGLE_STATE_MASK \
+ (SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)
+
+ // Single source of truth for all rasterizer specializations
+ // X(NAME, STATE_FLAGS)
+ #define SW_RASTER_VARIANTS(X) \
+ X(BASE, 0) \
+ X(TEX, SW_STATE_TEXTURE_2D) \
+ X(DEPTH, SW_STATE_DEPTH_TEST) \
+ X(BLEND, SW_STATE_BLEND) \
+ X(TEX_DEPTH, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST) \
+ X(TEX_BLEND, SW_STATE_TEXTURE_2D | SW_STATE_BLEND) \
+ X(DEPTH_BLEND, SW_STATE_DEPTH_TEST | SW_STATE_BLEND) \
+ X(TEX_DEPTH_BLEND, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)
+
+ // Forward declarations because clangd does not follow #include __FILE__ to avoid infinite recursion
+ // These declarations make all variants visible to static analysis tools without affecting compilation
+ #define SW_FWD_DECL(NAME, _FLAGS) \
+ static void sw_raster_triangle_##NAME(const sw_vertex_t*, const sw_vertex_t*, const sw_vertex_t*);
+ SW_RASTER_VARIANTS(SW_FWD_DECL) // NOLINT
+ #undef SW_FWD_DECL
+
+ // Specialization generation via self-inclusion
+
+ #define RLSW_TEMPLATE_RASTER_TRIANGLE BASE
+ #include __FILE__ // IWYU pragma: keep
+ #undef RLSW_TEMPLATE_RASTER_TRIANGLE
+
+ #define RLSW_TEMPLATE_RASTER_TRIANGLE TEX
+ #define SW_ENABLE_TEXTURE
+ #include __FILE__
+ #undef SW_ENABLE_TEXTURE
+ #undef RLSW_TEMPLATE_RASTER_TRIANGLE
+
+ #define RLSW_TEMPLATE_RASTER_TRIANGLE DEPTH
+ #define SW_ENABLE_DEPTH_TEST
+ #include __FILE__
+ #undef SW_ENABLE_DEPTH_TEST
+ #undef RLSW_TEMPLATE_RASTER_TRIANGLE
+
+ #define RLSW_TEMPLATE_RASTER_TRIANGLE BLEND
+ #define SW_ENABLE_BLEND
+ #include __FILE__
+ #undef SW_ENABLE_BLEND
+ #undef RLSW_TEMPLATE_RASTER_TRIANGLE
+
+ #define RLSW_TEMPLATE_RASTER_TRIANGLE TEX_DEPTH
+ #define SW_ENABLE_TEXTURE
+ #define SW_ENABLE_DEPTH_TEST
+ #include __FILE__
+ #undef SW_ENABLE_DEPTH_TEST
+ #undef SW_ENABLE_TEXTURE
+ #undef RLSW_TEMPLATE_RASTER_TRIANGLE
+
+ #define RLSW_TEMPLATE_RASTER_TRIANGLE TEX_BLEND
+ #define SW_ENABLE_TEXTURE
+ #define SW_ENABLE_BLEND
+ #include __FILE__
+ #undef SW_ENABLE_BLEND
+ #undef SW_ENABLE_TEXTURE
+ #undef RLSW_TEMPLATE_RASTER_TRIANGLE
+
+ #define RLSW_TEMPLATE_RASTER_TRIANGLE DEPTH_BLEND
+ #define SW_ENABLE_DEPTH_TEST
+ #define SW_ENABLE_BLEND
+ #include __FILE__
+ #undef SW_ENABLE_BLEND
+ #undef SW_ENABLE_DEPTH_TEST
+ #undef RLSW_TEMPLATE_RASTER_TRIANGLE
+
+ #define RLSW_TEMPLATE_RASTER_TRIANGLE TEX_DEPTH_BLEND
+ #define SW_ENABLE_TEXTURE
+ #define SW_ENABLE_DEPTH_TEST
+ #define SW_ENABLE_BLEND
+ #include __FILE__
+ #undef SW_ENABLE_BLEND
+ #undef SW_ENABLE_DEPTH_TEST
+ #undef SW_ENABLE_TEXTURE
+ #undef RLSW_TEMPLATE_RASTER_TRIANGLE
+
+ // Dispatch table (auto-generated from SW_RASTER_VARIANTS)
+ #define SW_TABLE_ENTRY(NAME, FLAGS) [FLAGS] = sw_raster_triangle_##NAME,
+ static const sw_raster_triangle_f SW_RASTER_TRIANGLE_TABLE[] = {
+ SW_RASTER_VARIANTS(SW_TABLE_ENTRY)
+ };
+ #undef SW_TABLE_ENTRY
+
+#undef SW_RASTER_VARIANTS
+#undef RLSW_TEMPLATE_RASTER_TRIANGLE_EXPANDING
+
+#endif // RLSW_TEMPLATE_RASTER_TRIANGLE_EXPANDING
+//-------------------------------------------------------------------------------------------
+
+// Quad rasterizer variant dispatch
+//-------------------------------------------------------------------------------------------
+#ifndef RLSW_TEMPLATE_RASTER_QUAD_EXPANDING
+#define RLSW_TEMPLATE_RASTER_QUAD_EXPANDING
+
+ // State mask to apply before indexing the dispatch table
+ #define SW_RASTER_QUAD_STATE_MASK \
+ (SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)
+
+ // Single source of truth for all rasterizer specializations
+ // X(NAME, STATE_FLAGS)
+ #define SW_RASTER_VARIANTS(X) \
+ X(BASE, 0) \
+ X(TEX, SW_STATE_TEXTURE_2D) \
+ X(DEPTH, SW_STATE_DEPTH_TEST) \
+ X(BLEND, SW_STATE_BLEND) \
+ X(TEX_DEPTH, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST) \
+ X(TEX_BLEND, SW_STATE_TEXTURE_2D | SW_STATE_BLEND) \
+ X(DEPTH_BLEND, SW_STATE_DEPTH_TEST | SW_STATE_BLEND) \
+ X(TEX_DEPTH_BLEND, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)
+
+ // Forward declarations because clangd does not follow #include __FILE__ to avoid infinite recursion
+ // These declarations make all variants visible to static analysis tools without affecting compilation
+ #define SW_FWD_DECL(NAME, _FLAGS) \
+ static void sw_raster_quad_##NAME(const sw_vertex_t *v0, const sw_vertex_t *v1, const sw_vertex_t *v2, const sw_vertex_t *v3);
+ SW_RASTER_VARIANTS(SW_FWD_DECL) // NOLINT
+ #undef SW_FWD_DECL
+
+ // Specialization generation via self-inclusion
+
+ #define RLSW_TEMPLATE_RASTER_QUAD BASE
+ #include __FILE__ // IWYU pragma: keep
+ #undef RLSW_TEMPLATE_RASTER_QUAD
+
+ #define RLSW_TEMPLATE_RASTER_QUAD TEX
+ #define SW_ENABLE_TEXTURE
+ #include __FILE__
+ #undef SW_ENABLE_TEXTURE
+ #undef RLSW_TEMPLATE_RASTER_QUAD
+
+ #define RLSW_TEMPLATE_RASTER_QUAD DEPTH
+ #define SW_ENABLE_DEPTH_TEST
+ #include __FILE__
+ #undef SW_ENABLE_DEPTH_TEST
+ #undef RLSW_TEMPLATE_RASTER_QUAD
+
+ #define RLSW_TEMPLATE_RASTER_QUAD BLEND
+ #define SW_ENABLE_BLEND
+ #include __FILE__
+ #undef SW_ENABLE_BLEND
+ #undef RLSW_TEMPLATE_RASTER_QUAD
+
+ #define RLSW_TEMPLATE_RASTER_QUAD TEX_DEPTH
+ #define SW_ENABLE_TEXTURE
+ #define SW_ENABLE_DEPTH_TEST
+ #include __FILE__
+ #undef SW_ENABLE_DEPTH_TEST
+ #undef SW_ENABLE_TEXTURE
+ #undef RLSW_TEMPLATE_RASTER_QUAD
+
+ #define RLSW_TEMPLATE_RASTER_QUAD TEX_BLEND
+ #define SW_ENABLE_TEXTURE
+ #define SW_ENABLE_BLEND
+ #include __FILE__
+ #undef SW_ENABLE_BLEND
+ #undef SW_ENABLE_TEXTURE
+ #undef RLSW_TEMPLATE_RASTER_QUAD
+
+ #define RLSW_TEMPLATE_RASTER_QUAD DEPTH_BLEND
+ #define SW_ENABLE_DEPTH_TEST
+ #define SW_ENABLE_BLEND
+ #include __FILE__
+ #undef SW_ENABLE_BLEND
+ #undef SW_ENABLE_DEPTH_TEST
+ #undef RLSW_TEMPLATE_RASTER_QUAD
+
+ #define RLSW_TEMPLATE_RASTER_QUAD TEX_DEPTH_BLEND
+ #define SW_ENABLE_TEXTURE
+ #define SW_ENABLE_DEPTH_TEST
+ #define SW_ENABLE_BLEND
+ #include __FILE__
+ #undef SW_ENABLE_BLEND
+ #undef SW_ENABLE_DEPTH_TEST
+ #undef SW_ENABLE_TEXTURE
+ #undef RLSW_TEMPLATE_RASTER_QUAD
+
+ // Dispatch table (auto-generated from SW_RASTER_VARIANTS)
+ #define SW_TABLE_ENTRY(NAME, FLAGS) [FLAGS] = sw_raster_quad_##NAME,
+ static const sw_raster_quad_f SW_RASTER_QUAD_TABLE[] = {
+ SW_RASTER_VARIANTS(SW_TABLE_ENTRY)
+ };
+ #undef SW_TABLE_ENTRY
+
+#undef SW_RASTER_VARIANTS
+#undef RLSW_TEMPLATE_RASTER_QUAD_EXPANDING
+
+#endif // RLSW_TEMPLATE_RASTER_QUAD_EXPANDING
+//-------------------------------------------------------------------------------------------
+
+// Line rasterizer variant dispatch
+//-------------------------------------------------------------------------------------------
+#ifndef RLSW_TEMPLATE_RASTER_LINE_EXPANDING
+#define RLSW_TEMPLATE_RASTER_LINE_EXPANDING
+
+ // State mask to apply before indexing the dispatch table
+ #define SW_RASTER_LINE_STATE_MASK \
+ (SW_STATE_DEPTH_TEST | SW_STATE_BLEND)
+
+ // Single source of truth for all rasterizer specializations
+ // X(NAME, STATE_FLAGS)
+ #define SW_RASTER_VARIANTS(X) \
+ X(BASE, 0) \
+ X(DEPTH, SW_STATE_DEPTH_TEST) \
+ X(BLEND, SW_STATE_BLEND) \
+ X(DEPTH_BLEND, SW_STATE_DEPTH_TEST | SW_STATE_BLEND)
+
+ // Forward declarations because clangd does not follow #include __FILE__ to avoid infinite recursion
+ // These declarations make all variants visible to static analysis tools without affecting compilation
+ #define SW_FWD_DECL(NAME, _FLAGS) \
+ static void sw_raster_line_##NAME(const sw_vertex_t *v0, const sw_vertex_t *v1); \
+ static void sw_raster_line_thick_##NAME(const sw_vertex_t *v0, const sw_vertex_t *v1);
+ SW_RASTER_VARIANTS(SW_FWD_DECL) // NOLINT
+ #undef SW_FWD_DECL
+
+ // Specialization generation via self-inclusion
+
+ #define RLSW_TEMPLATE_RASTER_LINE BASE
+ #include __FILE__ // IWYU pragma: keep
+ #undef RLSW_TEMPLATE_RASTER_LINE
+
+ #define RLSW_TEMPLATE_RASTER_LINE DEPTH
+ #define SW_ENABLE_DEPTH_TEST
+ #include __FILE__
+ #undef SW_ENABLE_DEPTH_TEST
+ #undef RLSW_TEMPLATE_RASTER_LINE
+
+ #define RLSW_TEMPLATE_RASTER_LINE BLEND
+ #define SW_ENABLE_BLEND
+ #include __FILE__
+ #undef SW_ENABLE_BLEND
+ #undef RLSW_TEMPLATE_RASTER_LINE
+
+ #define RLSW_TEMPLATE_RASTER_LINE DEPTH_BLEND
+ #define SW_ENABLE_DEPTH_TEST
+ #define SW_ENABLE_BLEND
+ #include __FILE__
+ #undef SW_ENABLE_BLEND
+ #undef SW_ENABLE_DEPTH_TEST
+ #undef RLSW_TEMPLATE_RASTER_LINE
+
+ // Dispatch table (auto-generated from SW_RASTER_VARIANTS)
+ #define SW_TABLE_ENTRY0(NAME, FLAGS) [FLAGS] = sw_raster_line_##NAME,
+ #define SW_TABLE_ENTRY1(NAME, FLAGS) [FLAGS] = sw_raster_line_thick_##NAME,
+ static const sw_raster_line_f SW_RASTER_LINE_TABLE[] = { SW_RASTER_VARIANTS(SW_TABLE_ENTRY0) };
+ static const sw_raster_line_f SW_RASTER_LINE_THICK_TABLE[] = { SW_RASTER_VARIANTS(SW_TABLE_ENTRY1) };
+ #undef SW_TABLE_ENTRY0
+ #undef SW_TABLE_ENTRY1
+
+#undef SW_RASTER_VARIANTS
+#undef RLSW_TEMPLATE_RASTER_LINE_EXPANDING
+
+#endif // RLSW_TEMPLATE_RASTER_LINE_EXPANDING
+//-------------------------------------------------------------------------------------------
+
+// Point rasterizer variant dispatch
+//-------------------------------------------------------------------------------------------
+#ifndef RLSW_TEMPLATE_RASTER_POINT_EXPANDING
+#define RLSW_TEMPLATE_RASTER_POINT_EXPANDING
+
+ // State mask to apply before indexing the dispatch table
+ #define SW_RASTER_POINT_STATE_MASK \
+ (SW_STATE_DEPTH_TEST | SW_STATE_BLEND)
+
+ // Single source of truth for all rasterizer specializations
+ // X(NAME, STATE_FLAGS)
+ #define SW_RASTER_VARIANTS(X) \
+ X(BASE, 0) \
+ X(DEPTH, SW_STATE_DEPTH_TEST) \
+ X(BLEND, SW_STATE_BLEND) \
+ X(DEPTH_BLEND, SW_STATE_DEPTH_TEST | SW_STATE_BLEND)
+
+ // Forward declarations because clangd does not follow #include __FILE__ to avoid infinite recursion
+ // These declarations make all variants visible to static analysis tools without affecting compilation
+ #define SW_FWD_DECL(NAME, _FLAGS) \
+ static void sw_raster_point_##NAME(const sw_vertex_t *v);
+ SW_RASTER_VARIANTS(SW_FWD_DECL) // NOLINT
+ #undef SW_FWD_DECL
+
+ // Specialization generation via self-inclusion
+
+ #define RLSW_TEMPLATE_RASTER_POINT BASE
+ #include __FILE__ // IWYU pragma: keep
+ #undef RLSW_TEMPLATE_RASTER_POINT
+
+ #define RLSW_TEMPLATE_RASTER_POINT DEPTH
+ #define SW_ENABLE_DEPTH_TEST
+ #include __FILE__
+ #undef SW_ENABLE_DEPTH_TEST
+ #undef RLSW_TEMPLATE_RASTER_POINT
+
+ #define RLSW_TEMPLATE_RASTER_POINT BLEND
+ #define SW_ENABLE_BLEND
+ #include __FILE__
+ #undef SW_ENABLE_BLEND
+ #undef RLSW_TEMPLATE_RASTER_POINT
+
+ #define RLSW_TEMPLATE_RASTER_POINT DEPTH_BLEND
+ #define SW_ENABLE_DEPTH_TEST
+ #define SW_ENABLE_BLEND
+ #include __FILE__
+ #undef SW_ENABLE_BLEND
+ #undef SW_ENABLE_DEPTH_TEST
+ #undef RLSW_TEMPLATE_RASTER_POINT
+
+ // Dispatch table (auto-generated from SW_RASTER_VARIANTS)
+ #define SW_TABLE_ENTRY(NAME, FLAGS) [FLAGS] = sw_raster_point_##NAME,
+ static const sw_raster_point_f SW_RASTER_POINT_TABLE[] = {
+ SW_RASTER_VARIANTS(SW_TABLE_ENTRY)
+ };
+ #undef SW_TABLE_ENTRY
+
+#undef SW_RASTER_VARIANTS
+#undef RLSW_TEMPLATE_RASTER_POINT_EXPANDING
+
+#endif // RLSW_TEMPLATE_RASTER_POINT_EXPANDING
+//-------------------------------------------------------------------------------------------
+
// Triangle rendering logic
//-------------------------------------------------------------------------------------------
static inline bool sw_triangle_face_culling(void)
{
// NOTE: Face culling is done before clipping to avoid unnecessary computations
// To handle triangles crossing the w=0 plane correctly,
- // the winding order test is performeed in homogeneous coordinates directly,
+ // the winding order test is performeed in clip space directly,
// before the perspective division (division by w)
// This test determines the orientation of the triangle in the (x,y,w) plane,
// which corresponds to the projected 2D winding order sign,
// even with negative w values
- // Preload homogeneous coordinates into local variables
- const float *h0 = RLSW.vertexBuffer[0].homogeneous;
- const float *h1 = RLSW.vertexBuffer[1].homogeneous;
- const float *h2 = RLSW.vertexBuffer[2].homogeneous;
+ // Preload clip coordinates into local variables
+ const float *p0 = RLSW.primitive.buffer[0].position;
+ const float *p1 = RLSW.primitive.buffer[1].position;
+ const float *p2 = RLSW.primitive.buffer[2].position;
// Compute a value proportional to the signed area in the projected 2D plane,
- // calculated directly using homogeneous coordinates BEFORE division by w
+ // calculated directly using clip coordinates BEFORE division by w
// This is the determinant of the matrix formed by the (x, y, w) components
- // of the vertices, which correctly captures the winding order in homogeneous
+ // of the vertices, which correctly captures the winding order in clip
// space and its relationship to the projected 2D winding order, even with
// negative w values
// The determinant formula used here is:
- // h0.x*(h1.y*h2.w - h2.y*h1.w) +
- // h1.x*(h2.y*h0.w - h0.y*h2.w) +
- // h2.x*(h0.y*h1.w - h1.y*h0.w)
+ // p0.x*(p1.y*p2.w - p2.y*p1.w) +
+ // p1.x*(p2.y*p0.w - p0.y*p2.w) +
+ // p2.x*(p0.y*p1.w - p1.y*p0.w)
- const float hSgnArea =
- h0[0]*(h1[1]*h2[3] - h2[1]*h1[3]) +
- h1[0]*(h2[1]*h0[3] - h0[1]*h2[3]) +
- h2[0]*(h0[1]*h1[3] - h1[1]*h0[3]);
+ const float sgnArea =
+ p0[0]*(p1[1]*p2[3] - p2[1]*p1[3]) +
+ p1[0]*(p2[1]*p0[3] - p0[1]*p2[3]) +
+ p2[0]*(p0[1]*p1[3] - p1[1]*p0[3]);
// Discard the triangle if its winding order (determined by the sign
// of the homogeneous area/determinant) matches the culled direction
- // A positive hSgnArea typically corresponds to a counter-clockwise
+ // A positive sgnArea typically corresponds to a counter-clockwise
// winding in the projected space when all w > 0
// This test is robust for points with w > 0 or w < 0, correctly
// capturing the change in orientation when crossing the w=0 plane
// The culling logic remains the same based on the signed area/determinant
- // A value of 0 for hSgnArea means the points are collinear in (x, y, w)
+ // A value of 0 for sgnArea means the points are collinear in (x, y, w)
// space, which corresponds to a degenerate triangle projection
// Such triangles are typically not culled by this test (0 < 0 is false, 0 > 0 is false)
// and should be handled by the clipper if necessary
- return (RLSW.cullFace == SW_FRONT)? (hSgnArea < 0) : (hSgnArea > 0); // Cull if winding is "clockwise" : "counter-clockwise"
+ return (RLSW.cullFace == SW_FRONT)? (sgnArea < 0) : (sgnArea > 0); // Cull if winding is "clockwise" : "counter-clockwise"
}
-static inline void sw_triangle_clip_and_project(void)
+static void sw_triangle_clip_and_project(void)
{
- sw_vertex_t *polygon = RLSW.vertexBuffer;
- int *vertexCounter = &RLSW.vertexCounter;
+ sw_vertex_t *polygon = RLSW.primitive.buffer;
+ int *vertexCounter = &RLSW.primitive.vertexCount;
if (sw_polygon_clip(polygon, vertexCounter))
{
@@ -2261,13 +3362,13 @@ static inline void sw_triangle_clip_and_project(void)
// Calculation of the reciprocal of W for normalization
// as well as perspective-correct attributes
- const float wRcp = 1.0f/v->homogeneous[3];
- v->homogeneous[3] = wRcp;
+ const float wRcp = 1.0f/v->position[3];
// Division of XYZ coordinates by weight
- v->homogeneous[0] *= wRcp;
- v->homogeneous[1] *= wRcp;
- v->homogeneous[2] *= wRcp;
+ v->position[0] *= wRcp;
+ v->position[1] *= wRcp;
+ v->position[2] *= wRcp;
+ v->position[3] = wRcp;
// Division of texture coordinates (perspective-correct)
v->texcoord[0] *= wRcp;
@@ -2280,276 +3381,31 @@ static inline void sw_triangle_clip_and_project(void)
v->color[3] *= wRcp;
// Transformation to screen space
- sw_project_ndc_to_screen(v->screen, v->homogeneous);
+ sw_project_ndc_to_screen(v->position);
}
}
}
-#define DEFINE_TRIANGLE_RASTER_SCANLINE(FUNC_NAME, ENABLE_TEXTURE, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \
-static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, \
- const sw_vertex_t *end, float dUdy, float dVdy) \
-{ \
- /* Gets the start and end coordinates */ \
- int xStart = (int)start->screen[0]; \
- int xEnd = (int)end->screen[0]; \
- \
- /* Avoid empty lines */ \
- if (xStart == xEnd) return; \
- \
- /* Compute the subpixel distance to traverse before the first pixel */ \
- float xSubstep = 1.0f - sw_fract(start->screen[0]); \
- \
- /* Compute the inverse horizontal distance along the X axis */ \
- float dxRcp = 1.0f/(end->screen[0] - start->screen[0]); \
- \
- /* Compute the interpolation steps along the X axis */ \
- float dZdx = (end->homogeneous[2] - start->homogeneous[2])*dxRcp; \
- float dWdx = (end->homogeneous[3] - start->homogeneous[3])*dxRcp; \
- \
- float dCdx[4] = { \
- (end->color[0] - start->color[0])*dxRcp, \
- (end->color[1] - start->color[1])*dxRcp, \
- (end->color[2] - start->color[2])*dxRcp, \
- (end->color[3] - start->color[3])*dxRcp \
- }; \
- \
- float dUdx = 0.0f; \
- float dVdx = 0.0f; \
- if (ENABLE_TEXTURE) { \
- dUdx = (end->texcoord[0] - start->texcoord[0])*dxRcp; \
- dVdx = (end->texcoord[1] - start->texcoord[1])*dxRcp; \
- } \
- \
- /* Initializing the interpolation starting values */ \
- float z = start->homogeneous[2] + dZdx*xSubstep; \
- float w = start->homogeneous[3] + dWdx*xSubstep; \
- \
- float color[4] = { \
- start->color[0] + dCdx[0]*xSubstep, \
- start->color[1] + dCdx[1]*xSubstep, \
- start->color[2] + dCdx[2]*xSubstep, \
- start->color[3] + dCdx[3]*xSubstep \
- }; \
- \
- float u = 0.0f; \
- float v = 0.0f; \
- if (ENABLE_TEXTURE) { \
- u = start->texcoord[0] + dUdx*xSubstep; \
- v = start->texcoord[1] + dVdx*xSubstep; \
- } \
- \
- /* Pre-calculate the starting pointers for the framebuffer row */ \
- int y = (int)start->screen[1]; \
- sw_pixel_t *ptr = RLSW.framebuffer.pixels + y*RLSW.framebuffer.width + xStart; \
- \
- /* Scanline rasterization */ \
- for (int x = xStart; x < xEnd; x++) \
- { \
- float wRcp = 1.0f/w; \
- float srcColor[4] = { \
- color[0]*wRcp, \
- color[1]*wRcp, \
- color[2]*wRcp, \
- color[3]*wRcp \
- }; \
- \
- if (ENABLE_DEPTH_TEST) \
- { \
- /* TODO: Implement different depth funcs? */ \
- float depth = sw_framebuffer_read_depth(ptr); \
- if (z > depth) goto discard; \
- } \
- \
- /* TODO: Implement depth mask */ \
- sw_framebuffer_write_depth(ptr, z); \
- \
- if (ENABLE_TEXTURE) \
- { \
- float texColor[4]; \
- float s = u*wRcp; \
- float t = v*wRcp; \
- sw_texture_sample(texColor, tex, s, t, dUdx, dUdy, dVdx, dVdy); \
- srcColor[0] *= texColor[0]; \
- srcColor[1] *= texColor[1]; \
- srcColor[2] *= texColor[2]; \
- srcColor[3] *= texColor[3]; \
- } \
- \
- if (ENABLE_COLOR_BLEND) \
- { \
- float dstColor[4]; \
- sw_framebuffer_read_color(dstColor, ptr); \
- sw_blend_colors(dstColor, srcColor); \
- sw_framebuffer_write_color(ptr, dstColor); \
- } \
- else \
- { \
- sw_framebuffer_write_color(ptr, srcColor); \
- } \
- \
- /* Increment the interpolation parameter, UVs, and pointers */ \
- discard: \
- z += dZdx; \
- w += dWdx; \
- color[0] += dCdx[0]; \
- color[1] += dCdx[1]; \
- color[2] += dCdx[2]; \
- color[3] += dCdx[3]; \
- if (ENABLE_TEXTURE) \
- { \
- u += dUdx; \
- v += dVdx; \
- } \
- ++ptr; \
- } \
-}
-
-#define DEFINE_TRIANGLE_RASTER(FUNC_NAME, FUNC_SCANLINE, ENABLE_TEXTURE) \
-static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1, \
- const sw_vertex_t *v2, const sw_texture_t *tex) \
-{ \
- /* Swap vertices by increasing y */ \
- if (v0->screen[1] > v1->screen[1]) { const sw_vertex_t *tmp = v0; v0 = v1; v1 = tmp; } \
- if (v1->screen[1] > v2->screen[1]) { const sw_vertex_t *tmp = v1; v1 = v2; v2 = tmp; } \
- if (v0->screen[1] > v1->screen[1]) { const sw_vertex_t *tmp = v0; v0 = v1; v1 = tmp; } \
- \
- /* Extracting coordinates from the sorted vertices */ \
- float x0 = v0->screen[0], y0 = v0->screen[1]; \
- float x1 = v1->screen[0], y1 = v1->screen[1]; \
- float x2 = v2->screen[0], y2 = v2->screen[1]; \
- \
- /* Compute height differences */ \
- float h02 = y2 - y0; \
- float h01 = y1 - y0; \
- float h12 = y2 - y1; \
- \
- if (h02 < 1e-6f) return; \
- \
- /* Precompute the inverse values without additional checks */ \
- float h02Rcp = 1.0f/h02; \
- float h01Rcp = (h01 > 1e-6f)? 1.0f/h01 : 0.0f; \
- float h12Rcp = (h12 > 1e-6f)? 1.0f/h12 : 0.0f; \
- \
- /* Pre-calculation of slopes */ \
- float dXdy02 = (x2 - x0)*h02Rcp; \
- float dXdy01 = (x1 - x0)*h01Rcp; \
- float dXdy12 = (x2 - x1)*h12Rcp; \
- \
- /* Y subpixel correction */ \
- float y0Substep = 1.0f - sw_fract(y0); \
- float y1Substep = 1.0f - sw_fract(y1); \
- \
- /* Y bounds (vertical clipping) */ \
- int yTop = (int)y0; \
- int yMid = (int)y1; \
- int yBot = (int)y2; \
- \
- /* Compute gradients for each side of the triangle */ \
- sw_vertex_t dVXdy02, dVXdy01, dVXdy12; \
- sw_get_vertex_grad_PTCH(&dVXdy02, v0, v2, h02Rcp); \
- sw_get_vertex_grad_PTCH(&dVXdy01, v0, v1, h01Rcp); \
- sw_get_vertex_grad_PTCH(&dVXdy12, v1, v2, h12Rcp); \
- \
- /* Get a copy of vertices for interpolation and apply substep correction */ \
- sw_vertex_t vLeft = *v0, vRight = *v0; \
- sw_add_vertex_grad_scaled_PTCH(&vLeft, &dVXdy02, y0Substep); \
- sw_add_vertex_grad_scaled_PTCH(&vRight, &dVXdy01, y0Substep); \
- \
- vLeft.screen[0] += dXdy02*y0Substep; \
- vRight.screen[0] += dXdy01*y0Substep; \
- \
- /* Scanline for the upper part of the triangle */ \
- for (int y = yTop; y < yMid; y++) \
- { \
- vLeft.screen[1] = vRight.screen[1] = y; \
- \
- if (vLeft.screen[0] < vRight.screen[0]) FUNC_SCANLINE(tex, &vLeft, &vRight, dVXdy02.texcoord[0], dVXdy02.texcoord[1]); \
- else FUNC_SCANLINE(tex, &vRight, &vLeft, dVXdy02.texcoord[0], dVXdy02.texcoord[1]); \
- \
- sw_add_vertex_grad_PTCH(&vLeft, &dVXdy02); \
- vLeft.screen[0] += dXdy02; \
- \
- sw_add_vertex_grad_PTCH(&vRight, &dVXdy01); \
- vRight.screen[0] += dXdy01; \
- } \
- \
- /* Get a copy of next right for interpolation and apply substep correction */ \
- vRight = *v1; \
- sw_add_vertex_grad_scaled_PTCH(&vRight, &dVXdy12, y1Substep); \
- vRight.screen[0] += dXdy12*y1Substep; \
- \
- /* Scanline for the lower part of the triangle */ \
- for (int y = yMid; y < yBot; y++) \
- { \
- vLeft.screen[1] = vRight.screen[1] = y; \
- \
- if (vLeft.screen[0] < vRight.screen[0]) FUNC_SCANLINE(tex, &vLeft, &vRight, dVXdy02.texcoord[0], dVXdy02.texcoord[1]); \
- else FUNC_SCANLINE(tex, &vRight, &vLeft, dVXdy02.texcoord[0], dVXdy02.texcoord[1]); \
- \
- sw_add_vertex_grad_PTCH(&vLeft, &dVXdy02); \
- vLeft.screen[0] += dXdy02; \
- \
- sw_add_vertex_grad_PTCH(&vRight, &dVXdy12); \
- vRight.screen[0] += dXdy12; \
- } \
-}
-
-DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline, 0, 0, 0)
-DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_TEX, 1, 0, 0)
-DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_DEPTH, 0, 1, 0)
-DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_BLEND, 0, 0, 1)
-DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_TEX_DEPTH, 1, 1, 0)
-DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_TEX_BLEND, 1, 0, 1)
-DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_DEPTH_BLEND, 0, 1, 1)
-DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_TEX_DEPTH_BLEND, 1, 1, 1)
-
-DEFINE_TRIANGLE_RASTER(sw_triangle_raster, sw_triangle_raster_scanline, false)
-DEFINE_TRIANGLE_RASTER(sw_triangle_raster_TEX, sw_triangle_raster_scanline_TEX, true)
-DEFINE_TRIANGLE_RASTER(sw_triangle_raster_DEPTH, sw_triangle_raster_scanline_DEPTH, false)
-DEFINE_TRIANGLE_RASTER(sw_triangle_raster_BLEND, sw_triangle_raster_scanline_BLEND, false)
-DEFINE_TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH, sw_triangle_raster_scanline_TEX_DEPTH, true)
-DEFINE_TRIANGLE_RASTER(sw_triangle_raster_TEX_BLEND, sw_triangle_raster_scanline_TEX_BLEND, true)
-DEFINE_TRIANGLE_RASTER(sw_triangle_raster_DEPTH_BLEND, sw_triangle_raster_scanline_DEPTH_BLEND, false)
-DEFINE_TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH_BLEND, sw_triangle_raster_scanline_TEX_DEPTH_BLEND, true)
-
-static inline void sw_triangle_render(void)
+static void sw_triangle_render(uint32_t state)
{
- if (RLSW.stateFlags & SW_STATE_CULL_FACE)
+ if (RLSW.userState & SW_STATE_CULL_FACE)
{
if (!sw_triangle_face_culling()) return;
}
sw_triangle_clip_and_project();
+ if (RLSW.primitive.vertexCount < 3) return;
- if (RLSW.vertexCounter < 3) return;
+ state &= SW_RASTER_TRIANGLE_STATE_MASK;
- #define TRIANGLE_RASTER(RASTER_FUNC) \
- { \
- for (int i = 0; i < RLSW.vertexCounter - 2; i++) \
- { \
- RASTER_FUNC( \
- &RLSW.vertexBuffer[0], \
- &RLSW.vertexBuffer[i + 1], \
- &RLSW.vertexBuffer[i + 2], \
- &RLSW.loadedTextures[RLSW.currentTexture] \
- ); \
- } \
+ for (int i = 0; i < RLSW.primitive.vertexCount - 2; i++)
+ {
+ SW_RASTER_TRIANGLE_TABLE[state](
+ &RLSW.primitive.buffer[0],
+ &RLSW.primitive.buffer[i + 1],
+ &RLSW.primitive.buffer[i + 2]
+ );
}
-
- uint32_t state = RLSW.stateFlags;
- if (RLSW.currentTexture == 0) state &= ~SW_STATE_TEXTURE_2D;
- if ((RLSW.srcFactor == SW_ONE) && (RLSW.dstFactor == SW_ZERO)) state &= ~SW_STATE_BLEND;
-
- if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH_BLEND)
- else if (SW_STATE_CHECK_EX(state, SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH_BLEND)
- else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_BLEND)
- else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH)
- else if (SW_STATE_CHECK_EX(state, SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_BLEND)
- else if (SW_STATE_CHECK_EX(state, SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH)
- else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D)) TRIANGLE_RASTER(sw_triangle_raster_TEX)
- else TRIANGLE_RASTER(sw_triangle_raster)
-
- #undef TRIANGLE_RASTER
}
//-------------------------------------------------------------------------------------------
@@ -2559,58 +3415,58 @@ static inline bool sw_quad_face_culling(void)
{
// NOTE: Face culling is done before clipping to avoid unnecessary computations
// To handle quads crossing the w=0 plane correctly,
- // the winding order test is performed in homogeneous coordinates directly,
+ // the winding order test is performed in clip space directly,
// before the perspective division (division by w)
// For a convex quad with vertices P0, P1, P2, P3 in sequential order,
// the winding order of the quad is the same as the winding order
- // of the triangle P0 P1 P2. The homogeneous triangle is used on
+ // of the triangle P0 P1 P2. The triangle in clip space is used on
// winding test on this first triangle
- // Preload homogeneous coordinates into local variables
- const float *h0 = RLSW.vertexBuffer[0].homogeneous;
- const float *h1 = RLSW.vertexBuffer[1].homogeneous;
- const float *h2 = RLSW.vertexBuffer[2].homogeneous;
+ // Preload clip coordinates into local variables
+ const float *p0 = RLSW.primitive.buffer[0].position;
+ const float *p1 = RLSW.primitive.buffer[1].position;
+ const float *p2 = RLSW.primitive.buffer[2].position;
// NOTE: h3 is not needed for this test
- // const float *h3 = RLSW.vertexBuffer[3].homogeneous;
+ // const float *h3 = RLSW.primitive.buffer[3].position;
// Compute a value proportional to the signed area of the triangle P0 P1 P2
- // in the projected 2D plane, calculated directly using homogeneous coordinates
+ // in the projected 2D plane, calculated directly using clip coordinates
// BEFORE division by w
// This is the determinant of the matrix formed by the (x, y, w) components
// of the vertices P0, P1, and P2. Its sign correctly indicates the winding order
- // in homogeneous space and its relationship to the projected 2D winding order,
+ // in clip space and its relationship to the projected 2D winding order,
// even with negative w values
// The determinant formula used here is:
- // h0.x*(h1.y*h2.w - h2.y*h1.w) +
- // h1.x*(h2.y*h0.w - h0.y*h2.w) +
- // h2.x*(h0.y*h1.w - h1.y*h0.w)
+ // p0.x*(p1.y*p2.w - p2.y*p1.w) +
+ // p1.x*(p2.y*p0.w - p0.y*p2.w) +
+ // p2.x*(p0.y*p1.w - p1.y*p0.w)
- const float hSgnArea =
- h0[0]*(h1[1]*h2[3] - h2[1]*h1[3]) +
- h1[0]*(h2[1]*h0[3] - h0[1]*h2[3]) +
- h2[0]*(h0[1]*h1[3] - h1[1]*h0[3]);
+ const float sgnArea =
+ p0[0]*(p1[1]*p2[3] - p2[1]*p1[3]) +
+ p1[0]*(p2[1]*p0[3] - p0[1]*p2[3]) +
+ p2[0]*(p0[1]*p1[3] - p1[1]*p0[3]);
// Perform face culling based on the winding order determined by the sign
// of the homogeneous area/determinant of triangle P0 P1 P2
// This test is robust for points with w > 0 or w < 0 within the triangle,
// correctly capturing the change in orientation when crossing the w=0 plane
- // A positive hSgnArea typically corresponds to a counter-clockwise
+ // A positive sgnArea typically corresponds to a counter-clockwise
// winding in the projected space when all w > 0
- // A value of 0 for hSgnArea means P0, P1, P2 are collinear in (x, y, w)
+ // A value of 0 for sgnArea means P0, P1, P2 are collinear in (x, y, w)
// space, which corresponds to a degenerate triangle projection
// Such quads might also be degenerate or non-planar. They are typically
// not culled by this test (0 < 0 is false, 0 > 0 is false)
// and should be handled by the clipper if necessary
- return (RLSW.cullFace == SW_FRONT)? (hSgnArea < 0.0f) : (hSgnArea > 0.0f); // Cull if winding is "clockwise" : "counter-clockwise"
+ return (RLSW.cullFace == SW_FRONT)? (sgnArea < 0.0f) : (sgnArea > 0.0f); // Cull if winding is "clockwise" : "counter-clockwise"
}
-static inline void sw_quad_clip_and_project(void)
+static void sw_quad_clip_and_project(void)
{
- sw_vertex_t *polygon = RLSW.vertexBuffer;
- int *vertexCounter = &RLSW.vertexCounter;
+ sw_vertex_t *polygon = RLSW.primitive.buffer;
+ int *vertexCounter = &RLSW.primitive.vertexCount;
if (sw_polygon_clip(polygon, vertexCounter))
{
@@ -2621,13 +3477,13 @@ static inline void sw_quad_clip_and_project(void)
// Calculation of the reciprocal of W for normalization
// as well as perspective-correct attributes
- const float wRcp = 1.0f/v->homogeneous[3];
- v->homogeneous[3] = wRcp;
+ const float wRcp = 1.0f/v->position[3];
// Division of XYZ coordinates by weight
- v->homogeneous[0] *= wRcp;
- v->homogeneous[1] *= wRcp;
- v->homogeneous[2] *= wRcp;
+ v->position[0] *= wRcp;
+ v->position[1] *= wRcp;
+ v->position[2] *= wRcp;
+ v->position[3] = wRcp;
// Division of texture coordinates (perspective-correct)
v->texcoord[0] *= wRcp;
@@ -2640,29 +3496,29 @@ static inline void sw_quad_clip_and_project(void)
v->color[3] *= wRcp;
// Transformation to screen space
- sw_project_ndc_to_screen(v->screen, v->homogeneous);
+ sw_project_ndc_to_screen(v->position);
}
}
}
-static inline bool sw_quad_is_axis_aligned(void)
+static bool sw_quad_is_axis_aligned(void)
{
// Reject quads with perspective projection
// The fast path assumes affine (non-perspective) quads,
// so it's required for all vertices to have homogeneous w = 1.0
for (int i = 0; i < 4; i++)
{
- if (RLSW.vertexBuffer[i].homogeneous[3] != 1.0f) return false;
+ if (RLSW.primitive.buffer[i].position[3] != 1.0f) return false;
}
// Epsilon tolerance in screen space (pixels)
const float epsilon = 0.5f;
// Fetch screen-space positions for the four quad vertices
- const float *p0 = RLSW.vertexBuffer[0].screen;
- const float *p1 = RLSW.vertexBuffer[1].screen;
- const float *p2 = RLSW.vertexBuffer[2].screen;
- const float *p3 = RLSW.vertexBuffer[3].screen;
+ const float *p0 = RLSW.primitive.buffer[0].position;
+ const float *p1 = RLSW.primitive.buffer[1].position;
+ const float *p2 = RLSW.primitive.buffer[2].position;
+ const float *p3 = RLSW.primitive.buffer[3].position;
// Compute edge vectors between consecutive vertices
// These define the four sides of the quad in screen space
@@ -2681,262 +3537,38 @@ static inline bool sw_quad_is_axis_aligned(void)
return true;
}
-static inline void sw_quad_sort_cw(const sw_vertex_t* *output)
+static void sw_quad_render(uint32_t state)
{
- const sw_vertex_t *input = RLSW.vertexBuffer;
-
- // Calculate the centroid of the quad
- float cx = (input[0].screen[0] + input[1].screen[0] +
- input[2].screen[0] + input[3].screen[0])*0.25f;
- float cy = (input[0].screen[1] + input[1].screen[1] +
- input[2].screen[1] + input[3].screen[1])*0.25f;
-
- // Calculate the angle of each vertex relative to the center
- // and assign them directly to their correct position
- const sw_vertex_t *corners[4] = { 0 };
-
- for (int i = 0; i < 4; i++)
- {
- float dx = input[i].screen[0] - cx;
- float dy = input[i].screen[1] - cy;
-
- // Determine the quadrant (clockwise from top-left)
- // top-left: dx < 0, dy < 0
- // top-right: dx >= 0, dy < 0
- // bottom-right: dx >= 0, dy >= 0
- // bottom-left: dx < 0, dy >= 0
-
- int idx;
- if (dy < 0) idx = (dx < 0)? 0 : 1; // Top row
- else idx = (dx < 0)? 3 : 2; // Bottom row
-
- corners[idx] = &input[i];
- }
-
- output[0] = corners[0]; // top-left
- output[1] = corners[1]; // top-right
- output[2] = corners[2]; // bottom-right
- output[3] = corners[3]; // bottom-left
-}
-
-// TODO: REVIEW: Could a perfectly aligned quad, where one of the four points has a different depth,
-// still appear perfectly aligned from a certain point of view?
-// Because in that case, it's still needed to perform perspective division for textures and colors...
-#define DEFINE_QUAD_RASTER_AXIS_ALIGNED(FUNC_NAME, ENABLE_TEXTURE, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \
-static inline void FUNC_NAME(void) \
-{ \
- const sw_vertex_t *sortedVerts[4]; \
- sw_quad_sort_cw(sortedVerts); \
- \
- const sw_vertex_t *v0 = sortedVerts[0]; \
- const sw_vertex_t *v1 = sortedVerts[1]; \
- const sw_vertex_t *v2 = sortedVerts[2]; \
- const sw_vertex_t *v3 = sortedVerts[3]; \
- \
- /* Screen bounds (axis-aligned) */ \
- int xMin = (int)v0->screen[0]; \
- int yMin = (int)v0->screen[1]; \
- int xMax = (int)v2->screen[0]; \
- int yMax = (int)v2->screen[1]; \
- \
- float w = v2->screen[0] - v0->screen[0]; \
- float h = v2->screen[1] - v0->screen[1]; \
- \
- if ((w == 0) || (h == 0)) return; \
- \
- float wRcp = (w > 0.0f)? 1.0f/w : 0.0f; \
- float hRcp = (h > 0.0f)? 1.0f/h : 0.0f; \
- \
- /* Subpixel corrections */ \
- float xSubstep = 1.0f - sw_fract(v0->screen[0]); \
- float ySubstep = 1.0f - sw_fract(v0->screen[1]); \
- \
- /* Calculation of vertex gradients in X and Y */ \
- float dUdx = 0.0f, dVdx = 0.0f; \
- float dUdy = 0.0f, dVdy = 0.0f; \
- if (ENABLE_TEXTURE) { \
- dUdx = (v1->texcoord[0] - v0->texcoord[0])*wRcp; \
- dVdx = (v1->texcoord[1] - v0->texcoord[1])*wRcp; \
- dUdy = (v3->texcoord[0] - v0->texcoord[0])*hRcp; \
- dVdy = (v3->texcoord[1] - v0->texcoord[1])*hRcp; \
- } \
- \
- float dCdx[4], dCdy[4]; \
- dCdx[0] = (v1->color[0] - v0->color[0])*wRcp; \
- dCdx[1] = (v1->color[1] - v0->color[1])*wRcp; \
- dCdx[2] = (v1->color[2] - v0->color[2])*wRcp; \
- dCdx[3] = (v1->color[3] - v0->color[3])*wRcp; \
- dCdy[0] = (v3->color[0] - v0->color[0])*hRcp; \
- dCdy[1] = (v3->color[1] - v0->color[1])*hRcp; \
- dCdy[2] = (v3->color[2] - v0->color[2])*hRcp; \
- dCdy[3] = (v3->color[3] - v0->color[3])*hRcp; \
- \
- float dZdx, dZdy; \
- dZdx = (v1->homogeneous[2] - v0->homogeneous[2])*wRcp; \
- dZdy = (v3->homogeneous[2] - v0->homogeneous[2])*hRcp; \
- \
- /* Start of quad rasterization */ \
- const sw_texture_t *tex; \
- if (ENABLE_TEXTURE) tex = &RLSW.loadedTextures[RLSW.currentTexture]; \
- \
- sw_pixel_t *pixels = RLSW.framebuffer.pixels; \
- int wDst = RLSW.framebuffer.width; \
- \
- float zScanline = v0->homogeneous[2] + dZdx*xSubstep + dZdy*ySubstep; \
- float uScanline = v0->texcoord[0] + dUdx*xSubstep + dUdy*ySubstep; \
- float vScanline = v0->texcoord[1] + dVdx*xSubstep + dVdy*ySubstep; \
- \
- float colorScanline[4] = { \
- v0->color[0] + dCdx[0]*xSubstep + dCdy[0]*ySubstep, \
- v0->color[1] + dCdx[1]*xSubstep + dCdy[1]*ySubstep, \
- v0->color[2] + dCdx[2]*xSubstep + dCdy[2]*ySubstep, \
- v0->color[3] + dCdx[3]*xSubstep + dCdy[3]*ySubstep \
- }; \
- \
- for (int y = yMin; y < yMax; y++) \
- { \
- sw_pixel_t *ptr = pixels + y*wDst + xMin; \
- \
- float z = zScanline; \
- float u = uScanline; \
- float v = vScanline; \
- \
- float color[4] = { \
- colorScanline[0], \
- colorScanline[1], \
- colorScanline[2], \
- colorScanline[3] \
- }; \
- \
- /* Scanline rasterization */ \
- for (int x = xMin; x < xMax; x++) \
- { \
- /* Pixel color computation */ \
- float srcColor[4] = { \
- color[0], \
- color[1], \
- color[2], \
- color[3] \
- }; \
- \
- /* Test and write depth */ \
- if (ENABLE_DEPTH_TEST) \
- { \
- /* TODO: Implement different depth funcs? */ \
- float depth = sw_framebuffer_read_depth(ptr); \
- if (z > depth) goto discard; \
- } \
- \
- /* TODO: Implement depth mask */ \
- sw_framebuffer_write_depth(ptr, z); \
- \
- if (ENABLE_TEXTURE) \
- { \
- float texColor[4]; \
- sw_texture_sample(texColor, tex, u, v, dUdx, dUdy, dVdx, dVdy); \
- srcColor[0] *= texColor[0]; \
- srcColor[1] *= texColor[1]; \
- srcColor[2] *= texColor[2]; \
- srcColor[3] *= texColor[3]; \
- } \
- \
- if (ENABLE_COLOR_BLEND) \
- { \
- float dstColor[4]; \
- sw_framebuffer_read_color(dstColor, ptr); \
- sw_blend_colors(dstColor, srcColor); \
- sw_framebuffer_write_color(ptr, dstColor); \
- } \
- else sw_framebuffer_write_color(ptr, srcColor); \
- \
- discard: \
- z += dZdx; \
- color[0] += dCdx[0]; \
- color[1] += dCdx[1]; \
- color[2] += dCdx[2]; \
- color[3] += dCdx[3]; \
- if (ENABLE_TEXTURE) \
- { \
- u += dUdx; \
- v += dVdx; \
- } \
- ++ptr; \
- } \
- \
- zScanline += dZdy; \
- colorScanline[0] += dCdy[0]; \
- colorScanline[1] += dCdy[1]; \
- colorScanline[2] += dCdy[2]; \
- colorScanline[3] += dCdy[3]; \
- \
- if (ENABLE_TEXTURE) \
- { \
- uScanline += dUdy; \
- vScanline += dVdy; \
- } \
- } \
-}
-
-DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned, 0, 0, 0)
-DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_TEX, 1, 0, 0)
-DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_DEPTH, 0, 1, 0)
-DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_BLEND, 0, 0, 1)
-DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_TEX_DEPTH, 1, 1, 0)
-DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_TEX_BLEND, 1, 0, 1)
-DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_DEPTH_BLEND, 0, 1, 1)
-DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_TEX_DEPTH_BLEND, 1, 1, 1)
-
-static inline void sw_quad_render(void)
-{
- if (RLSW.stateFlags & SW_STATE_CULL_FACE)
+ if (RLSW.userState & SW_STATE_CULL_FACE)
{
if (!sw_quad_face_culling()) return;
}
sw_quad_clip_and_project();
+ if (RLSW.primitive.vertexCount < 3) return;
- if (RLSW.vertexCounter < 3) return;
+ state &= SW_RASTER_QUAD_STATE_MASK;
- uint32_t state = RLSW.stateFlags;
- if (RLSW.currentTexture == 0) state &= ~SW_STATE_TEXTURE_2D;
- if ((RLSW.srcFactor == SW_ONE) && (RLSW.dstFactor == SW_ZERO)) state &= ~SW_STATE_BLEND;
-
- if ((RLSW.vertexCounter == 4) && sw_quad_is_axis_aligned())
+ if ((RLSW.primitive.vertexCount == 4) && sw_quad_is_axis_aligned())
{
- if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_TEX_DEPTH_BLEND();
- else if (SW_STATE_CHECK_EX(state, SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_DEPTH_BLEND();
- else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_TEX_BLEND();
- else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST)) sw_quad_raster_axis_aligned_TEX_DEPTH();
- else if (SW_STATE_CHECK_EX(state, SW_STATE_BLEND)) sw_quad_raster_axis_aligned_BLEND();
- else if (SW_STATE_CHECK_EX(state, SW_STATE_DEPTH_TEST)) sw_quad_raster_axis_aligned_DEPTH();
- else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D)) sw_quad_raster_axis_aligned_TEX();
- else sw_quad_raster_axis_aligned();
- return;
+ SW_RASTER_QUAD_TABLE[state](
+ &RLSW.primitive.buffer[0],
+ &RLSW.primitive.buffer[1],
+ &RLSW.primitive.buffer[2],
+ &RLSW.primitive.buffer[3]
+ );
}
-
- #define TRIANGLE_RASTER(RASTER_FUNC) \
- { \
- for (int i = 0; i < RLSW.vertexCounter - 2; i++) \
- { \
- RASTER_FUNC( \
- &RLSW.vertexBuffer[0], \
- &RLSW.vertexBuffer[i + 1], \
- &RLSW.vertexBuffer[i + 2], \
- &RLSW.loadedTextures[RLSW.currentTexture] \
- ); \
- } \
+ else
+ {
+ for (int i = 0; i < RLSW.primitive.vertexCount - 2; i++)
+ {
+ SW_RASTER_TRIANGLE_TABLE[state](
+ &RLSW.primitive.buffer[0],
+ &RLSW.primitive.buffer[i + 1],
+ &RLSW.primitive.buffer[i + 2]
+ );
+ }
}
-
- if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH_BLEND)
- else if (SW_STATE_CHECK_EX(state, SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH_BLEND)
- else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_BLEND)
- else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH)
- else if (SW_STATE_CHECK_EX(state, SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_BLEND)
- else if (SW_STATE_CHECK_EX(state, SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH)
- else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D)) TRIANGLE_RASTER(sw_triangle_raster_TEX)
- else TRIANGLE_RASTER(sw_triangle_raster)
-
- #undef TRIANGLE_RASTER
}
//-------------------------------------------------------------------------------------------
@@ -2967,32 +3599,33 @@ static inline bool sw_line_clip_coord(float q, float p, float *t0, float *t1)
return 1;
}
-static inline bool sw_line_clip(sw_vertex_t *v0, sw_vertex_t *v1)
+static bool sw_line_clip(sw_vertex_t *v0, sw_vertex_t *v1)
{
float t0 = 0.0f, t1 = 1.0f;
- float dH[4], dC[4];
+ float dH[4] = { 0 };
+ float dC[4] = { 0 };
for (int i = 0; i < 4; i++)
{
- dH[i] = v1->homogeneous[i] - v0->homogeneous[i];
+ dH[i] = v1->position[i] - v0->position[i];
dC[i] = v1->color[i] - v0->color[i];
}
// Clipping Liang-Barsky
- if (!sw_line_clip_coord(v0->homogeneous[3] - v0->homogeneous[0], -dH[3] + dH[0], &t0, &t1)) return false;
- if (!sw_line_clip_coord(v0->homogeneous[3] + v0->homogeneous[0], -dH[3] - dH[0], &t0, &t1)) return false;
- if (!sw_line_clip_coord(v0->homogeneous[3] - v0->homogeneous[1], -dH[3] + dH[1], &t0, &t1)) return false;
- if (!sw_line_clip_coord(v0->homogeneous[3] + v0->homogeneous[1], -dH[3] - dH[1], &t0, &t1)) return false;
- if (!sw_line_clip_coord(v0->homogeneous[3] - v0->homogeneous[2], -dH[3] + dH[2], &t0, &t1)) return false;
- if (!sw_line_clip_coord(v0->homogeneous[3] + v0->homogeneous[2], -dH[3] - dH[2], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->position[3] - v0->position[0], -dH[3] + dH[0], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->position[3] + v0->position[0], -dH[3] - dH[0], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->position[3] - v0->position[1], -dH[3] + dH[1], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->position[3] + v0->position[1], -dH[3] - dH[1], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->position[3] - v0->position[2], -dH[3] + dH[2], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->position[3] + v0->position[2], -dH[3] - dH[2], &t0, &t1)) return false;
// Clipping Scissor
- if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
+ if (RLSW.userState & SW_STATE_SCISSOR_TEST)
{
- if (!sw_line_clip_coord(v0->homogeneous[0] - RLSW.scClipMin[0]*v0->homogeneous[3], RLSW.scClipMin[0]*dH[3] - dH[0], &t0, &t1)) return false;
- if (!sw_line_clip_coord(RLSW.scClipMax[0]*v0->homogeneous[3] - v0->homogeneous[0], dH[0] - RLSW.scClipMax[0]*dH[3], &t0, &t1)) return false;
- if (!sw_line_clip_coord(v0->homogeneous[1] - RLSW.scClipMin[1]*v0->homogeneous[3], RLSW.scClipMin[1]*dH[3] - dH[1], &t0, &t1)) return false;
- if (!sw_line_clip_coord(RLSW.scClipMax[1]*v0->homogeneous[3] - v0->homogeneous[1], dH[1] - RLSW.scClipMax[1]*dH[3], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->position[0] - RLSW.scClipMin[0]*v0->position[3], RLSW.scClipMin[0]*dH[3] - dH[0], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(RLSW.scClipMax[0]*v0->position[3] - v0->position[0], dH[0] - RLSW.scClipMax[0]*dH[3], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->position[1] - RLSW.scClipMin[1]*v0->position[3], RLSW.scClipMin[1]*dH[3] - dH[1], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(RLSW.scClipMax[1]*v0->position[3] - v0->position[1], dH[1] - RLSW.scClipMax[1]*dH[3], &t0, &t1)) return false;
}
// Interpolation of new coordinates
@@ -3000,7 +3633,7 @@ static inline bool sw_line_clip(sw_vertex_t *v0, sw_vertex_t *v1)
{
for (int i = 0; i < 4; i++)
{
- v1->homogeneous[i] = v0->homogeneous[i] + t1*dH[i];
+ v1->position[i] = v0->position[i] + t1*dH[i];
v1->color[i] = v0->color[i] + t1*dC[i];
}
}
@@ -3009,7 +3642,7 @@ static inline bool sw_line_clip(sw_vertex_t *v0, sw_vertex_t *v1)
{
for (int i = 0; i < 4; i++)
{
- v0->homogeneous[i] += t0*dH[i];
+ v0->position[i] += t0*dH[i];
v0->color[i] += t0*dC[i];
}
}
@@ -3017,527 +3650,235 @@ static inline bool sw_line_clip(sw_vertex_t *v0, sw_vertex_t *v1)
return true;
}
-static inline bool sw_line_clip_and_project(sw_vertex_t *v0, sw_vertex_t *v1)
+static bool sw_line_clip_and_project(sw_vertex_t *v0, sw_vertex_t *v1)
{
if (!sw_line_clip(v0, v1)) return false;
- // Convert homogeneous coordinates to NDC
- v0->homogeneous[3] = 1.0f/v0->homogeneous[3];
- v1->homogeneous[3] = 1.0f/v1->homogeneous[3];
+ // Convert clip coordinates to NDC
+ v0->position[3] = 1.0f/v0->position[3];
+ v1->position[3] = 1.0f/v1->position[3];
for (int i = 0; i < 3; i++)
{
- v0->homogeneous[i] *= v0->homogeneous[3];
- v1->homogeneous[i] *= v1->homogeneous[3];
+ v0->position[i] *= v0->position[3];
+ v1->position[i] *= v1->position[3];
}
// Convert NDC coordinates to screen space
- sw_project_ndc_to_screen(v0->screen, v0->homogeneous);
- sw_project_ndc_to_screen(v1->screen, v1->homogeneous);
+ sw_project_ndc_to_screen(v0->position);
+ sw_project_ndc_to_screen(v1->position);
+
+ // NDC +1.0 projects to exactly (width + 0.5f), which truncates out of bounds
+ // The clamp is at most 0.5px on a boundary endpoint, it's visually imperceptible
+ v0->position[0] = sw_clamp(v0->position[0], 0.0f, (float)(RLSW.colorBuffer->width - 1) + 0.5f);
+ v0->position[1] = sw_clamp(v0->position[1], 0.0f, (float)(RLSW.colorBuffer->height - 1) + 0.5f);
+ v1->position[0] = sw_clamp(v1->position[0], 0.0f, (float)(RLSW.colorBuffer->width - 1) + 0.5f);
+ v1->position[1] = sw_clamp(v1->position[1], 0.0f, (float)(RLSW.colorBuffer->height - 1) + 0.5f);
return true;
}
-#define DEFINE_LINE_RASTER(FUNC_NAME, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \
-static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \
-{ \
- float x0 = v0->screen[0]; \
- float y0 = v0->screen[1]; \
- float x1 = v1->screen[0]; \
- float y1 = v1->screen[1]; \
- \
- float dx = x1 - x0; \
- float dy = y1 - y0; \
- \
- /* Compute dominant axis and subpixel offset */ \
- float steps, substep; \
- if (fabsf(dx) > fabsf(dy)) \
- { \
- steps = fabsf(dx); \
- if (steps < 1.0f) return; \
- substep = (dx >= 0.0f)? (1.0f - sw_fract(x0)) : sw_fract(x0); \
- } \
- else \
- { \
- steps = fabsf(dy); \
- if (steps < 1.0f) return; \
- substep = (dy >= 0.0f)? (1.0f - sw_fract(y0)) : sw_fract(y0); \
- } \
- \
- /* Compute per pixel increments */ \
- float xInc = dx/steps; \
- float yInc = dy/steps; \
- float stepRcp = 1.0f/steps; \
- \
- float zInc = (v1->homogeneous[2] - v0->homogeneous[2])*stepRcp; \
- float rInc = (v1->color[0] - v0->color[0])*stepRcp; \
- float gInc = (v1->color[1] - v0->color[1])*stepRcp; \
- float bInc = (v1->color[2] - v0->color[2])*stepRcp; \
- float aInc = (v1->color[3] - v0->color[3])*stepRcp; \
- \
- /* Initializing the interpolation starting values */ \
- float x = x0 + xInc*substep; \
- float y = y0 + yInc*substep; \
- float z = v0->homogeneous[2] + zInc*substep; \
- float r = v0->color[0] + rInc*substep; \
- float g = v0->color[1] + gInc*substep; \
- float b = v0->color[2] + bInc*substep; \
- float a = v0->color[3] + aInc*substep; \
- \
- const int fbWidth = RLSW.framebuffer.width; \
- sw_pixel_t *pixels = RLSW.framebuffer.pixels; \
- \
- int numPixels = (int)(steps - substep) + 1; \
- \
- for (int i = 0; i < numPixels; i++) \
- { \
- /* TODO: REVIEW: May require reviewing projection details */ \
- int px = (int)(x - 0.5f); \
- int py = (int)(y - 0.5f); \
- \
- sw_pixel_t *ptr = pixels + py*fbWidth + px; \
- \
- if (ENABLE_DEPTH_TEST) \
- { \
- float depth = sw_framebuffer_read_depth(ptr); \
- if (z > depth) goto discard; \
- } \
- \
- sw_framebuffer_write_depth(ptr, z); \
- \
- float color[4] = {r, g, b, a}; \
- \
- if (ENABLE_COLOR_BLEND) \
- { \
- float dstColor[4]; \
- sw_framebuffer_read_color(dstColor, ptr); \
- sw_blend_colors(dstColor, color); \
- sw_framebuffer_write_color(ptr, dstColor); \
- } \
- else sw_framebuffer_write_color(ptr, color); \
- \
- discard: \
- x += xInc; y += yInc; z += zInc; \
- r += rInc; g += gInc; b += bInc; a += aInc; \
- } \
-}
-
-#define DEFINE_LINE_THICK_RASTER(FUNC_NAME, RASTER_FUNC) \
-void FUNC_NAME(const sw_vertex_t *v1, const sw_vertex_t *v2) \
-{ \
- sw_vertex_t tv1, tv2; \
- \
- int x1 = (int)v1->screen[0]; \
- int y1 = (int)v1->screen[1]; \
- int x2 = (int)v2->screen[0]; \
- int y2 = (int)v2->screen[1]; \
- \
- int dx = x2 - x1; \
- int dy = y2 - y1; \
- \
- RASTER_FUNC(v1, v2); \
- \
- if ((dx != 0) && (abs(dy/dx) < 1)) \
- { \
- int wy = (int)((RLSW.lineWidth - 1.0f)*abs(dx)/sqrtf(dx*dx + dy*dy)); \
- wy >>= 1; \
- for (int i = 1; i <= wy; i++) \
- { \
- tv1 = *v1, tv2 = *v2; \
- tv1.screen[1] -= i; \
- tv2.screen[1] -= i; \
- RASTER_FUNC(&tv1, &tv2); \
- tv1 = *v1, tv2 = *v2; \
- tv1.screen[1] += i; \
- tv2.screen[1] += i; \
- RASTER_FUNC(&tv1, &tv2); \
- } \
- } \
- else if (dy != 0) \
- { \
- int wx = (int)((RLSW.lineWidth - 1.0f)*abs(dy)/sqrtf(dx*dx + dy*dy)); \
- wx >>= 1; \
- for (int i = 1; i <= wx; i++) \
- { \
- tv1 = *v1, tv2 = *v2; \
- tv1.screen[0] -= i; \
- tv2.screen[0] -= i; \
- RASTER_FUNC(&tv1, &tv2); \
- tv1 = *v1, tv2 = *v2; \
- tv1.screen[0] += i; \
- tv2.screen[0] += i; \
- RASTER_FUNC(&tv1, &tv2); \
- } \
- } \
-}
-
-DEFINE_LINE_RASTER(sw_line_raster, 0, 0)
-DEFINE_LINE_RASTER(sw_line_raster_DEPTH, 1, 0)
-DEFINE_LINE_RASTER(sw_line_raster_BLEND, 0, 1)
-DEFINE_LINE_RASTER(sw_line_raster_DEPTH_BLEND, 1, 1)
-
-DEFINE_LINE_THICK_RASTER(sw_line_thick_raster, sw_line_raster)
-DEFINE_LINE_THICK_RASTER(sw_line_thick_raster_DEPTH, sw_line_raster_DEPTH)
-DEFINE_LINE_THICK_RASTER(sw_line_thick_raster_BLEND, sw_line_raster_BLEND)
-DEFINE_LINE_THICK_RASTER(sw_line_thick_raster_DEPTH_BLEND, sw_line_raster_DEPTH_BLEND)
-
-static inline void sw_line_render(sw_vertex_t *vertices)
+static void sw_line_render(uint32_t state, sw_vertex_t *vertices)
{
if (!sw_line_clip_and_project(&vertices[0], &vertices[1])) return;
+ state &= SW_RASTER_LINE_STATE_MASK;
+
if (RLSW.lineWidth >= 2.0f)
{
- if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_line_thick_raster_DEPTH_BLEND(&vertices[0], &vertices[1]);
- else if (SW_STATE_CHECK(SW_STATE_BLEND)) sw_line_thick_raster_BLEND(&vertices[0], &vertices[1]);
- else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) sw_line_thick_raster_DEPTH(&vertices[0], &vertices[1]);
- else sw_line_thick_raster(&vertices[0], &vertices[1]);
+ SW_RASTER_LINE_THICK_TABLE[state](&vertices[0], &vertices[1]);
}
else
{
- if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_line_raster_DEPTH_BLEND(&vertices[0], &vertices[1]);
- else if (SW_STATE_CHECK(SW_STATE_BLEND)) sw_line_raster_BLEND(&vertices[0], &vertices[1]);
- else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) sw_line_raster_DEPTH(&vertices[0], &vertices[1]);
- else sw_line_raster(&vertices[0], &vertices[1]);
+ SW_RASTER_LINE_TABLE[state](&vertices[0], &vertices[1]);
}
}
//-------------------------------------------------------------------------------------------
// Point rendering logic
//-------------------------------------------------------------------------------------------
-static inline bool sw_point_clip_and_project(sw_vertex_t *v)
+static bool sw_point_clip_and_project(sw_vertex_t *v)
{
- if (v->homogeneous[3] != 1.0f)
+ if (v->position[3] != 1.0f)
{
for (int_fast8_t i = 0; i < 3; i++)
{
- if ((v->homogeneous[i] < -v->homogeneous[3]) || (v->homogeneous[i] > v->homogeneous[3])) return false;
+ if ((v->position[i] < -v->position[3]) || (v->position[i] > v->position[3])) return false;
}
- v->homogeneous[3] = 1.0f/v->homogeneous[3];
- v->homogeneous[0] *= v->homogeneous[3];
- v->homogeneous[1] *= v->homogeneous[3];
- v->homogeneous[2] *= v->homogeneous[3];
+ v->position[3] = 1.0f/v->position[3];
+ v->position[0] *= v->position[3];
+ v->position[1] *= v->position[3];
+ v->position[2] *= v->position[3];
}
- sw_project_ndc_to_screen(v->screen, v->homogeneous);
+ sw_project_ndc_to_screen(v->position);
- const int *min = NULL, *max = NULL;
+ int min[2] = { 0, 0 };
+ int max[2] = { RLSW.colorBuffer->width, RLSW.colorBuffer->height };
- if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
+ if (RLSW.userState & SW_STATE_SCISSOR_TEST)
{
- min = RLSW.scMin;
- max = RLSW.scMax;
- }
- else
- {
- min = RLSW.vpMin;
- max = RLSW.vpMax;
+ min[0] = sw_clamp_int(RLSW.scMin[0], 0, RLSW.colorBuffer->width);
+ min[1] = sw_clamp_int(RLSW.scMin[1], 0, RLSW.colorBuffer->height);
+ max[0] = sw_clamp_int(RLSW.scMax[0], 0, RLSW.colorBuffer->width);
+ max[1] = sw_clamp_int(RLSW.scMax[1], 0, RLSW.colorBuffer->height);
}
- bool insideX = (v->screen[0] - RLSW.pointRadius < max[0]) && (v->screen[0] + RLSW.pointRadius > min[0]);
- bool insideY = (v->screen[1] - RLSW.pointRadius < max[1]) && (v->screen[1] + RLSW.pointRadius > min[1]);
+ bool insideX = (v->position[0] - RLSW.pointRadius < max[0]) && (v->position[0] + RLSW.pointRadius > min[0]);
+ bool insideY = (v->position[1] - RLSW.pointRadius < max[1]) && (v->position[1] + RLSW.pointRadius > min[1]);
return (insideX && insideY);
}
-#define DEFINE_POINT_RASTER(FUNC_NAME, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND, CHECK_BOUNDS) \
-static inline void FUNC_NAME(int x, int y, float z, const float color[4]) \
-{ \
- if (CHECK_BOUNDS == 1) \
- { \
- if ((x < RLSW.vpMin[0]) || (x >= RLSW.vpMax[0])) return; \
- if ((y < RLSW.vpMin[1]) || (y >= RLSW.vpMax[1])) return; \
- } \
- else if (CHECK_BOUNDS == SW_SCISSOR_TEST) \
- { \
- if ((x < RLSW.scMin[0]) || (x >= RLSW.scMax[0])) return; \
- if ((y < RLSW.scMin[1]) || (y >= RLSW.scMax[1])) return; \
- } \
- \
- int offset = y*RLSW.framebuffer.width + x; \
- sw_pixel_t *ptr = RLSW.framebuffer.pixels + offset; \
- \
- if (ENABLE_DEPTH_TEST) \
- { \
- float depth = sw_framebuffer_read_depth(ptr); \
- if (z > depth) return; \
- } \
- \
- sw_framebuffer_write_depth(ptr, z); \
- \
- if (ENABLE_COLOR_BLEND) \
- { \
- float dstColor[4]; \
- sw_framebuffer_read_color(dstColor, ptr); \
- sw_blend_colors(dstColor, color); \
- sw_framebuffer_write_color(ptr, dstColor); \
- } \
- else sw_framebuffer_write_color(ptr, color); \
-}
-
-#define DEFINE_POINT_THICK_RASTER(FUNC_NAME, RASTER_FUNC) \
-static inline void FUNC_NAME(sw_vertex_t *v) \
-{ \
- int cx = v->screen[0]; \
- int cy = v->screen[1]; \
- float cz = v->homogeneous[2]; \
- int radius = RLSW.pointRadius; \
- const float *color = v->color; \
- \
- int x = 0; \
- int y = radius; \
- int d = 3 - 2*radius; \
- \
- while (x <= y) \
- { \
- for (int i = -x; i <= x; i++) \
- { \
- RASTER_FUNC(cx + i, cy + y, cz, color); \
- RASTER_FUNC(cx + i, cy - y, cz, color); \
- } \
- for (int i = -y; i <= y; i++) \
- { \
- RASTER_FUNC(cx + i, cy + x, cz, color); \
- RASTER_FUNC(cx + i, cy - x, cz, color); \
- } \
- if (d > 0) \
- { \
- y--; \
- d = d + 4*(x - y) + 10; \
- } \
- else d = d + 4*x + 6; \
- x++; \
- } \
-}
-
-DEFINE_POINT_RASTER(sw_point_raster, 0, 0, 0)
-DEFINE_POINT_RASTER(sw_point_raster_DEPTH, 1, 0, 0)
-DEFINE_POINT_RASTER(sw_point_raster_BLEND, 0, 1, 0)
-DEFINE_POINT_RASTER(sw_point_raster_DEPTH_BLEND, 1, 1, 0)
-
-DEFINE_POINT_RASTER(sw_point_raster_CHECK, 0, 0, 1)
-DEFINE_POINT_RASTER(sw_point_raster_DEPTH_CHECK, 1, 0, 1)
-DEFINE_POINT_RASTER(sw_point_raster_BLEND_CHECK, 0, 1, 1)
-DEFINE_POINT_RASTER(sw_point_raster_DEPTH_BLEND_CHECK, 1, 1, 1)
-
-DEFINE_POINT_RASTER(sw_point_raster_CHECK_SCISSOR, 0, 0, SW_SCISSOR_TEST)
-DEFINE_POINT_RASTER(sw_point_raster_DEPTH_CHECK_SCISSOR, 1, 0, SW_SCISSOR_TEST)
-DEFINE_POINT_RASTER(sw_point_raster_BLEND_CHECK_SCISSOR, 0, 1, SW_SCISSOR_TEST)
-DEFINE_POINT_RASTER(sw_point_raster_DEPTH_BLEND_CHECK_SCISSOR, 1, 1, SW_SCISSOR_TEST)
-
-DEFINE_POINT_THICK_RASTER(sw_point_thick_raster, sw_point_raster_CHECK)
-DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_DEPTH, sw_point_raster_DEPTH_CHECK)
-DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_BLEND, sw_point_raster_BLEND_CHECK)
-DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_DEPTH_BLEND, sw_point_raster_DEPTH_BLEND_CHECK)
-
-DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_SCISSOR, sw_point_raster_CHECK_SCISSOR)
-DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_DEPTH_SCISSOR, sw_point_raster_DEPTH_CHECK_SCISSOR)
-DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_BLEND_SCISSOR, sw_point_raster_BLEND_CHECK_SCISSOR)
-DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_DEPTH_BLEND_SCISSOR, sw_point_raster_DEPTH_BLEND_CHECK_SCISSOR)
-
-static inline void sw_point_render(sw_vertex_t *v)
+static void sw_point_render(uint32_t state, sw_vertex_t *v)
{
if (!sw_point_clip_and_project(v)) return;
-
- if (RLSW.pointRadius >= 1.0f)
- {
- if (SW_STATE_CHECK(SW_STATE_SCISSOR_TEST))
- {
- if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_point_thick_raster_DEPTH_BLEND_SCISSOR(v);
- else if (SW_STATE_CHECK(SW_STATE_BLEND)) sw_point_thick_raster_BLEND_SCISSOR(v);
- else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) sw_point_thick_raster_DEPTH_SCISSOR(v);
- else sw_point_thick_raster_SCISSOR(v);
- }
- else
- {
- if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_point_thick_raster_DEPTH_BLEND(v);
- else if (SW_STATE_CHECK(SW_STATE_BLEND)) sw_point_thick_raster_BLEND(v);
- else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) sw_point_thick_raster_DEPTH(v);
- else sw_point_thick_raster(v);
- }
- }
- else
- {
- if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_point_raster_DEPTH_BLEND(v->screen[0], v->screen[1], v->homogeneous[2], v->color);
- else if (SW_STATE_CHECK(SW_STATE_BLEND)) sw_point_raster_BLEND(v->screen[0], v->screen[1], v->homogeneous[2], v->color);
- else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) sw_point_raster_DEPTH(v->screen[0], v->screen[1], v->homogeneous[2], v->color);
- else sw_point_raster(v->screen[0], v->screen[1], v->homogeneous[2], v->color);
- }
+ state &= SW_RASTER_POINT_STATE_MASK;
+ SW_RASTER_POINT_TABLE[state](v);
}
//-------------------------------------------------------------------------------------------
// Polygon modes rendering logic
//-------------------------------------------------------------------------------------------
-static inline void sw_poly_point_render(void)
+static inline void sw_poly_point_render(uint32_t state)
{
- for (int i = 0; i < RLSW.vertexCounter; i++) sw_point_render(&RLSW.vertexBuffer[i]);
+ for (int i = 0; i < RLSW.primitive.vertexCount; i++) sw_point_render(state, &RLSW.primitive.buffer[i]);
}
-static inline void sw_poly_line_render(void)
+static inline void sw_poly_line_render(uint32_t state)
{
- const sw_vertex_t *vertices = RLSW.vertexBuffer;
- int cm1 = RLSW.vertexCounter - 1;
+ const sw_vertex_t *vertices = RLSW.primitive.buffer;
+ int cm1 = RLSW.primitive.vertexCount - 1;
for (int i = 0; i < cm1; i++)
{
sw_vertex_t verts[2] = { vertices[i], vertices[i + 1] };
- sw_line_render(verts);
+ sw_line_render(state, verts);
}
sw_vertex_t verts[2] = { vertices[cm1], vertices[0] };
- sw_line_render(verts);
+ sw_line_render(state, verts);
}
-static inline void sw_poly_fill_render(void)
+static inline void sw_poly_fill_render(uint32_t state)
{
switch (RLSW.drawMode)
{
- case SW_POINTS: sw_point_render(&RLSW.vertexBuffer[0]); break;
- case SW_LINES: sw_line_render(RLSW.vertexBuffer); break;
- case SW_TRIANGLES: sw_triangle_render(); break;
- case SW_QUADS: sw_quad_render(); break;
+ case SW_POINTS: sw_point_render(state, &RLSW.primitive.buffer[0]); break;
+ case SW_LINES: sw_line_render(state, RLSW.primitive.buffer); break;
+ case SW_TRIANGLES: sw_triangle_render(state); break;
+ case SW_QUADS: sw_quad_render(state); break;
+ default: break;
}
}
//-------------------------------------------------------------------------------------------
// Immediate rendering logic
//-------------------------------------------------------------------------------------------
-void sw_immediate_push_vertex(const float position[4], const float color[4], const float texcoord[2])
+static void sw_immediate_begin(SWdraw mode)
{
- // Copy the attributes in the current vertex
- sw_vertex_t *vertex = &RLSW.vertexBuffer[RLSW.vertexCounter++];
- for (int i = 0; i < 4; i++)
+ // NOTE: Any checks to ensure command recording can start
+ // must be performed before calling this function.
+
+ // Recalculate the MVP if this is needed
+ if (RLSW.isDirtyMVP)
{
- vertex->position[i] = position[i];
- if (i < 2) vertex->texcoord[i] = texcoord[i];
- vertex->color[i] = color[i];
+ sw_matrix_mul_rst(RLSW.matMVP,
+ RLSW.stackModelview[RLSW.stackModelviewCounter - 1],
+ RLSW.stackProjection[RLSW.stackProjectionCounter - 1]);
+
+ RLSW.isDirtyMVP = false;
}
- // Calculate homogeneous coordinates
- const float *m = RLSW.matMVP, *v = vertex->position;
- vertex->homogeneous[0] = m[0]*v[0] + m[4]*v[1] + m[8]*v[2] + m[12]*v[3];
- vertex->homogeneous[1] = m[1]*v[0] + m[5]*v[1] + m[9]*v[2] + m[13]*v[3];
- vertex->homogeneous[2] = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3];
- vertex->homogeneous[3] = m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3];
+ // Disable pipeline states that are incompatible with the global state
+ uint32_t state = RLSW.userState;
+ if (!sw_is_texture_complete(RLSW.depthBuffer)) state &= ~SW_STATE_DEPTH_TEST;
+ if (!sw_is_texture_complete(RLSW.boundTexture)) state &= ~SW_STATE_TEXTURE_2D;
+ else if (sw_pixel_is_depth_format(RLSW.boundTexture->format)) state &= ~SW_STATE_TEXTURE_2D;
+
+ // Initialize required values
+ RLSW.primitive.hasColorAlpha = false;
+ RLSW.primitive.vertexCount = 0;
+ RLSW.rasterState = state;
+ RLSW.drawMode = mode;
+}
+
+static bool sw_immediate_is_active(void)
+{
+ return (RLSW.drawMode != SW_DRAW_INVALID);
+}
+
+static void sw_immediate_set_color(const float color[4])
+{
+ RLSW.primitive.color[0] = color[0];
+ RLSW.primitive.color[1] = color[1];
+ RLSW.primitive.color[2] = color[2];
+ RLSW.primitive.color[3] = color[3];
+
+ RLSW.primitive.hasColorAlpha |= (color[3] < 1.0f);
+}
+
+static void sw_immediate_set_texcoord(const float texcoord[2])
+{
+ const float *m = RLSW.stackTexture[RLSW.stackTextureCounter - 1];
+ RLSW.primitive.texcoord[0] = m[0]*texcoord[0] + m[4]*texcoord[1] + m[12];
+ RLSW.primitive.texcoord[1] = m[1]*texcoord[0] + m[5]*texcoord[1] + m[13];
+}
+
+static void sw_immediate_push_vertex(const float position[4])
+{
+ // Check if the draw mode is valid
+ if (!sw_is_draw_mode_valid(RLSW.drawMode))
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ // Gets the current vertex
+ sw_vertex_t *vertex = &RLSW.primitive.buffer[RLSW.primitive.vertexCount++];
+
+ // Calculate clip coordinates
+ const float *m = RLSW.matMVP;
+ vertex->position[0] = m[0]*position[0] + m[4]*position[1] + m[8]*position[2] + m[12]*position[3];
+ vertex->position[1] = m[1]*position[0] + m[5]*position[1] + m[9]*position[2] + m[13]*position[3];
+ vertex->position[2] = m[2]*position[0] + m[6]*position[1] + m[10]*position[2] + m[14]*position[3];
+ vertex->position[3] = m[3]*position[0] + m[7]*position[1] + m[11]*position[2] + m[15]*position[3];
+
+ // Copy the attributes in the current vertex
+ for (int i = 0; i < 4; i++) vertex->color[i] = RLSW.primitive.color[i];
+ for (int i = 0; i < 2; i++) vertex->texcoord[i] = RLSW.primitive.texcoord[i];
// Immediate rendering of the primitive if the required number is reached
- if (RLSW.vertexCounter == RLSW.reqVertices)
+ if (RLSW.primitive.vertexCount == SW_PRIMITIVE_VERTEX_COUNT[RLSW.drawMode])
{
+ uint32_t state = RLSW.rasterState;
+
+ // Reduces blend mode costs when it's possible
+ if (state & SW_STATE_BLEND)
+ {
+ if (RLSW.blendFlags & SW_BLEND_FLAG_NOOP) state &= ~SW_STATE_BLEND;
+ else if ((RLSW.blendFlags & SW_BLEND_FLAG_NEEDS_ALPHA) && (!RLSW.primitive.hasColorAlpha))
+ {
+ if (!(state & SW_STATE_TEXTURE_2D) || (RLSW.boundTexture->alpha == SW_PIXEL_ALPHA_NONE)) state &= ~SW_STATE_BLEND;
+ }
+ }
+
switch (RLSW.polyMode)
{
- case SW_FILL: sw_poly_fill_render(); break;
- case SW_LINE: sw_poly_line_render(); break;
- case SW_POINT: sw_poly_point_render(); break;
+ case SW_FILL: sw_poly_fill_render(state); break;
+ case SW_LINE: sw_poly_line_render(state); break;
+ case SW_POINT: sw_poly_point_render(state); break;
default: break;
}
- RLSW.vertexCounter = 0;
+ RLSW.primitive.hasColorAlpha = false;
+ RLSW.primitive.vertexCount = 0;
}
}
-//-------------------------------------------------------------------------------------------
-
-// Validity check helper functions
-//-------------------------------------------------------------------------------------------
-static inline bool sw_is_texture_valid(uint32_t id)
+static void sw_immediate_end(void)
{
- bool valid = true;
-
- if (id == 0) valid = false;
- else if (id >= SW_MAX_TEXTURES) valid = false;
- else if (RLSW.loadedTextures[id].pixels == NULL) valid = false;
-
- return valid;
-}
-
-static inline bool sw_is_texture_filter_valid(int filter)
-{
- return ((filter == SW_NEAREST) || (filter == SW_LINEAR));
-}
-
-static inline bool sw_is_texture_wrap_valid(int wrap)
-{
- return ((wrap == SW_REPEAT) || (wrap == SW_CLAMP));
-}
-
-static inline bool sw_is_draw_mode_valid(int mode)
-{
- bool result = false;
-
- switch (mode)
- {
- case SW_POINTS:
- case SW_LINES:
- case SW_TRIANGLES:
- case SW_QUADS: result = true; break;
- default: break;
- }
-
- return result;
-}
-
-static inline bool sw_is_poly_mode_valid(int mode)
-{
- bool result = false;
-
- switch (mode)
- {
- case SW_POINT:
- case SW_LINE:
- case SW_FILL: result = true; break;
- default: break;
- }
-
- return result;
-}
-
-static inline bool sw_is_face_valid(int face)
-{
- return (face == SW_FRONT || face == SW_BACK);
-}
-
-static inline bool sw_is_blend_src_factor_valid(int blend)
-{
- bool result = false;
-
- switch (blend)
- {
- case SW_ZERO:
- case SW_ONE:
- case SW_SRC_COLOR:
- case SW_ONE_MINUS_SRC_COLOR:
- case SW_SRC_ALPHA:
- case SW_ONE_MINUS_SRC_ALPHA:
- case SW_DST_ALPHA:
- case SW_ONE_MINUS_DST_ALPHA:
- case SW_DST_COLOR:
- case SW_ONE_MINUS_DST_COLOR:
- case SW_SRC_ALPHA_SATURATE: result = true; break;
- default: break;
- }
-
- return result;
-}
-
-static inline bool sw_is_blend_dst_factor_valid(int blend)
-{
- bool result = false;
-
- switch (blend)
- {
- case SW_ZERO:
- case SW_ONE:
- case SW_SRC_COLOR:
- case SW_ONE_MINUS_SRC_COLOR:
- case SW_SRC_ALPHA:
- case SW_ONE_MINUS_SRC_ALPHA:
- case SW_DST_ALPHA:
- case SW_ONE_MINUS_DST_ALPHA:
- case SW_DST_COLOR:
- case SW_ONE_MINUS_DST_COLOR: result = true; break;
- default: break;
- }
-
- return result;
+ RLSW.drawMode = SW_DRAW_INVALID;
}
//-------------------------------------------------------------------------------------------
@@ -3546,20 +3887,35 @@ static inline bool sw_is_blend_dst_factor_valid(int blend)
//----------------------------------------------------------------------------------
bool swInit(int w, int h)
{
- if (!sw_framebuffer_load(w, h)) { swClose(); return false; }
+ if (!sw_default_framebuffer_alloc(&RLSW.framebuffer, w, h))
+ {
+ swClose();
+ return false;
+ }
+
+ if (!sw_pool_init(&RLSW.framebufferPool, SW_MAX_FRAMEBUFFERS, sizeof(sw_framebuffer_t)))
+ {
+ swClose();
+ return false;
+ }
+
+ if (!sw_pool_init(&RLSW.texturePool, SW_MAX_TEXTURES, sizeof(sw_texture_t)))
+ {
+ swClose();
+ return false;
+ }
+
+ RLSW.colorBuffer = &RLSW.framebuffer.color;
+ RLSW.depthBuffer = &RLSW.framebuffer.depth;
swViewport(0, 0, w, h);
swScissor(0, 0, w, h);
- RLSW.loadedTextures = (sw_texture_t *)SW_MALLOC(SW_MAX_TEXTURES*sizeof(sw_texture_t));
- if (RLSW.loadedTextures == NULL) { swClose(); return false; }
-
- RLSW.freeTextureIds = (uint32_t *)SW_MALLOC(SW_MAX_TEXTURES*sizeof(uint32_t));
- if (RLSW.loadedTextures == NULL) { swClose(); return false; }
-
- const float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
- sw_framebuffer_write_color(&RLSW.clearValue, clearColor);
- sw_framebuffer_write_depth(&RLSW.clearValue, 1.0f);
+ RLSW.clearColor[0] = 0.0f;
+ RLSW.clearColor[1] = 0.0f;
+ RLSW.clearColor[2] = 0.0f;
+ RLSW.clearColor[3] = 1.0f;
+ RLSW.clearDepth = 1.0f;
RLSW.currentMatrixMode = SW_MODELVIEW;
RLSW.currentMatrix = &RLSW.stackModelview[0];
@@ -3574,43 +3930,25 @@ bool swInit(int w, int h)
RLSW.stackTextureCounter = 1;
RLSW.isDirtyMVP = false;
- RLSW.current.texcoord[0] = 0.0f;
- RLSW.current.texcoord[1] = 0.0f;
+ RLSW.primitive.texcoord[0] = 0.0f;
+ RLSW.primitive.texcoord[1] = 0.0f;
- RLSW.current.color[0] = 1.0f;
- RLSW.current.color[1] = 1.0f;
- RLSW.current.color[2] = 1.0f;
- RLSW.current.color[3] = 1.0f;
+ RLSW.primitive.color[0] = 1.0f;
+ RLSW.primitive.color[1] = 1.0f;
+ RLSW.primitive.color[2] = 1.0f;
+ RLSW.primitive.color[3] = 1.0f;
RLSW.srcFactor = SW_SRC_ALPHA;
RLSW.dstFactor = SW_ONE_MINUS_SRC_ALPHA;
+ RLSW.blendFunc = sw_blend_SRC_ALPHA_ONE_MINUS_SRC_ALPHA;
- RLSW.srcFactorFunc = sw_factor_src_alpha;
- RLSW.dstFactorFunc = sw_factor_one_minus_src_alpha;
-
+ RLSW.drawMode = SW_DRAW_INVALID;
RLSW.polyMode = SW_FILL;
RLSW.cullFace = SW_BACK;
- static uint32_t defaultTex[3*2*2] = {
- 0xFFFFFFFF,
- 0xFFFFFFFF,
- 0xFFFFFFFF,
- 0xFFFFFFFF
- };
-
- RLSW.loadedTextures[0].pixels = (uint8_t*)defaultTex;
- RLSW.loadedTextures[0].width = 2;
- RLSW.loadedTextures[0].height = 2;
- RLSW.loadedTextures[0].wMinus1 = 1;
- RLSW.loadedTextures[0].hMinus1 = 1;
- RLSW.loadedTextures[0].minFilter = SW_NEAREST;
- RLSW.loadedTextures[0].magFilter = SW_NEAREST;
- RLSW.loadedTextures[0].sWrap = SW_REPEAT;
- RLSW.loadedTextures[0].tWrap = SW_REPEAT;
- RLSW.loadedTextures[0].tx = 0.5f;
- RLSW.loadedTextures[0].ty = 0.5f;
-
- RLSW.loadedTextureCount = 1;
+#if SW_USE_COLOR_LUT
+ for (int i = 0; i < 256; i++) SW_LUT_UINT8_TO_FLOAT[i] = (float)i*SW_INV_255;
+#endif
SW_LOG("INFO: RLSW: Software renderer initialized successfully\n");
#if defined(SW_HAS_FMA_AVX) && defined(SW_HAS_FMA_AVX2)
@@ -3634,130 +3972,101 @@ bool swInit(int w, int h)
void swClose(void)
{
- // NOTE: Starts at texture 1, texture 0 does not have to be freed
- for (int i = 1; i < RLSW.loadedTextureCount; i++)
+ for (int i = 1; i < RLSW.texturePool.watermark; i++)
{
- if (sw_is_texture_valid(i))
+ if (RLSW.texturePool.gen[i] & SW_POOL_SLOT_LIVE)
{
- SW_FREE(RLSW.loadedTextures[i].pixels);
+ sw_texture_free((sw_texture_t *)RLSW.texturePool.data + i);
}
}
- SW_FREE(RLSW.framebuffer.pixels);
- SW_FREE(RLSW.loadedTextures);
- SW_FREE(RLSW.freeTextureIds);
+ sw_pool_destroy(&RLSW.texturePool);
+ sw_pool_destroy(&RLSW.framebufferPool);
+ sw_default_framebuffer_free(&RLSW.framebuffer);
RLSW = SW_CURLY_INIT(sw_context_t) { 0 };
}
-bool swResizeFramebuffer(int w, int h)
+bool swResize(int w, int h)
{
- return sw_framebuffer_resize(w, h);
+ return sw_default_framebuffer_alloc(&RLSW.framebuffer, w, h);
}
-void swCopyFramebuffer(int x, int y, int w, int h, SWformat format, SWtype type, void *pixels)
+void swReadPixels(int x, int y, int w, int h, SWformat format, SWtype type, void *pixels)
{
- sw_pixelformat_t pFormat = (sw_pixelformat_t)sw_get_pixel_format(format, type);
+ // REVIEW: Handle depth buffer copy here or consider it as an error ?
+ if (format == SW_DEPTH_COMPONENT) { RLSW.errCode = SW_INVALID_ENUM; return; }
+
+ sw_pixelformat_t pFormat = (sw_pixelformat_t)sw_pixel_get_format(format, type);
+ if (pFormat <= SW_PIXELFORMAT_UNKNOWN) { RLSW.errCode = SW_INVALID_ENUM; return; }
if (w <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; }
if (h <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; }
- if (w > RLSW.framebuffer.width) w = RLSW.framebuffer.width;
- if (h > RLSW.framebuffer.height) h = RLSW.framebuffer.height;
+ if (w > RLSW.colorBuffer->width) w = RLSW.colorBuffer->width;
+ if (h > RLSW.colorBuffer->height) h = RLSW.colorBuffer->height;
- x = sw_clampi(x, 0, w);
- y = sw_clampi(y, 0, h);
+ x = sw_clamp_int(x, 0, w);
+ y = sw_clamp_int(y, 0, h);
if ((x >= w) || (y >= h)) return;
- if ((x == 0) && (y == 0) && (w == RLSW.framebuffer.width) && (h == RLSW.framebuffer.height))
+ if ((pFormat == SW_FRAMEBUFFER_COLOR_FORMAT) && (x == 0) && (y == 0) && (w == RLSW.colorBuffer->width) && (h == RLSW.colorBuffer->height))
{
- #if SW_COLOR_BUFFER_BITS == 32
- if (pFormat == SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)
- {
- sw_framebuffer_copy_fast(pixels);
- return;
- }
- #elif SW_COLOR_BUFFER_BITS == 16
- if (pFormat == SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5)
- {
- sw_framebuffer_copy_fast(pixels);
- return;
- }
- #endif
+ sw_framebuffer_output_fast(pixels, RLSW.colorBuffer);
}
-
- switch (pFormat)
+ else
{
- case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_framebuffer_copy_to_GRAYALPHA(x, y, w, h, (uint8_t *)pixels); break;
- case SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: sw_framebuffer_copy_to_GRAYALPHA(x, y, w, h, (uint8_t *)pixels); break;
- case SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5: sw_framebuffer_copy_to_R5G6B5(x, y, w, h, (uint16_t *)pixels); break;
- case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8: sw_framebuffer_copy_to_R8G8B8(x, y, w, h, (uint8_t *)pixels); break;
- case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: sw_framebuffer_copy_to_R5G5B5A1(x, y, w, h, (uint16_t *)pixels); break;
- case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: sw_framebuffer_copy_to_R4G4B4A4(x, y, w, h, (uint16_t *)pixels); break;
- //case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: sw_framebuffer_copy_to_R8G8B8A8(x, y, w, h, (uint8_t *)pixels); break;
- // Below: not implemented
- case SW_PIXELFORMAT_UNCOMPRESSED_R32:
- case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32:
- case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
- case SW_PIXELFORMAT_UNCOMPRESSED_R16:
- case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16:
- case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:
- default: RLSW.errCode = SW_INVALID_ENUM; break;
+ sw_framebuffer_output_copy(pixels, RLSW.colorBuffer, x, y, w, h, pFormat);
}
}
-void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, SWformat format, SWtype type, void *pixels)
+void swBlitPixels(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, SWformat format, SWtype type, void *pixels)
{
- sw_pixelformat_t pFormat = (sw_pixelformat_t)sw_get_pixel_format(format, type);
+ // REVIEW: Handle depth buffer copy here or consider it as an error ?
+ if (format == SW_DEPTH_COMPONENT) { RLSW.errCode = SW_INVALID_ENUM; return; }
+
+ sw_pixelformat_t pFormat = (sw_pixelformat_t)sw_pixel_get_format(format, type);
+ if (pFormat <= SW_PIXELFORMAT_UNKNOWN) { RLSW.errCode = SW_INVALID_ENUM; return; }
if (wSrc <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; }
if (hSrc <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; }
- if (wSrc > RLSW.framebuffer.width) wSrc = RLSW.framebuffer.width;
- if (hSrc > RLSW.framebuffer.height) hSrc = RLSW.framebuffer.height;
+ if (wSrc > RLSW.colorBuffer->width) wSrc = RLSW.colorBuffer->width;
+ if (hSrc > RLSW.colorBuffer->height) hSrc = RLSW.colorBuffer->height;
- xSrc = sw_clampi(xSrc, 0, wSrc);
- ySrc = sw_clampi(ySrc, 0, hSrc);
+ xSrc = sw_clamp_int(xSrc, 0, wSrc);
+ ySrc = sw_clamp_int(ySrc, 0, hSrc);
// Check if the sizes are identical after clamping the source to avoid unexpected issues
// TODO: REVIEW: This repeats the operations if true, so a copy function can be made without these checks
- if (xDst == xSrc && yDst == ySrc && wDst == wSrc && hDst == hSrc)
+ if ((xDst == xSrc) && (yDst == ySrc) && (wDst == wSrc) && (hDst == hSrc))
{
- swCopyFramebuffer(xSrc, ySrc, wSrc, hSrc, format, type, pixels);
+ swReadPixels(xSrc, ySrc, wSrc, hSrc, format, type, pixels);
}
+ else
+ {
+ sw_framebuffer_output_blit(pixels, RLSW.colorBuffer, xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pFormat);
+ }
+}
- switch (pFormat)
- {
- case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_framebuffer_blit_to_GRAYALPHA(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break;
- case SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: sw_framebuffer_blit_to_GRAYALPHA(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break;
- case SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5: sw_framebuffer_blit_to_R5G6B5(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint16_t *)pixels); break;
- case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8: sw_framebuffer_blit_to_R8G8B8(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break;
- case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: sw_framebuffer_blit_to_R5G5B5A1(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint16_t *)pixels); break;
- case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: sw_framebuffer_blit_to_R4G4B4A4(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint16_t *)pixels); break;
- case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: sw_framebuffer_blit_to_R8G8B8A8(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break;
- // Below: not implemented
- case SW_PIXELFORMAT_UNCOMPRESSED_R32:
- case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32:
- case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
- case SW_PIXELFORMAT_UNCOMPRESSED_R16:
- case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16:
- case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:
- default:
- RLSW.errCode = SW_INVALID_ENUM;
- break;
- }
+// Get framefuffer pixel data pointer and size
+void *swGetColorBuffer(int *width, int *height)
+{
+ if (width != NULL) *width = RLSW.framebuffer.color.width;
+ if (height != NULL) *height = RLSW.framebuffer.color.height;
+ return RLSW.framebuffer.color.pixels;
}
void swEnable(SWstate state)
{
switch (state)
{
- case SW_SCISSOR_TEST: RLSW.stateFlags |= SW_STATE_SCISSOR_TEST; break;
- case SW_TEXTURE_2D: RLSW.stateFlags |= SW_STATE_TEXTURE_2D; break;
- case SW_DEPTH_TEST: RLSW.stateFlags |= SW_STATE_DEPTH_TEST; break;
- case SW_CULL_FACE: RLSW.stateFlags |= SW_STATE_CULL_FACE; break;
- case SW_BLEND: RLSW.stateFlags |= SW_STATE_BLEND; break;
+ case SW_SCISSOR_TEST: RLSW.userState |= SW_STATE_SCISSOR_TEST; break;
+ case SW_TEXTURE_2D: RLSW.userState |= SW_STATE_TEXTURE_2D; break;
+ case SW_DEPTH_TEST: RLSW.userState |= SW_STATE_DEPTH_TEST; break;
+ case SW_CULL_FACE: RLSW.userState |= SW_STATE_CULL_FACE; break;
+ case SW_BLEND: RLSW.userState |= SW_STATE_BLEND; break;
default: RLSW.errCode = SW_INVALID_ENUM; break;
}
}
@@ -3766,11 +4075,11 @@ void swDisable(SWstate state)
{
switch (state)
{
- case SW_SCISSOR_TEST: RLSW.stateFlags &= ~SW_STATE_SCISSOR_TEST; break;
- case SW_TEXTURE_2D: RLSW.stateFlags &= ~SW_STATE_TEXTURE_2D; break;
- case SW_DEPTH_TEST: RLSW.stateFlags &= ~SW_STATE_DEPTH_TEST; break;
- case SW_CULL_FACE: RLSW.stateFlags &= ~SW_STATE_CULL_FACE; break;
- case SW_BLEND: RLSW.stateFlags &= ~SW_STATE_BLEND; break;
+ case SW_SCISSOR_TEST: RLSW.userState &= ~SW_STATE_SCISSOR_TEST; break;
+ case SW_TEXTURE_2D: RLSW.userState &= ~SW_STATE_TEXTURE_2D; break;
+ case SW_DEPTH_TEST: RLSW.userState &= ~SW_STATE_DEPTH_TEST; break;
+ case SW_CULL_FACE: RLSW.userState &= ~SW_STATE_CULL_FACE; break;
+ case SW_BLEND: RLSW.userState &= ~SW_STATE_BLEND; break;
default: RLSW.errCode = SW_INVALID_ENUM; break;
}
}
@@ -3782,6 +4091,7 @@ void swGetIntegerv(SWget name, int *v)
case SW_MODELVIEW_STACK_DEPTH: *v = SW_MODELVIEW_STACK_DEPTH; break;
case SW_PROJECTION_STACK_DEPTH: *v = SW_PROJECTION_STACK_DEPTH; break;
case SW_TEXTURE_STACK_DEPTH: *v = SW_TEXTURE_STACK_DEPTH; break;
+ case SW_DRAW_FRAMEBUFFER_BINDING: *v = RLSW.boundFramebufferId; break;
default: RLSW.errCode = SW_INVALID_ENUM; break;
}
}
@@ -3792,23 +4102,26 @@ void swGetFloatv(SWget name, float *v)
{
case SW_COLOR_CLEAR_VALUE:
{
- sw_framebuffer_read_color(v, &RLSW.clearValue);
+ v[0] = RLSW.clearColor[0];
+ v[1] = RLSW.clearColor[1];
+ v[2] = RLSW.clearColor[2];
+ v[3] = RLSW.clearColor[3];
} break;
case SW_DEPTH_CLEAR_VALUE:
{
- v[0] = sw_framebuffer_read_depth(&RLSW.clearValue);
+ v[0] = RLSW.clearDepth;
} break;
case SW_CURRENT_COLOR:
{
- v[0] = RLSW.vertexBuffer[RLSW.vertexCounter - 1].color[0];
- v[1] = RLSW.vertexBuffer[RLSW.vertexCounter - 1].color[1];
- v[2] = RLSW.vertexBuffer[RLSW.vertexCounter - 1].color[2];
- v[3] = RLSW.vertexBuffer[RLSW.vertexCounter - 1].color[3];
+ v[0] = RLSW.primitive.buffer[RLSW.primitive.vertexCount - 1].color[0];
+ v[1] = RLSW.primitive.buffer[RLSW.primitive.vertexCount - 1].color[1];
+ v[2] = RLSW.primitive.buffer[RLSW.primitive.vertexCount - 1].color[2];
+ v[3] = RLSW.primitive.buffer[RLSW.primitive.vertexCount - 1].color[3];
} break;
case SW_CURRENT_TEXTURE_COORDS:
{
- v[0] = RLSW.vertexBuffer[RLSW.vertexCounter - 1].texcoord[0];
- v[1] = RLSW.vertexBuffer[RLSW.vertexCounter - 1].texcoord[1];
+ v[0] = RLSW.primitive.buffer[RLSW.primitive.vertexCount - 1].texcoord[0];
+ v[1] = RLSW.primitive.buffer[RLSW.primitive.vertexCount - 1].texcoord[1];
} break;
case SW_POINT_SIZE:
{
@@ -3843,9 +4156,9 @@ const char *swGetString(SWget name)
switch (name)
{
- case SW_VENDOR: result = "RLSW Header"; break;
- case SW_RENDERER: result = "RLSW Software Renderer"; break;
- case SW_VERSION: result = "RLSW 1.0"; break;
+ case SW_VENDOR: result = "RLSW"; break;
+ case SW_RENDERER: result = "RLSW OpenGL Software Renderer"; break;
+ case SW_VERSION: result = RLSW_VERSION; break;
case SW_EXTENSIONS: result = "None"; break;
default: RLSW.errCode = SW_INVALID_ENUM; break;
}
@@ -3876,11 +4189,6 @@ void swViewport(int x, int y, int width, int height)
RLSW.vpCenter[0] = (float)x + RLSW.vpHalf[0];
RLSW.vpCenter[1] = (float)y + RLSW.vpHalf[1];
-
- RLSW.vpMin[0] = sw_clampi(x, 0, RLSW.framebuffer.width - 1);
- RLSW.vpMin[1] = sw_clampi(y, 0, RLSW.framebuffer.height - 1);
- RLSW.vpMax[0] = sw_clampi(x + width, 0, RLSW.framebuffer.width - 1);
- RLSW.vpMax[1] = sw_clampi(y + height, 0, RLSW.framebuffer.height - 1);
}
void swScissor(int x, int y, int width, int height)
@@ -3891,10 +4199,10 @@ void swScissor(int x, int y, int width, int height)
return;
}
- RLSW.scMin[0] = sw_clampi(x, 0, RLSW.framebuffer.width - 1);
- RLSW.scMin[1] = sw_clampi(y, 0, RLSW.framebuffer.height - 1);
- RLSW.scMax[0] = sw_clampi(x + width, 0, RLSW.framebuffer.width - 1);
- RLSW.scMax[1] = sw_clampi(y + height, 0, RLSW.framebuffer.height - 1);
+ RLSW.scMin[0] = x;
+ RLSW.scMin[1] = y;
+ RLSW.scMax[0] = x + width;
+ RLSW.scMax[1] = y + height;
RLSW.scClipMin[0] = (2.0f*(float)RLSW.scMin[0]/(float)RLSW.vpSize[0]) - 1.0f;
RLSW.scClipMax[0] = (2.0f*(float)RLSW.scMax[0]/(float)RLSW.vpSize[0]) - 1.0f;
@@ -3904,76 +4212,44 @@ void swScissor(int x, int y, int width, int height)
void swClearColor(float r, float g, float b, float a)
{
- float v[4] = { r, g, b, a };
- sw_framebuffer_write_color(&RLSW.clearValue, v);
+ RLSW.clearColor[0] = r;
+ RLSW.clearColor[1] = g;
+ RLSW.clearColor[2] = b;
+ RLSW.clearColor[3] = a;
}
void swClearDepth(float depth)
{
- sw_framebuffer_write_depth(&RLSW.clearValue, depth);
+ RLSW.clearDepth = depth;
}
void swClear(uint32_t bitmask)
{
- int size = RLSW.framebuffer.width*RLSW.framebuffer.height;
+ if (!sw_is_ready_to_render()) return;
- if ((bitmask & (SW_COLOR_BUFFER_BIT | SW_DEPTH_BUFFER_BIT)) == (SW_COLOR_BUFFER_BIT | SW_DEPTH_BUFFER_BIT))
+ if ((bitmask & (SW_COLOR_BUFFER_BIT)) && (RLSW.colorBuffer != NULL) && (RLSW.colorBuffer->pixels != NULL))
{
- sw_framebuffer_fill(RLSW.framebuffer.pixels, size, RLSW.clearValue);
+ sw_framebuffer_fill_color(RLSW.colorBuffer, RLSW.clearColor);
}
- else if (bitmask & (SW_COLOR_BUFFER_BIT))
+
+ if ((bitmask & (SW_DEPTH_BUFFER_BIT)) && (RLSW.depthBuffer != NULL) && (RLSW.depthBuffer->pixels != NULL))
{
- sw_framebuffer_fill_color(RLSW.framebuffer.pixels, size, RLSW.clearValue.color);
- }
- else if (bitmask & SW_DEPTH_BUFFER_BIT)
- {
- sw_framebuffer_fill_depth(RLSW.framebuffer.pixels, size, RLSW.clearValue.depth);
+ sw_framebuffer_fill_depth(RLSW.depthBuffer, RLSW.clearDepth);
}
}
void swBlendFunc(SWfactor sfactor, SWfactor dfactor)
{
- if (!sw_is_blend_src_factor_valid(sfactor) ||
- !sw_is_blend_dst_factor_valid(dfactor))
- {
- RLSW.errCode = SW_INVALID_ENUM;
- return;
- }
+ int sIndex = sw_blend_factor_index(sfactor);
+ if (sIndex < 0) { RLSW.errCode = SW_INVALID_ENUM; return; }
+
+ int dIndex = sw_blend_factor_index(dfactor);
+ if (dIndex < 0) { RLSW.errCode = SW_INVALID_ENUM; return; }
RLSW.srcFactor = sfactor;
RLSW.dstFactor = dfactor;
-
- switch (sfactor)
- {
- case SW_ZERO: RLSW.srcFactorFunc = sw_factor_zero; break;
- case SW_ONE: RLSW.srcFactorFunc = sw_factor_one; break;
- case SW_SRC_COLOR: RLSW.srcFactorFunc = sw_factor_src_color; break;
- case SW_ONE_MINUS_SRC_COLOR: RLSW.srcFactorFunc = sw_factor_one_minus_src_color; break;
- case SW_SRC_ALPHA: RLSW.srcFactorFunc = sw_factor_src_alpha; break;
- case SW_ONE_MINUS_SRC_ALPHA: RLSW.srcFactorFunc = sw_factor_one_minus_src_alpha; break;
- case SW_DST_ALPHA: RLSW.srcFactorFunc = sw_factor_dst_alpha; break;
- case SW_ONE_MINUS_DST_ALPHA: RLSW.srcFactorFunc = sw_factor_one_minus_dst_alpha; break;
- case SW_DST_COLOR: RLSW.srcFactorFunc = sw_factor_dst_color; break;
- case SW_ONE_MINUS_DST_COLOR: RLSW.srcFactorFunc = sw_factor_one_minus_dst_color; break;
- case SW_SRC_ALPHA_SATURATE: RLSW.srcFactorFunc = sw_factor_src_alpha_saturate; break;
- default: break;
- }
-
- switch (dfactor)
- {
- case SW_ZERO: RLSW.dstFactorFunc = sw_factor_zero; break;
- case SW_ONE: RLSW.dstFactorFunc = sw_factor_one; break;
- case SW_SRC_COLOR: RLSW.dstFactorFunc = sw_factor_src_color; break;
- case SW_ONE_MINUS_SRC_COLOR: RLSW.dstFactorFunc = sw_factor_one_minus_src_color; break;
- case SW_SRC_ALPHA: RLSW.dstFactorFunc = sw_factor_src_alpha; break;
- case SW_ONE_MINUS_SRC_ALPHA: RLSW.dstFactorFunc = sw_factor_one_minus_src_alpha; break;
- case SW_DST_ALPHA: RLSW.dstFactorFunc = sw_factor_dst_alpha; break;
- case SW_ONE_MINUS_DST_ALPHA: RLSW.dstFactorFunc = sw_factor_one_minus_dst_alpha; break;
- case SW_DST_COLOR: RLSW.dstFactorFunc = sw_factor_dst_color; break;
- case SW_ONE_MINUS_DST_COLOR: RLSW.dstFactorFunc = sw_factor_one_minus_dst_color; break;
- case SW_SRC_ALPHA_SATURATE: break;
- default: break;
- }
+ RLSW.blendFlags = sw_blend_compute_flags(sfactor, dfactor);
+ RLSW.blendFunc = SW_BLEND_TABLE[sIndex][dIndex];
}
void swPolygonMode(SWpoly mode)
@@ -4095,7 +4371,7 @@ void swPopMatrix(void)
return;
}
- RLSW.currentMatrix = &RLSW.stackProjection[--RLSW.stackProjectionCounter];
+ RLSW.currentMatrix = &RLSW.stackProjection[(--RLSW.stackProjectionCounter) - 1];
RLSW.isDirtyMVP = true; //< The MVP is considered to have been changed
} break;
case SW_MODELVIEW:
@@ -4106,7 +4382,7 @@ void swPopMatrix(void)
return;
}
- RLSW.currentMatrix = &RLSW.stackModelview[--RLSW.stackModelviewCounter];
+ RLSW.currentMatrix = &RLSW.stackModelview[(--RLSW.stackModelviewCounter) - 1];
RLSW.isDirtyMVP = true; //< The MVP is considered to have been changed
} break;
case SW_TEXTURE:
@@ -4117,7 +4393,7 @@ void swPopMatrix(void)
return;
}
- RLSW.currentMatrix = &RLSW.stackTexture[--RLSW.stackTextureCounter];
+ RLSW.currentMatrix = &RLSW.stackTexture[(--RLSW.stackTextureCounter) - 1];
} break;
default: break;
}
@@ -4131,7 +4407,7 @@ void swLoadIdentity(void)
void swTranslatef(float x, float y, float z)
{
- sw_matrix_t mat;
+ sw_matrix_t mat = { 0 };
sw_matrix_id(mat);
mat[12] = x;
@@ -4161,7 +4437,7 @@ void swRotatef(float angle, float x, float y, float z)
float cosres = cosf(angle);
float t = 1.0f - cosres;
- sw_matrix_t mat;
+ sw_matrix_t mat = { 0 };
mat[0] = x*x*t + cosres;
mat[1] = y*x*t + z*sinres;
@@ -4190,7 +4466,7 @@ void swRotatef(float angle, float x, float y, float z)
void swScalef(float x, float y, float z)
{
- sw_matrix_t mat;
+ sw_matrix_t mat = { 0 };
mat[0] = x, mat[1] = 0, mat[2] = 0, mat[3] = 0;
mat[4] = 0, mat[5] = y, mat[6] = 0, mat[7] = 0;
@@ -4211,7 +4487,7 @@ void swMultMatrixf(const float *mat)
void swFrustum(double left, double right, double bottom, double top, double znear, double zfar)
{
- sw_matrix_t mat;
+ sw_matrix_t mat = { 0 };
double rl = right - left;
double tb = top - bottom;
@@ -4244,7 +4520,7 @@ void swFrustum(double left, double right, double bottom, double top, double znea
void swOrtho(double left, double right, double bottom, double top, double znear, double zfar)
{
- sw_matrix_t mat;
+ sw_matrix_t mat = { 0 };
double rl = right - left;
double tb = top - bottom;
@@ -4277,6 +4553,13 @@ void swOrtho(double left, double right, double bottom, double top, double znear,
void swBegin(SWdraw mode)
{
+ // Check if render is possible
+ if (!sw_is_ready_to_render())
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
// Check if the draw mode is valid
if (!sw_is_draw_mode_valid(mode))
{
@@ -4284,188 +4567,182 @@ void swBegin(SWdraw mode)
return;
}
- // Recalculate the MVP if this is needed
- if (RLSW.isDirtyMVP)
+ // Ensures that a recording has not already started (spec)
+ if (sw_immediate_is_active())
{
- sw_matrix_mul_rst(RLSW.matMVP,
- RLSW.stackModelview[RLSW.stackModelviewCounter - 1],
- RLSW.stackProjection[RLSW.stackProjectionCounter - 1]);
-
- RLSW.isDirtyMVP = false;
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
}
- // Obtain the number of vertices needed for this primitive
- switch (mode)
- {
- case SW_POINTS: RLSW.reqVertices = 1; break;
- case SW_LINES: RLSW.reqVertices = 2; break;
- case SW_TRIANGLES: RLSW.reqVertices = 3; break;
- case SW_QUADS: RLSW.reqVertices = 4; break;
- }
-
- // Initialize required values
- RLSW.vertexCounter = 0;
- RLSW.drawMode = mode;
+ sw_immediate_begin(mode);
}
void swEnd(void)
{
- RLSW.drawMode = (SWdraw)0;
+ // Ensures that a recording has already started (spec)
+ if (!sw_immediate_is_active())
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ sw_immediate_end();
}
void swVertex2i(int x, int y)
{
const float v[4] = { (float)x, (float)y, 0.0f, 1.0f };
- sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
+ sw_immediate_push_vertex(v);
}
void swVertex2f(float x, float y)
{
const float v[4] = { x, y, 0.0f, 1.0f };
- sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
+ sw_immediate_push_vertex(v);
}
void swVertex2fv(const float *v)
{
const float v4[4] = { v[0], v[1], 0.0f, 1.0f };
- sw_immediate_push_vertex(v4, RLSW.current.color, RLSW.current.texcoord);
+ sw_immediate_push_vertex(v4);
}
void swVertex3i(int x, int y, int z)
{
const float v[4] = { (float)x, (float)y, (float)z, 1.0f };
- sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
+ sw_immediate_push_vertex(v);
}
void swVertex3f(float x, float y, float z)
{
const float v[4] = { x, y, z, 1.0f };
- sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
+ sw_immediate_push_vertex(v);
}
void swVertex3fv(const float *v)
{
const float v4[4] = { v[0], v[1], v[2], 1.0f };
- sw_immediate_push_vertex(v4, RLSW.current.color, RLSW.current.texcoord);
+ sw_immediate_push_vertex(v4);
}
void swVertex4i(int x, int y, int z, int w)
{
const float v[4] = { (float)x, (float)y, (float)z, (float)w };
- sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
+ sw_immediate_push_vertex(v);
}
void swVertex4f(float x, float y, float z, float w)
{
const float v[4] = { x, y, z, w };
- sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
+ sw_immediate_push_vertex(v);
}
void swVertex4fv(const float *v)
{
- sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
+ sw_immediate_push_vertex(v);
}
void swColor3ub(uint8_t r, uint8_t g, uint8_t b)
{
- float cv[4];
+ float cv[4] = { 0 };
cv[0] = (float)r*SW_INV_255;
cv[1] = (float)g*SW_INV_255;
cv[2] = (float)b*SW_INV_255;
cv[3] = 1.0f;
- swColor4fv(cv);
+ sw_immediate_set_color(cv);
}
void swColor3ubv(const uint8_t *v)
{
- float cv[4];
+ float cv[4] = { 0 };
cv[0] = (float)v[0]*SW_INV_255;
cv[1] = (float)v[1]*SW_INV_255;
cv[2] = (float)v[2]*SW_INV_255;
cv[3] = 1.0f;
- swColor4fv(cv);
+ sw_immediate_set_color(cv);
}
void swColor3f(float r, float g, float b)
{
- float cv[4];
+ float cv[4] = { 0 };
cv[0] = r;
cv[1] = g;
cv[2] = b;
cv[3] = 1.0f;
- swColor4fv(cv);
+ sw_immediate_set_color(cv);
}
void swColor3fv(const float *v)
{
- float cv[4];
+ float cv[4] = { 0 };
cv[0] = v[0];
cv[1] = v[1];
cv[2] = v[2];
cv[3] = 1.0f;
- swColor4fv(cv);
+ sw_immediate_set_color(cv);
}
void swColor4ub(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
- float cv[4];
+ float cv[4] = { 0 };
cv[0] = (float)r*SW_INV_255;
cv[1] = (float)g*SW_INV_255;
cv[2] = (float)b*SW_INV_255;
cv[3] = (float)a*SW_INV_255;
- swColor4fv(cv);
+ sw_immediate_set_color(cv);
}
void swColor4ubv(const uint8_t *v)
{
- float cv[4];
+ float cv[4] = { 0 };
cv[0] = (float)v[0]*SW_INV_255;
cv[1] = (float)v[1]*SW_INV_255;
cv[2] = (float)v[2]*SW_INV_255;
cv[3] = (float)v[3]*SW_INV_255;
- swColor4fv(cv);
+ sw_immediate_set_color(cv);
}
void swColor4f(float r, float g, float b, float a)
{
- float cv[4];
+ float cv[4] = { 0 };
cv[0] = r;
cv[1] = g;
cv[2] = b;
cv[3] = a;
- swColor4fv(cv);
+ sw_immediate_set_color(cv);
}
void swColor4fv(const float *v)
{
- for (int i = 0; i < 4; i++) RLSW.current.color[i] = v[i];
+ sw_immediate_set_color(v);
}
void swTexCoord2f(float u, float v)
{
- const float *m = RLSW.stackTexture[RLSW.stackTextureCounter - 1];
-
- RLSW.current.texcoord[0] = m[0]*u + m[4]*v + m[12];
- RLSW.current.texcoord[1] = m[1]*u + m[5]*v + m[13];
+ const float texcoord[2] = { u, v };
+ sw_immediate_set_texcoord(texcoord);
}
void swTexCoord2fv(const float *v)
{
- const float *m = RLSW.stackTexture[RLSW.stackTextureCounter - 1];
-
- RLSW.current.texcoord[0] = m[0]*v[0] + m[4]*v[1] + m[12];
- RLSW.current.texcoord[1] = m[1]*v[0] + m[5]*v[1] + m[13];
+ sw_immediate_set_texcoord(v);
}
void swBindArray(SWarray type, void *buffer)
{
+ if (sw_immediate_is_active())
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
switch (type)
{
case SW_VERTEX_ARRAY: RLSW.array.positions = (float *)buffer; break;
@@ -4477,255 +4754,155 @@ void swBindArray(SWarray type, void *buffer)
void swDrawArrays(SWdraw mode, int offset, int count)
{
- if (RLSW.array.positions == 0)
+ if ((sw_immediate_is_active()) || (!sw_is_ready_to_render()) || (RLSW.array.positions == NULL))
{
RLSW.errCode = SW_INVALID_OPERATION;
return;
}
- swBegin(mode);
+ sw_immediate_begin(mode);
{
- const float *texMatrix = RLSW.stackTexture[RLSW.stackTextureCounter - 1];
- const float *defaultTexcoord = RLSW.current.texcoord;
- const float *defaultColor = RLSW.current.color;
-
const float *positions = RLSW.array.positions;
const float *texcoords = RLSW.array.texcoords;
const uint8_t *colors = RLSW.array.colors;
int end = offset + count;
-
for (int i = offset; i < end; i++)
{
- float u, v;
- if (texcoords)
- {
- int idx = 2*i;
- u = texcoords[idx];
- v = texcoords[idx + 1];
- }
- else
- {
- u = defaultTexcoord[0];
- v = defaultTexcoord[1];
- }
-
- float texcoord[2];
- texcoord[0] = texMatrix[0]*u + texMatrix[4]*v + texMatrix[12];
- texcoord[1] = texMatrix[1]*u + texMatrix[5]*v + texMatrix[13];
-
- float color[4] = {
- defaultColor[0],
- defaultColor[1],
- defaultColor[2],
- defaultColor[3]
- };
+ if (texcoords) sw_immediate_set_texcoord(&texcoords[2*i]);
if (colors)
{
- int idx = 4*i;
- color[0] *= (float)colors[idx]*SW_INV_255;
- color[1] *= (float)colors[idx + 1]*SW_INV_255;
- color[2] *= (float)colors[idx + 2]*SW_INV_255;
- color[3] *= (float)colors[idx + 3]*SW_INV_255;
+ const uint8_t *c = &colors[4*i];
+ float color[4] = {
+ (float)c[0]*SW_INV_255,
+ (float)c[1]*SW_INV_255,
+ (float)c[2]*SW_INV_255,
+ (float)c[3]*SW_INV_255,
+ };
+ sw_immediate_set_color(color);
}
- int idx = 3*i;
- float position[4] = {
- positions[idx],
- positions[idx + 1],
- positions[idx + 2],
- 1.0f
- };
-
- sw_immediate_push_vertex(position, color, texcoord);
+ const float *p = &positions[3*i];
+ float position[4] = { p[0], p[1], p[2], 1.0f };
+ sw_immediate_push_vertex(position);
}
}
- swEnd();
+ sw_immediate_end();
}
void swDrawElements(SWdraw mode, int count, int type, const void *indices)
{
- if (RLSW.array.positions == 0)
+ if ((sw_immediate_is_active()) || (!sw_is_ready_to_render()) || (RLSW.array.positions == NULL))
{
RLSW.errCode = SW_INVALID_OPERATION;
return;
}
- if (count < 0)
+ if ((count < 0) || (indices == NULL))
{
RLSW.errCode = SW_INVALID_VALUE;
return;
}
- const uint8_t *indicesUb = NULL;
- const uint16_t *indicesUs = NULL;
- const uint32_t *indicesUi = NULL;
-
- switch (type)
- {
- case SW_UNSIGNED_BYTE:
- indicesUb = (const uint8_t *)indices;
- break;
- case SW_UNSIGNED_SHORT:
- indicesUs = (const uint16_t *)indices;
- break;
- case SW_UNSIGNED_INT:
- indicesUi = (const uint32_t *)indices;
- break;
- default:
- RLSW.errCode = SW_INVALID_ENUM;
- return;
- }
-
- swBegin(mode);
- {
- const float *texMatrix = RLSW.stackTexture[RLSW.stackTextureCounter - 1];
- const float *defaultTexcoord = RLSW.current.texcoord;
- const float *defaultColor = RLSW.current.color;
-
- const float *positions = RLSW.array.positions;
- const float *texcoords = RLSW.array.texcoords;
- const uint8_t *colors = RLSW.array.colors;
-
- for (int i = 0; i < count; i++)
- {
- int index = indicesUb? indicesUb[i] :
- (indicesUs? indicesUs[i] : indicesUi[i]);
-
- float u, v;
- if (texcoords)
- {
- int idx = 2*index;
- u = texcoords[idx];
- v = texcoords[idx + 1];
- }
- else
- {
- u = defaultTexcoord[0];
- v = defaultTexcoord[1];
- }
-
- float texcoord[2];
- texcoord[0] = texMatrix[0]*u + texMatrix[4]*v + texMatrix[12];
- texcoord[1] = texMatrix[1]*u + texMatrix[5]*v + texMatrix[13];
-
- float color[4] = {
- defaultColor[0],
- defaultColor[1],
- defaultColor[2],
- defaultColor[3]
- };
-
- if (colors)
- {
- int idx = 4*index;
- color[0] *= (float)colors[idx]*SW_INV_255;
- color[1] *= (float)colors[idx + 1]*SW_INV_255;
- color[2] *= (float)colors[idx + 2]*SW_INV_255;
- color[3] *= (float)colors[idx + 3]*SW_INV_255;
- }
-
- int idx = 3*index;
- float position[4] = {
- positions[idx],
- positions[idx + 1],
- positions[idx + 2],
- 1.0f
- };
-
- sw_immediate_push_vertex(position, color, texcoord);
- }
- }
- swEnd();
-}
-
-void swGenTextures(int count, uint32_t *textures)
-{
- if ((count == 0) || (textures == NULL)) return;
-
- for (int i = 0; i < count; i++)
- {
- if (RLSW.loadedTextureCount >= SW_MAX_TEXTURES)
- {
- RLSW.errCode = SW_STACK_OVERFLOW; // WARNING: Out of memory, not really stack overflow
- return;
- }
-
- uint32_t id = 0;
- if (RLSW.freeTextureIdCount > 0) id = RLSW.freeTextureIds[--RLSW.freeTextureIdCount];
- else id = RLSW.loadedTextureCount++;
-
- RLSW.loadedTextures[id] = RLSW.loadedTextures[0];
- textures[i] = id;
- }
-}
-
-void swDeleteTextures(int count, uint32_t *textures)
-{
- if ((count == 0) || (textures == NULL)) return;
-
- for (int i = 0; i < count; i++)
- {
- if (!sw_is_texture_valid(textures[i]))
- {
- RLSW.errCode = SW_INVALID_VALUE;
- continue;
- }
-
- SW_FREE(RLSW.loadedTextures[textures[i]].pixels);
-
- RLSW.loadedTextures[textures[i]].pixels = NULL;
- RLSW.freeTextureIds[RLSW.freeTextureIdCount++] = textures[i];
- }
-}
-
-void swTexImage2D(int width, int height, SWformat format, SWtype type, const void *data)
-{
- uint32_t id = RLSW.currentTexture;
-
- if (!sw_is_texture_valid(id))
- {
- RLSW.errCode = SW_INVALID_VALUE;
- return;
- }
-
- int pixelFormat = sw_get_pixel_format(format, type);
-
- if (pixelFormat <= SW_PIXELFORMAT_UNKNOWN)
+ if ((type != SW_UNSIGNED_BYTE) && (type != SW_UNSIGNED_SHORT) && (type != SW_UNSIGNED_INT))
{
RLSW.errCode = SW_INVALID_ENUM;
return;
}
- sw_texture_t *texture = &RLSW.loadedTextures[id];
-
- int size = width*height;
- texture->pixels = SW_MALLOC(4*size);
-
- if (texture->pixels == NULL)
+ sw_immediate_begin(mode);
{
- RLSW.errCode = SW_STACK_OVERFLOW; // WARNING: Out of memory...
+ const float *positions = RLSW.array.positions;
+ const float *texcoords = RLSW.array.texcoords;
+ const uint8_t *colors = RLSW.array.colors;
+
+ const uint8_t *indicesUb = (type == SW_UNSIGNED_BYTE)? indices : NULL;
+ const uint16_t *indicesUs = (type == SW_UNSIGNED_SHORT)? indices : NULL;
+ const uint32_t *indicesUi = (type == SW_UNSIGNED_INT)? indices : NULL;
+
+ for (int i = 0; i < count; i++)
+ {
+ uint32_t index = indicesUb? (uint32_t)indicesUb[i] : (indicesUs? (uint32_t)indicesUs[i] : (uint32_t)indicesUi[i]);
+
+ if (texcoords) sw_immediate_set_texcoord(&texcoords[2*index]);
+
+ if (colors)
+ {
+ const uint8_t *c = &colors[4*index];
+ float color[4] = {
+ (float)c[0]*SW_INV_255,
+ (float)c[1]*SW_INV_255,
+ (float)c[2]*SW_INV_255,
+ (float)c[3]*SW_INV_255,
+ };
+ sw_immediate_set_color(color);
+ }
+
+ const float *p = &positions[3*index];
+ float position[4] = { p[0], p[1], p[2], 1.0f };
+ sw_immediate_push_vertex(position);
+ }
+ }
+ sw_immediate_end();
+}
+
+void swGenTextures(int count, sw_handle_t *textures)
+{
+ if (sw_immediate_is_active())
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
return;
}
- for (int i = 0; i < size; i++)
- {
- uint32_t *dst = &((uint32_t*)texture->pixels)[i];
- sw_get_pixel((uint8_t*)dst, data, i, pixelFormat);
- }
+ if (!count || !textures) return;
- texture->width = width;
- texture->height = height;
- texture->wMinus1 = width - 1;
- texture->hMinus1 = height - 1;
- texture->tx = 1.0f/width;
- texture->ty = 1.0f/height;
+ for (int i = 0; i < count; i++)
+ {
+ sw_handle_t h = sw_pool_alloc(&RLSW.texturePool);
+ if (h == SW_HANDLE_NULL) { RLSW.errCode = SW_OUT_OF_MEMORY; return; }
+ textures[i] = h;
+ }
}
-void swTexParameteri(int param, int value)
+void swDeleteTextures(int count, sw_handle_t *textures)
{
- uint32_t id = RLSW.currentTexture;
+ if (sw_immediate_is_active())
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ if (!count || !textures) return;
+
+ for (int i = 0; i < count; i++)
+ {
+ sw_texture_t *tex = sw_pool_get(&RLSW.texturePool, textures[i]);
+ if (!tex) { RLSW.errCode = SW_INVALID_VALUE; continue; }
+ if (tex == RLSW.boundTexture) RLSW.boundTexture = NULL;
+ if (tex == RLSW.colorBuffer) RLSW.colorBuffer = NULL;
+ if (tex == RLSW.depthBuffer) RLSW.depthBuffer = NULL;
+
+ sw_texture_free(tex);
+ *tex = (sw_texture_t) { 0 };
+
+ sw_pool_free(&RLSW.texturePool, textures[i]);
+ }
+}
+
+void swBindTexture(sw_handle_t id)
+{
+ if (sw_immediate_is_active())
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ if (id == SW_HANDLE_NULL)
+ {
+ RLSW.boundTexture = NULL;
+ return;
+ }
if (!sw_is_texture_valid(id))
{
@@ -4733,69 +4910,1031 @@ void swTexParameteri(int param, int value)
return;
}
- sw_texture_t *texture = &RLSW.loadedTextures[id];
-
- switch (param)
- {
- case SW_TEXTURE_MIN_FILTER:
- {
- if (!sw_is_texture_filter_valid(value))
- {
- RLSW.errCode = SW_INVALID_ENUM;
- return;
- }
-
- texture->minFilter = (SWfilter)value;
- } break;
- case SW_TEXTURE_MAG_FILTER:
- {
- if (!sw_is_texture_filter_valid(value))
- {
- RLSW.errCode = SW_INVALID_ENUM;
- return;
- }
-
- texture->magFilter = (SWfilter)value;
- } break;
- case SW_TEXTURE_WRAP_S:
- {
- if (!sw_is_texture_wrap_valid(value))
- {
- RLSW.errCode = SW_INVALID_ENUM;
- return;
- }
-
- texture->sWrap = (SWwrap)value;
- } break;
- case SW_TEXTURE_WRAP_T:
- {
- if (!sw_is_texture_wrap_valid(value))
- {
- RLSW.errCode = SW_INVALID_ENUM;
- return;
- }
-
- texture->tWrap = (SWwrap)value;
- } break;
- default: RLSW.errCode = SW_INVALID_ENUM; break;
- }
+ RLSW.boundTexture = sw_pool_get(&RLSW.texturePool, id);
}
-void swBindTexture(uint32_t id)
+void swTexStorage2D(int width, int height, SWinternalformat format)
{
- if (id >= SW_MAX_TEXTURES)
- {
- RLSW.errCode = SW_INVALID_VALUE;
- return;
- }
-
- if (RLSW.loadedTextures[id].pixels == NULL)
+ if (sw_immediate_is_active())
{
RLSW.errCode = SW_INVALID_OPERATION;
return;
}
- RLSW.currentTexture = id;
+ if (RLSW.boundTexture == NULL) return;
+
+ int pixelFormat = SW_PIXELFORMAT_UNKNOWN;
+ switch (format)
+ {
+ case SW_LUMINANCE8: pixelFormat = SW_PIXELFORMAT_COLOR_GRAYSCALE; break;
+ case SW_LUMINANCE8_ALPHA8: pixelFormat = SW_PIXELFORMAT_COLOR_GRAYALPHA; break;
+ case SW_R3_G3_B2: pixelFormat = SW_PIXELFORMAT_COLOR_R3G3B2; break;
+ case SW_RGB8: pixelFormat = SW_PIXELFORMAT_COLOR_R8G8B8; break;
+ case SW_RGBA4: pixelFormat = SW_PIXELFORMAT_COLOR_R4G4B4A4; break;
+ case SW_RGB5_A1: pixelFormat = SW_PIXELFORMAT_COLOR_R5G5B5A1; break;
+ case SW_RGBA8: pixelFormat = SW_PIXELFORMAT_COLOR_R8G8B8A8; break;
+ case SW_R16F: pixelFormat = SW_PIXELFORMAT_COLOR_R16; break;
+ case SW_RGB16F: pixelFormat = SW_PIXELFORMAT_COLOR_R16G16B16; break;
+ case SW_RGBA16F: pixelFormat = SW_PIXELFORMAT_COLOR_R16G16B16A16; break;
+ case SW_R32F: pixelFormat = SW_PIXELFORMAT_COLOR_R32; break;
+ case SW_RGB32F: pixelFormat = SW_PIXELFORMAT_COLOR_R32G32B32; break;
+ case SW_RGBA32F: pixelFormat = SW_PIXELFORMAT_COLOR_R32G32B32A32; break;
+ case SW_DEPTH_COMPONENT16: pixelFormat = SW_PIXELFORMAT_DEPTH_D16; break;
+ case SW_DEPTH_COMPONENT24: pixelFormat = SW_PIXELFORMAT_DEPTH_D32; break;
+ case SW_DEPTH_COMPONENT32: pixelFormat = SW_PIXELFORMAT_DEPTH_D32; break;
+ case SW_DEPTH_COMPONENT32F: pixelFormat = SW_PIXELFORMAT_DEPTH_D32; break;
+ default: RLSW.errCode = SW_INVALID_ENUM; return;
+ }
+
+ (void)sw_texture_alloc(RLSW.boundTexture, NULL, width, height, pixelFormat);
+}
+
+void swTexImage2D(int width, int height, SWformat format, SWtype type, const void *data)
+{
+ if (sw_immediate_is_active())
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ if (RLSW.boundTexture == NULL) return;
+
+ int pixelFormat = sw_pixel_get_format(format, type);
+ if (pixelFormat <= SW_PIXELFORMAT_UNKNOWN) { RLSW.errCode = SW_INVALID_ENUM; return; }
+
+ (void)sw_texture_alloc(RLSW.boundTexture, data, width, height, pixelFormat);
+}
+
+void swTexSubImage2D(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
+{
+ if (sw_immediate_is_active())
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ if (!sw_is_texture_complete(RLSW.boundTexture) || (!pixels) || (width <= 0) || (height <= 0))
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ return;
+ }
+
+ if ((x < 0) || (y < 0) || (x + width > RLSW.boundTexture->width) || (y + height > RLSW.boundTexture->height))
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ return;
+ }
+
+ sw_pixel_write_color_f writeColor = sw_pixel_get_write_color_func(RLSW.boundTexture->format);
+ if (writeColor == NULL) // probably a depth format
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ sw_pixelformat_t srcPixelFormat = sw_pixel_get_format(format, type);
+ sw_pixel_read_color_f readColor = sw_pixel_get_read_color_func(srcPixelFormat);
+ if (readColor == NULL)
+ {
+ RLSW.errCode = SW_INVALID_ENUM;
+ return;
+ }
+
+ const int srcPixelSize = SW_PIXELFORMAT_SIZE[srcPixelFormat];
+ const int dstPixelSize = SW_PIXELFORMAT_SIZE[RLSW.boundTexture->format];
+
+ const uint8_t *srcBytes = (const uint8_t *)pixels;
+ uint8_t *dstBytes = (uint8_t *)RLSW.boundTexture->pixels;
+
+ if (srcPixelFormat == RLSW.boundTexture->format)
+ {
+ const int rowSize = width*dstPixelSize;
+ const int dstStride = RLSW.boundTexture->width*dstPixelSize;
+ const int srcStride = width*srcPixelSize;
+
+ uint8_t *dstRow = dstBytes + (y*RLSW.boundTexture->width + x)*dstPixelSize;
+ const uint8_t *srcRow = srcBytes;
+
+ for (int j = 0; j < height; ++j)
+ {
+ for (int i = 0; i < rowSize; ++i) dstRow[i] = srcRow[i];
+ dstRow += dstStride;
+ srcRow += srcStride;
+ }
+ return;
+ }
+
+ bool alphaFound = false;
+
+ for (int j = 0; j < height; ++j)
+ {
+ for (int i = 0; i < width; ++i)
+ {
+ float color[4];
+ const int srcPixelOffset = ((j*width) + i)*srcPixelSize;
+ const int dstPixelOffset = (((y + j)*RLSW.boundTexture->width) + (x + i))*dstPixelSize;
+
+ readColor(color, srcBytes, srcPixelOffset);
+ alphaFound |= (color[3] < 1.0f);
+
+ writeColor(dstBytes, color, dstPixelOffset);
+ }
+ }
+
+ RLSW.boundTexture->alpha = alphaFound? SW_PIXELFORMAT_ALPHA[srcPixelFormat] : SW_PIXEL_ALPHA_NONE;
+}
+
+void swTexParameteri(int param, int value)
+{
+ if (sw_immediate_is_active())
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ if (RLSW.boundTexture == NULL) return;
+
+ switch (param)
+ {
+ case SW_TEXTURE_MIN_FILTER:
+ {
+ if (!sw_is_texture_filter_valid(value)) { RLSW.errCode = SW_INVALID_ENUM; return; }
+ RLSW.boundTexture->minFilter = (SWfilter)value;
+ } break;
+ case SW_TEXTURE_MAG_FILTER:
+ {
+ if (!sw_is_texture_filter_valid(value)) { RLSW.errCode = SW_INVALID_ENUM; return; }
+ RLSW.boundTexture->magFilter = (SWfilter)value;
+ } break;
+ case SW_TEXTURE_WRAP_S:
+ {
+ if (!sw_is_texture_wrap_valid(value)) { RLSW.errCode = SW_INVALID_ENUM; return; }
+ RLSW.boundTexture->sWrap = (SWwrap)value;
+ } break;
+ case SW_TEXTURE_WRAP_T:
+ {
+ if (!sw_is_texture_wrap_valid(value)) { RLSW.errCode = SW_INVALID_ENUM; return; }
+ RLSW.boundTexture->tWrap = (SWwrap)value;
+ } break;
+ default: RLSW.errCode = SW_INVALID_ENUM; break;
+ }
+}
+
+void swGenFramebuffers(int count, uint32_t *framebuffers)
+{
+ if (sw_immediate_is_active())
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ if (!count || !framebuffers) return;
+
+ for (int i = 0; i < count; i++)
+ {
+ sw_handle_t h = sw_pool_alloc(&RLSW.framebufferPool);
+ if (h == SW_HANDLE_NULL) { RLSW.errCode = SW_OUT_OF_MEMORY; return; }
+ framebuffers[i] = h;
+ }
+}
+
+void swDeleteFramebuffers(int count, uint32_t *framebuffers)
+{
+ if (sw_immediate_is_active())
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ if (!count || !framebuffers) return;
+
+ for (int i = 0; i < count; i++)
+ {
+ sw_framebuffer_t *fb = sw_pool_get(&RLSW.framebufferPool, framebuffers[i]);
+ if (!fb) { RLSW.errCode = SW_INVALID_VALUE; continue; }
+
+ if (framebuffers[i] == RLSW.boundFramebufferId)
+ {
+ RLSW.boundFramebufferId = SW_HANDLE_NULL;
+ RLSW.colorBuffer = &RLSW.framebuffer.color;
+ RLSW.depthBuffer = &RLSW.framebuffer.depth;
+ }
+
+ sw_pool_free(&RLSW.framebufferPool, framebuffers[i]);
+ }
+}
+
+void swBindFramebuffer(uint32_t id)
+{
+ if (sw_immediate_is_active())
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ if (id == SW_HANDLE_NULL)
+ {
+ RLSW.boundFramebufferId = SW_HANDLE_NULL;
+ RLSW.colorBuffer = &RLSW.framebuffer.color;
+ RLSW.depthBuffer = &RLSW.framebuffer.depth;
+ return;
+ }
+
+ sw_framebuffer_t *fb = sw_pool_get(&RLSW.framebufferPool, id);
+ if (fb == NULL)
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ return;
+ }
+
+ RLSW.boundFramebufferId = id;
+ RLSW.colorBuffer = sw_pool_get(&RLSW.texturePool, fb->colorAttachment);
+ RLSW.depthBuffer = sw_pool_get(&RLSW.texturePool, fb->depthAttachment);
+}
+
+void swFramebufferTexture2D(SWattachment attach, uint32_t texture)
+{
+ if ((sw_immediate_is_active()) || (RLSW.boundFramebufferId == SW_HANDLE_NULL))
+ {
+ RLSW.errCode = SW_INVALID_OPERATION; // not really standard but hey
+ return;
+ }
+
+ sw_framebuffer_t *fb = sw_pool_get(&RLSW.framebufferPool, RLSW.boundFramebufferId);
+ if (fb == NULL) return; // Should never happen
+
+ switch (attach)
+ {
+ case SW_COLOR_ATTACHMENT:
+ {
+ fb->colorAttachment = texture;
+ RLSW.colorBuffer = sw_pool_get(&RLSW.texturePool, texture);
+ } break;
+ case SW_DEPTH_ATTACHMENT:
+ {
+ fb->depthAttachment = texture;
+ RLSW.depthBuffer = sw_pool_get(&RLSW.texturePool, texture);
+ } break;
+ default: RLSW.errCode = SW_INVALID_ENUM; break;
+ }
+}
+
+SWfbstatus swCheckFramebufferStatus(void)
+{
+ if (RLSW.boundFramebufferId == SW_HANDLE_NULL) return SW_FRAMEBUFFER_COMPLETE;
+
+ if (RLSW.colorBuffer == NULL) return SW_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+
+ if (!sw_is_texture_complete(RLSW.colorBuffer)) return SW_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+
+ if (RLSW.colorBuffer->format != SW_FRAMEBUFFER_COLOR_FORMAT) return SW_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+
+ if (RLSW.depthBuffer)
+ {
+ if (!sw_is_texture_complete(RLSW.depthBuffer)) return SW_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+
+ if (RLSW.depthBuffer->format != SW_FRAMEBUFFER_DEPTH_FORMAT) return SW_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+
+ if ((RLSW.colorBuffer->width != RLSW.depthBuffer->width) ||
+ (RLSW.colorBuffer->height != RLSW.depthBuffer->height)) return SW_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ }
+
+ return SW_FRAMEBUFFER_COMPLETE;
+}
+
+void swGetFramebufferAttachmentParameteriv(SWattachment attachment, SWattachget property, int *v)
+{
+ if (RLSW.boundFramebufferId == SW_HANDLE_NULL)
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ if (v == NULL)
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ return;
+ }
+
+ sw_framebuffer_t *fb = sw_pool_get(&RLSW.framebufferPool, RLSW.boundFramebufferId);
+ if (fb == NULL) return; // Should never happen
+
+ switch (property)
+ {
+ case SW_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ {
+ if (attachment == SW_COLOR_ATTACHMENT) *v = fb->colorAttachment;
+ else if (attachment == SW_DEPTH_ATTACHMENT) *v = fb->depthAttachment;
+ } break;
+ case SW_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: *v = GL_TEXTURE; break;
+ default: break;
+ }
}
#endif // RLSW_IMPLEMENTATION
+
+//----------------------------------------------------------------------------------
+// Template Rasterization Functions
+//----------------------------------------------------------------------------------
+
+// Triangle rasterization functions
+//-------------------------------------------------------------------------------------------
+#ifdef RLSW_TEMPLATE_RASTER_TRIANGLE
+
+// Options:
+// - RLSW_TEMPLATE_RASTER_TRIANGLE -> Contains the suffix name
+// - SW_ENABLE_DEPTH_TEST
+// - SW_ENABLE_TEXTURE
+// - SW_ENABLE_BLEND
+
+#define SW_RASTER_TRIANGLE_SPAN SW_CONCATX(sw_raster_triangle_span_, RLSW_TEMPLATE_RASTER_TRIANGLE)
+#define SW_RASTER_TRIANGLE SW_CONCATX(sw_raster_triangle_, RLSW_TEMPLATE_RASTER_TRIANGLE)
+
+#ifdef SW_ENABLE_TEXTURE
+ #define SW_GET_GRAD sw_get_vertex_grad_PCT
+ #define SW_ADD_GRAD sw_add_vertex_grad_PCT
+ #define SW_ADD_GRAD_SCALED sw_add_vertex_grad_scaled_PCT
+#else
+ #define SW_GET_GRAD sw_get_vertex_grad_PC
+ #define SW_ADD_GRAD sw_add_vertex_grad_PC
+ #define SW_ADD_GRAD_SCALED sw_add_vertex_grad_scaled_PC
+#endif
+
+static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t *end, float dUdy, float dVdy)
+{
+ // Gets the start/end coordinates and skip empty lines
+ int xStart = (int)start->position[0];
+ int xEnd = (int)end->position[0];
+ if (xStart == xEnd) return;
+
+ // Compute the inverse horizontal distance along the X axis
+ float dxRcp = 1.0f/(end->position[0] - start->position[0]);
+
+ // Compute the interpolation steps along the X axis
+ float dWdx = (end->position[3] - start->position[3])*dxRcp;
+ float dCdx[4] = {
+ (end->color[0] - start->color[0])*dxRcp,
+ (end->color[1] - start->color[1])*dxRcp,
+ (end->color[2] - start->color[2])*dxRcp,
+ (end->color[3] - start->color[3])*dxRcp
+ };
+#ifdef SW_ENABLE_DEPTH_TEST
+ float dZdx = (end->position[2] - start->position[2])*dxRcp;
+#endif
+#ifdef SW_ENABLE_TEXTURE
+ float dUdx = (end->texcoord[0] - start->texcoord[0])*dxRcp;
+ float dVdx = (end->texcoord[1] - start->texcoord[1])*dxRcp;
+#endif
+
+ // Compute the subpixel distance to traverse before the first pixel
+ float xSubstep = 1.0f - sw_fract(start->position[0]);
+
+ // Initializing the interpolation starting values
+ float w = start->position[3] + dWdx*xSubstep;
+ float color[4] = {
+ start->color[0] + dCdx[0]*xSubstep,
+ start->color[1] + dCdx[1]*xSubstep,
+ start->color[2] + dCdx[2]*xSubstep,
+ start->color[3] + dCdx[3]*xSubstep
+ };
+#ifdef SW_ENABLE_DEPTH_TEST
+ float z = start->position[2] + dZdx*xSubstep;
+#endif
+#ifdef SW_ENABLE_TEXTURE
+ float u = start->texcoord[0] + dUdx*xSubstep;
+ float v = start->texcoord[1] + dVdx*xSubstep;
+#endif
+
+ // Pre-calculate the starting pointers for the framebuffer row
+ int y = (int)start->position[1];
+ int baseOffset = y*RLSW.colorBuffer->width + xStart;
+ uint8_t *cPtr = (uint8_t *)(RLSW.colorBuffer->pixels) + baseOffset*SW_FRAMEBUFFER_COLOR_SIZE;
+#ifdef SW_ENABLE_DEPTH_TEST
+ uint8_t *dPtr = (uint8_t *)(RLSW.depthBuffer->pixels) + baseOffset*SW_FRAMEBUFFER_DEPTH_SIZE;
+#endif
+
+#define SW_AFFINE_BLOCK 16
+
+ int x = xStart;
+ while (x < xEnd)
+ {
+ // Clamp last block to remaining pixels
+ int blockEnd = x + SW_AFFINE_BLOCK;
+ if (blockEnd > xEnd) blockEnd = xEnd;
+ float blockLenF = (float)(blockEnd - x);
+ float blockLenRcp = 1.0f/blockLenF;
+
+ // Only 2 '1/w' here; none inside the pixel loop
+ float wRcpA = 1.0f/w;
+ float wB = w + dWdx*blockLenF;
+ float wRcpB = 1.0f/wB;
+
+ // Perspective-correct color at both block endpoints, then affine gradient
+ float srcColor[4] = {
+ color[0]*wRcpA,
+ color[1]*wRcpA,
+ color[2]*wRcpA,
+ color[3]*wRcpA
+ };
+ float dSrcColordx[4] = {
+ ((color[0] + dCdx[0]*blockLenF)*wRcpB - srcColor[0])*blockLenRcp,
+ ((color[1] + dCdx[1]*blockLenF)*wRcpB - srcColor[1])*blockLenRcp,
+ ((color[2] + dCdx[2]*blockLenF)*wRcpB - srcColor[2])*blockLenRcp,
+ ((color[3] + dCdx[3]*blockLenF)*wRcpB - srcColor[3])*blockLenRcp
+ };
+
+ #ifdef SW_ENABLE_TEXTURE
+ // Perspective-correct UVs at both endpoints, then affine gradient
+ float uAffine = u*wRcpA;
+ float vAffine = v*wRcpA;
+ float dUaffine = ((u + dUdx*blockLenF)*wRcpB - uAffine)*blockLenRcp;
+ float dVaffine = ((v + dVdx*blockLenF)*wRcpB - vAffine)*blockLenRcp;
+ #endif
+
+ // Inner span pixel loop
+ for (; x < blockEnd; x++)
+ {
+ #ifdef SW_ENABLE_DEPTH_TEST
+ {
+ float depth = SW_FRAMEBUFFER_DEPTH_GET(dPtr, 0);
+ if (z > depth) goto discard;
+ SW_FRAMEBUFFER_DEPTH_SET(dPtr, z, 0);
+ }
+ #endif
+
+ #ifdef SW_ENABLE_TEXTURE
+ {
+ float texColor[4];
+ sw_texture_sample(texColor, RLSW.boundTexture, uAffine, vAffine, dUdx, dUdy, dVdx, dVdy);
+ float finalColor[4] = {
+ srcColor[0]*texColor[0],
+ srcColor[1]*texColor[1],
+ srcColor[2]*texColor[2],
+ srcColor[3]*texColor[3]
+ };
+ #ifdef SW_ENABLE_BLEND
+ {
+ float dstColor[4];
+ SW_FRAMEBUFFER_COLOR_GET(dstColor, cPtr, 0);
+ RLSW.blendFunc(dstColor, finalColor);
+ SW_FRAMEBUFFER_COLOR_SET(cPtr, dstColor, 0);
+ }
+ #else
+ SW_FRAMEBUFFER_COLOR_SET(cPtr, finalColor, 0);
+ #endif
+ }
+ #else
+ {
+ #ifdef SW_ENABLE_BLEND
+ {
+ float dstColor[4];
+ SW_FRAMEBUFFER_COLOR_GET(dstColor, cPtr, 0);
+ RLSW.blendFunc(dstColor, srcColor);
+ SW_FRAMEBUFFER_COLOR_SET(cPtr, dstColor, 0);
+ }
+ #else
+ SW_FRAMEBUFFER_COLOR_SET(cPtr, srcColor, 0);
+ #endif
+ }
+ #endif
+
+ discard:
+ srcColor[0] += dSrcColordx[0];
+ srcColor[1] += dSrcColordx[1];
+ srcColor[2] += dSrcColordx[2];
+ srcColor[3] += dSrcColordx[3];
+ cPtr += SW_FRAMEBUFFER_COLOR_SIZE;
+
+ #ifdef SW_ENABLE_DEPTH_TEST
+ {
+ z += dZdx;
+ dPtr += SW_FRAMEBUFFER_DEPTH_SIZE;
+ }
+ #endif
+
+ #ifdef SW_ENABLE_TEXTURE
+ {
+ uAffine += dUaffine;
+ vAffine += dVaffine;
+ }
+ #endif
+ }
+
+ // Advance perspective-space accumulators by the full block width
+ w = wB;
+ color[0] += dCdx[0]*blockLenF;
+ color[1] += dCdx[1]*blockLenF;
+ color[2] += dCdx[2]*blockLenF;
+ color[3] += dCdx[3]*blockLenF;
+ #ifdef SW_ENABLE_TEXTURE
+ u += dUdx*blockLenF;
+ v += dVdx*blockLenF;
+ #endif
+ }
+
+#undef SW_AFFINE_BLOCK
+}
+
+static void SW_RASTER_TRIANGLE(const sw_vertex_t *v0, const sw_vertex_t *v1, const sw_vertex_t *v2)
+{
+ // Swap vertices by increasing Y
+ if (v0->position[1] > v1->position[1]) { const sw_vertex_t *tmp = v0; v0 = v1; v1 = tmp; }
+ if (v1->position[1] > v2->position[1]) { const sw_vertex_t *tmp = v1; v1 = v2; v2 = tmp; }
+ if (v0->position[1] > v1->position[1]) { const sw_vertex_t *tmp = v0; v0 = v1; v1 = tmp; }
+
+ // Extracting coordinates from the sorted vertices
+ float x0 = v0->position[0], y0 = v0->position[1];
+ float x1 = v1->position[0], y1 = v1->position[1];
+ float x2 = v2->position[0], y2 = v2->position[1];
+
+ // Compute height differences
+ float h02 = y2 - y0;
+ float h01 = y1 - y0;
+ float h12 = y2 - y1;
+
+ if (h02 < 1e-6f) return;
+
+ // Inverse edge dy for per-edge dV/dy (scanline interpolation)
+ float h02Rcp = 1.0f/h02;
+ float h01Rcp = (h01 > 1e-6f)? 1.0f/h01 : 0.0f;
+ float h12Rcp = (h12 > 1e-6f)? 1.0f/h12 : 0.0f;
+
+ // Compute gradients for each side of the triangle
+ sw_vertex_t dVXdy02, dVXdy01, dVXdy12;
+ SW_GET_GRAD(&dVXdy02, v0, v2, h02Rcp);
+ SW_GET_GRAD(&dVXdy01, v0, v1, h01Rcp);
+ SW_GET_GRAD(&dVXdy12, v1, v2, h12Rcp);
+
+ // Y subpixel correction
+ float y0Substep = 1.0f - sw_fract(y0);
+ float y1Substep = 1.0f - sw_fract(y1);
+
+ // Get a copy of vertices for interpolation and apply substep correction
+ sw_vertex_t lVert = *v0, rVert = *v0;
+ SW_ADD_GRAD_SCALED(&lVert, &dVXdy02, y0Substep);
+ SW_ADD_GRAD_SCALED(&rVert, &dVXdy01, y0Substep);
+
+ // Y bounds (vertical clipping)
+ int yTop = (int)y0;
+ int yMid = (int)y1;
+ int yBot = (int)y2;
+
+ // Scanline for the upper part of the triangle
+ for (int y = yTop; y < yMid; y++)
+ {
+ lVert.position[1] = rVert.position[1] = y;
+ bool longSideIsLeft = (lVert.position[0] < rVert.position[0]);
+ const sw_vertex_t *a = longSideIsLeft? &lVert : &rVert;
+ const sw_vertex_t *b = longSideIsLeft? &rVert : &lVert;
+ SW_RASTER_TRIANGLE_SPAN(a, b, dVXdy02.texcoord[0], dVXdy02.texcoord[1]);
+ SW_ADD_GRAD(&lVert, &dVXdy02);
+ SW_ADD_GRAD(&rVert, &dVXdy01);
+ }
+
+ // Get a copy of next right for interpolation and apply substep correction
+ rVert = *v1;
+ SW_ADD_GRAD_SCALED(&rVert, &dVXdy12, y1Substep);
+
+ // Scanline for the lower part of the triangle
+ for (int y = yMid; y < yBot; y++)
+ {
+ lVert.position[1] = rVert.position[1] = y;
+ bool longSideIsLeft = (lVert.position[0] < rVert.position[0]);
+ const sw_vertex_t *a = longSideIsLeft? &lVert : &rVert;
+ const sw_vertex_t *b = longSideIsLeft? &rVert : &lVert;
+ SW_RASTER_TRIANGLE_SPAN(a, b, dVXdy02.texcoord[0], dVXdy02.texcoord[1]);
+ SW_ADD_GRAD(&lVert, &dVXdy02);
+ SW_ADD_GRAD(&rVert, &dVXdy12);
+ }
+}
+
+#undef SW_GET_GRAD
+#undef SW_ADD_GRAD
+#undef SW_ADD_GRAD_SCALED
+
+#endif // RLSW_TEMPLATE_RASTER_TRIANGLE
+//-------------------------------------------------------------------------------------------
+
+// Quad rasterization functions
+//-------------------------------------------------------------------------------------------
+#ifdef RLSW_TEMPLATE_RASTER_QUAD
+
+// Options:
+// - RLSW_TEMPLATE_RASTER_QUAD -> Contains the suffix name
+// - SW_ENABLE_DEPTH_TEST
+// - SW_ENABLE_TEXTURE
+// - SW_ENABLE_BLEND
+
+#define SW_RASTER_QUAD SW_CONCATX(sw_raster_quad_, RLSW_TEMPLATE_RASTER_QUAD)
+
+// NOTE: This function should only render affine axis-aligned quads
+// No perspective divide is applied after interpolation
+
+static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
+ const sw_vertex_t *c, const sw_vertex_t *d)
+{
+ // Classify corners
+ // For axis-aligned quads x+y and x-y uniquely identify each corner
+ const sw_vertex_t *verts[4] = { a, b, c, d };
+ const sw_vertex_t *tl = verts[0], *tr = verts[0], *br = verts[0], *bl = verts[0];
+ for (int i = 1; i < 4; i++)
+ {
+ float sum = verts[i]->position[0] + verts[i]->position[1];
+ float diff = verts[i]->position[0] - verts[i]->position[1];
+ if (sum < tl->position[0] + tl->position[1]) tl = verts[i];
+ if (diff > tr->position[0] - tr->position[1]) tr = verts[i];
+ if (sum > br->position[0] + br->position[1]) br = verts[i];
+ if (diff < bl->position[0] - bl->position[1]) bl = verts[i];
+ }
+
+ int xMin = (int)tl->position[0];
+ int yMin = (int)tl->position[1];
+ int xMax = (int)br->position[0];
+ int yMax = (int)br->position[1];
+
+ float w = (float)(xMax - xMin);
+ float h = (float)(yMax - yMin);
+ if ((w <= 0) || (h <= 0)) return;
+
+ float wRcp = 1.0f/w;
+ float hRcp = 1.0f/h;
+
+ // Subpixel corrections
+ float xSubstep = 1.0f - sw_fract(tl->position[0]);
+ float ySubstep = 1.0f - sw_fract(tl->position[1]);
+
+ // Gradients along X (tl->tr) and Y (tl->bl)
+ float dCdx[4] = {
+ (tr->color[0] - tl->color[0])*wRcp,
+ (tr->color[1] - tl->color[1])*wRcp,
+ (tr->color[2] - tl->color[2])*wRcp,
+ (tr->color[3] - tl->color[3])*wRcp,
+ };
+ float dCdy[4] = {
+ (bl->color[0] - tl->color[0])*hRcp,
+ (bl->color[1] - tl->color[1])*hRcp,
+ (bl->color[2] - tl->color[2])*hRcp,
+ (bl->color[3] - tl->color[3])*hRcp,
+ };
+
+#ifdef SW_ENABLE_DEPTH_TEST
+ float dZdx = (tr->position[2] - tl->position[2])*wRcp;
+ float dZdy = (bl->position[2] - tl->position[2])*hRcp;
+ float zRow = tl->position[2] + dZdx*xSubstep + dZdy*ySubstep;
+#endif
+
+#ifdef SW_ENABLE_TEXTURE
+ float dUdx = (tr->texcoord[0] - tl->texcoord[0])*wRcp;
+ float dVdx = (tr->texcoord[1] - tl->texcoord[1])*wRcp;
+ float dUdy = (bl->texcoord[0] - tl->texcoord[0])*hRcp;
+ float dVdy = (bl->texcoord[1] - tl->texcoord[1])*hRcp;
+ float uRow = tl->texcoord[0] + dUdx*xSubstep + dUdy*ySubstep;
+ float vRow = tl->texcoord[1] + dVdx*xSubstep + dVdy*ySubstep;
+#endif
+
+ float cRow[4] = {
+ tl->color[0] + dCdx[0]*xSubstep + dCdy[0]*ySubstep,
+ tl->color[1] + dCdx[1]*xSubstep + dCdy[1]*ySubstep,
+ tl->color[2] + dCdx[2]*xSubstep + dCdy[2]*ySubstep,
+ tl->color[3] + dCdx[3]*xSubstep + dCdy[3]*ySubstep,
+ };
+
+ int stride = RLSW.colorBuffer->width;
+ uint8_t *cPixels = RLSW.colorBuffer->pixels;
+#ifdef SW_ENABLE_DEPTH_TEST
+ uint8_t *dPixels = RLSW.depthBuffer->pixels;
+#endif
+
+ for (int y = yMin; y < yMax; y++)
+ {
+ int baseOffset = y*stride + xMin;
+ uint8_t *cPtr = cPixels + baseOffset*SW_FRAMEBUFFER_COLOR_SIZE;
+ #ifdef SW_ENABLE_DEPTH_TEST
+ uint8_t *dPtr = dPixels + baseOffset*SW_FRAMEBUFFER_DEPTH_SIZE;
+ float z = zRow;
+ #endif
+ #ifdef SW_ENABLE_TEXTURE
+ float u = uRow;
+ float v = vRow;
+ #endif
+ float color[4] = { cRow[0], cRow[1], cRow[2], cRow[3] };
+
+ for (int x = xMin; x < xMax; x++)
+ {
+ float srcColor[4] = { color[0], color[1], color[2], color[3] };
+
+ #ifdef SW_ENABLE_DEPTH_TEST
+ {
+ float depth = SW_FRAMEBUFFER_DEPTH_GET(dPtr, 0);
+ if (z > depth) goto discard;
+ SW_FRAMEBUFFER_DEPTH_SET(dPtr, z, 0);
+ }
+ #endif
+
+ #ifdef SW_ENABLE_TEXTURE
+ {
+ float texColor[4];
+ sw_texture_sample(texColor, RLSW.boundTexture, u, v, dUdx, dUdy, dVdx, dVdy);
+ srcColor[0] *= texColor[0];
+ srcColor[1] *= texColor[1];
+ srcColor[2] *= texColor[2];
+ srcColor[3] *= texColor[3];
+ }
+ #endif
+
+ #ifdef SW_ENABLE_BLEND
+ {
+ float dstColor[4];
+ SW_FRAMEBUFFER_COLOR_GET(dstColor, cPtr, 0);
+ RLSW.blendFunc(dstColor, srcColor);
+ SW_FRAMEBUFFER_COLOR_SET(cPtr, dstColor, 0);
+ }
+ #else
+ {
+ SW_FRAMEBUFFER_COLOR_SET(cPtr, srcColor, 0);
+ }
+ #endif
+
+ discard:
+ color[0] += dCdx[0];
+ color[1] += dCdx[1];
+ color[2] += dCdx[2];
+ color[3] += dCdx[3];
+
+ #ifdef SW_ENABLE_DEPTH_TEST
+ {
+ z += dZdx;
+ dPtr += SW_FRAMEBUFFER_DEPTH_SIZE;
+ }
+ #endif
+
+ #ifdef SW_ENABLE_TEXTURE
+ {
+ u += dUdx;
+ v += dVdx;
+ }
+ #endif
+
+ cPtr += SW_FRAMEBUFFER_COLOR_SIZE;
+ }
+
+ cRow[0] += dCdy[0];
+ cRow[1] += dCdy[1];
+ cRow[2] += dCdy[2];
+ cRow[3] += dCdy[3];
+
+ #ifdef SW_ENABLE_DEPTH_TEST
+ {
+ zRow += dZdy;
+ }
+ #endif
+
+ #ifdef SW_ENABLE_TEXTURE
+ {
+ uRow += dUdy;
+ vRow += dVdy;
+ }
+ #endif
+ }
+}
+
+#endif // RLSW_TEMPLATE_RASTER_QUAD
+//-------------------------------------------------------------------------------------------
+
+// Quad rasterization functions
+//-------------------------------------------------------------------------------------------
+#ifdef RLSW_TEMPLATE_RASTER_LINE
+
+// Options:
+// - RLSW_TEMPLATE_RASTER_LINE -> Contains the suffix name
+// - SW_ENABLE_DEPTH_TEST
+// - SW_ENABLE_BLEND
+
+#define SW_RASTER_LINE SW_CONCATX(sw_raster_line_, RLSW_TEMPLATE_RASTER_LINE)
+#define SW_RASTER_LINE_THICK SW_CONCATX(sw_raster_line_thick_, RLSW_TEMPLATE_RASTER_LINE)
+
+static void SW_RASTER_LINE(const sw_vertex_t *v0, const sw_vertex_t *v1)
+{
+ // Convert from pixel-center convention (n+0.5) to pixel-origin convention (n)
+ float x0 = v0->position[0] - 0.5f;
+ float y0 = v0->position[1] - 0.5f;
+ float x1 = v1->position[0] - 0.5f;
+ float y1 = v1->position[1] - 0.5f;
+
+ float dx = x1 - x0;
+ float dy = y1 - y0;
+
+ // Compute dominant axis and subpixel offset
+ float steps, substep;
+ if (fabsf(dx) > fabsf(dy))
+ {
+ steps = fabsf(dx);
+ if (steps < 1.0f) return;
+ substep = (dx >= 0.0f)? (1.0f - sw_fract(x0)) : sw_fract(x0);
+ }
+ else
+ {
+ steps = fabsf(dy);
+ if (steps < 1.0f) return;
+ substep = (dy >= 0.0f)? (1.0f - sw_fract(y0)) : sw_fract(y0);
+ }
+
+ // Compute per pixel increments
+ float xInc = dx/steps;
+ float yInc = dy/steps;
+ float stepRcp = 1.0f/steps;
+#ifdef SW_ENABLE_DEPTH_TEST
+ float zInc = (v1->position[2] - v0->position[2])*stepRcp;
+#endif
+ float rInc = (v1->color[0] - v0->color[0])*stepRcp;
+ float gInc = (v1->color[1] - v0->color[1])*stepRcp;
+ float bInc = (v1->color[2] - v0->color[2])*stepRcp;
+ float aInc = (v1->color[3] - v0->color[3])*stepRcp;
+
+ // Initializing the interpolation starting values
+ float x = x0 + xInc*substep;
+ float y = y0 + yInc*substep;
+#ifdef SW_ENABLE_DEPTH_TEST
+ float z = v0->position[2] + zInc*substep;
+#endif
+ float r = v0->color[0] + rInc*substep;
+ float g = v0->color[1] + gInc*substep;
+ float b = v0->color[2] + bInc*substep;
+ float a = v0->color[3] + aInc*substep;
+
+ // Start line rasterization
+ const int fbWidth = RLSW.colorBuffer->width;
+ uint8_t *cPixels = RLSW.colorBuffer->pixels;
+#ifdef SW_ENABLE_DEPTH_TEST
+ uint8_t *dPixels = RLSW.depthBuffer->pixels;
+#endif
+
+ int numPixels = (int)(steps - substep) + 1;
+
+ for (int i = 0; i < numPixels; i++)
+ {
+ int px = x;
+ int py = y;
+
+ int baseOffset = py*fbWidth + px;
+ uint8_t *cPtr = cPixels + baseOffset*SW_FRAMEBUFFER_COLOR_SIZE;
+ #ifdef SW_ENABLE_DEPTH_TEST
+ uint8_t *dPtr = dPixels + baseOffset*SW_FRAMEBUFFER_DEPTH_SIZE;
+ #endif
+
+ #ifdef SW_ENABLE_DEPTH_TEST
+ {
+ // TODO: Implement different depth funcs?
+ float depth = SW_FRAMEBUFFER_DEPTH_GET(dPtr, 0);
+ if (z > depth) goto discard;
+
+ // TODO: Implement depth mask
+ SW_FRAMEBUFFER_DEPTH_SET(dPtr, z, 0);
+ }
+ #endif
+
+ float srcColor[4] = {r, g, b, a};
+
+ #ifdef SW_ENABLE_BLEND
+ {
+ float dstColor[4];
+ SW_FRAMEBUFFER_COLOR_GET(dstColor, cPtr, 0);
+ RLSW.blendFunc(dstColor, srcColor);
+ SW_FRAMEBUFFER_COLOR_SET(cPtr, dstColor, 0);
+ }
+ #else
+ {
+ SW_FRAMEBUFFER_COLOR_SET(cPtr, srcColor, 0);
+ }
+ #endif
+
+ discard:
+ x += xInc;
+ y += yInc;
+ #ifdef SW_ENABLE_DEPTH_TEST
+ {
+ z += zInc;
+ }
+ #endif
+ r += rInc;
+ g += gInc;
+ b += bInc;
+ a += aInc;
+ }
+}
+
+static void SW_RASTER_LINE_THICK(const sw_vertex_t *v0, const sw_vertex_t *v1)
+{
+ sw_vertex_t tv0, tv1;
+
+ int x0 = (int)v0->position[0];
+ int y0 = (int)v0->position[1];
+ int x1 = (int)v1->position[0];
+ int y1 = (int)v1->position[1];
+
+ int dx = x1 - x0;
+ int dy = y1 - y0;
+
+ SW_RASTER_LINE(v0, v1);
+
+ if ((dx != 0) && (abs(dy/dx) < 1))
+ {
+ int wy = (int)((RLSW.lineWidth - 1.0f)*abs(dx)/sqrtf(dx*dx + dy*dy));
+ wy >>= 1;
+ for (int i = 1; i <= wy; i++)
+ {
+ tv0 = *v0, tv1 = *v1;
+ tv0.position[1] -= i;
+ tv1.position[1] -= i;
+ SW_RASTER_LINE(&tv0, &tv1);
+ tv0 = *v0, tv1 = *v1;
+ tv0.position[1] += i;
+ tv1.position[1] += i;
+ SW_RASTER_LINE(&tv0, &tv1);
+ }
+ }
+ else if (dy != 0)
+ {
+ int wx = (int)((RLSW.lineWidth - 1.0f)*abs(dy)/sqrtf(dx*dx + dy*dy));
+ wx >>= 1;
+ for (int i = 1; i <= wx; i++)
+ {
+ tv0 = *v0, tv1 = *v1;
+ tv0.position[0] -= i;
+ tv1.position[0] -= i;
+ SW_RASTER_LINE(&tv0, &tv1);
+ tv0 = *v0, tv1 = *v1;
+ tv0.position[0] += i;
+ tv1.position[0] += i;
+ SW_RASTER_LINE(&tv0, &tv1);
+ }
+ }
+}
+
+#endif // RLSW_TEMPLATE_RASTER_LINE
+//-------------------------------------------------------------------------------------------
+
+// Point rasterization functions
+//-------------------------------------------------------------------------------------------
+#ifdef RLSW_TEMPLATE_RASTER_POINT
+
+// Options:
+// - RLSW_TEMPLATE_RASTER_POINT -> Contains the suffix name
+// - SW_ENABLE_DEPTH_TEST
+// - SW_ENABLE_BLEND
+
+#define SW_RASTER_POINT_PIXEL SW_CONCATX(sw_raster_point_pixel_, RLSW_TEMPLATE_RASTER_POINT)
+#define SW_RASTER_POINT SW_CONCATX(sw_raster_point_, RLSW_TEMPLATE_RASTER_POINT)
+
+static void SW_RASTER_POINT_PIXEL(int x, int y, float z, const float color[4])
+{
+ int offset = y*RLSW.colorBuffer->width + x;
+
+ #ifdef SW_ENABLE_DEPTH_TEST
+ {
+ uint8_t *dPtr = (uint8_t *)(RLSW.depthBuffer->pixels) + offset*SW_FRAMEBUFFER_DEPTH_SIZE;
+
+ // TODO: Implement different depth funcs?
+ float depth = SW_FRAMEBUFFER_DEPTH_GET(dPtr, 0);
+ if (z > depth) return;
+
+ // TODO: Implement depth mask
+ SW_FRAMEBUFFER_DEPTH_SET(dPtr, z, 0);
+ }
+ #endif
+
+ uint8_t *cPtr = (uint8_t *)(RLSW.colorBuffer->pixels) + offset*SW_FRAMEBUFFER_COLOR_SIZE;
+
+ #ifdef SW_ENABLE_BLEND
+ {
+ float dstColor[4];
+ SW_FRAMEBUFFER_COLOR_GET(dstColor, cPtr, 0);
+ RLSW.blendFunc(dstColor, color);
+ SW_FRAMEBUFFER_COLOR_SET(cPtr, dstColor, 0);
+ }
+ #else
+ {
+ SW_FRAMEBUFFER_COLOR_SET(cPtr, color, 0);
+ }
+ #endif
+}
+
+static void SW_RASTER_POINT(const sw_vertex_t *v)
+{
+ int cx = v->position[0];
+ int cy = v->position[1];
+ float cz = v->position[2];
+ int radius = RLSW.pointRadius;
+ const float *color = v->color;
+
+ for (int dy = -radius; dy <= radius; dy++)
+ {
+ for (int dx = -radius; dx <= radius; dx++)
+ {
+ SW_RASTER_POINT_PIXEL(cx + dx, cy + dy, cz, color);
+ }
+ }
+}
+
+#endif // RLSW_TEMPLATE_RASTER_POINT
+//-------------------------------------------------------------------------------------------
diff --git a/src/external/rl_gputex.h b/src/external/rltexgpu.h
similarity index 74%
rename from src/external/rl_gputex.h
rename to src/external/rltexgpu.h
index 033045bc8..eb4d2b6b1 100644
--- a/src/external/rl_gputex.h
+++ b/src/external/rltexgpu.h
@@ -1,6 +1,6 @@
/**********************************************************************************************
*
-* rl_gputex v1.1 - GPU compressed textures loading and saving
+* rltexgpu v1.2 - GPU compressed textures loading and saving
*
* DESCRIPTION:
*
@@ -10,41 +10,40 @@
* Note that some file formats (DDS, PVR, KTX) also support uncompressed data storage.
* In those cases data is loaded uncompressed and format is returned
*
-* FIXME: This library still depends on Raylib due to the following reasons:
+* FIXME: This library still depends on raylib due to the following reasons:
* - rl_save_ktx_to_memory() requires rlGetGlTextureFormats() from rlgl.h
-* though this is not a problem, if you don't need KTX support
*
* TODO:
* - Review rl_load_ktx_from_memory() to support KTX v2.2 specs
*
* CONFIGURATION:
*
-* #define RL_GPUTEX_SUPPORT_DDS
-* #define RL_GPUTEX_SUPPORT_PKM
-* #define RL_GPUTEX_SUPPORT_KTX
-* #define RL_GPUTEX_SUPPORT_PVR
-* #define RL_GPUTEX_SUPPORT_ASTC
+* #define RLTEXGPU_SUPPORT_DDS
+* #define RLTEXGPU_SUPPORT_PKM
+* #define RLTEXGPU_SUPPORT_KTX
+* #define RLTEXGPU_SUPPORT_PVR
+* #define RLTEXGPU_SUPPORT_ASTC
* Define desired file formats to be supported
*
-* #define RL_GPUTEX_SHOW_LOG_INFO
+* #define RLTEXGPU_SHOW_LOG_INFO
* Define, if you wish to see warnings generated by the library
-* This will include unless you provide your own RL_GPUTEX_LOG
-* #define RL_GPUTEX_LOG
+* This will include unless you provide your own RLTEXGPU_LOG
+* #define RLTEXGPU_LOG
* Define, if you wish to provide your own warning function
* Make sure that this macro puts newline character '\n' at the end
*
-* #define RL_GPUTEX_MALLOC
-* #define RL_GPUTEX_FREE
+* #define RLTEXGPU_MALLOC
+* #define RLTEXGPU_FREE
* Define those macros in order to provide your own libc-compliant allocator;
* not doing so will include
* If you're providing any of those, you must provide ALL of them,
* otherwise the code will (most likely) crash...
*
-* #define RL_GPUTEX_NULL
+* #define RLTEXGPU_NULL
* Define in order to provide your own libc-compliant NULL pointer;
* not doing so will include
*
-* #define RL_GPUTEX_MEMCPY
+* #define RLTEXGPU_MEMCPY
* Define in order to provide your own libc-compliant 'memcpy' function;
* not doing so will include
*
@@ -53,12 +52,16 @@
* There is no need to do so when statically linking
*
* VERSIONS HISTORY:
+* 1.2 (18-Mar-2026) Renamed library to `rltexgpu`
+* Improved usage as standalone linrary
+* Decouple logging and memory allocation from raylib
+*
* 1.1 (15-Jul-2025) Several minor fixes related to specific image formats; some work has been done
-* in order to decouple the library from Raylib by introducing few new macros; library still
-* requires Raylib in order to function properly
+* in order to decouple the library from raylib by introducing few new macros; library still
+* requires raylib in order to function properly
*
* 1.0 (17-Sep-2022) First version has been created by migrating part of compressed-texture-loading
-* functionality from Raylib src/rtextures.c into self-contained library
+* functionality from raylib src/rtextures.c into self-contained library
*
* LICENSE: zlib/libpng
*
@@ -81,8 +84,8 @@
*
**********************************************************************************************/
-#ifndef RL_GPUTEX_H
-#define RL_GPUTEX_H
+#ifndef RLTEXGPU_H
+#define RLTEXGPU_H
#ifndef RLGPUTEXAPI
#define RLGPUTEXAPI // Functions defined as 'extern' by default (implicit specifiers)
@@ -93,30 +96,30 @@
// WARNING: Enum values aligned with raylib/rlgl equivalent PixelFormat/rlPixelFormat enum,
// to avoid value mapping between the 3 libraries format values
typedef enum {
- RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
- RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels)
- RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G6B5, // 16 bpp
- RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8, // 24 bpp
- RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
- RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
- RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, // 32 bpp
- RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
- RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
- RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
- RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float)
- RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float)
- RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float)
- RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
- RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
- RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp
- RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT5_RGBA, // 8 bpp
- RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC1_RGB, // 4 bpp
- RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC2_RGB, // 4 bpp
- RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
- RL_GPUTEX_PIXELFORMAT_COMPRESSED_PVRT_RGB, // 4 bpp
- RL_GPUTEX_PIXELFORMAT_COMPRESSED_PVRT_RGBA, // 4 bpp
- RL_GPUTEX_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
- RL_GPUTEX_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA // 2 bpp
+ RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
+ RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels)
+ RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G6B5, // 16 bpp
+ RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8, // 24 bpp
+ RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
+ RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
+ RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, // 32 bpp
+ RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
+ RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
+ RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
+ RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float)
+ RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float)
+ RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float)
+ RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
+ RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
+ RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp
+ RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT5_RGBA, // 8 bpp
+ RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC1_RGB, // 4 bpp
+ RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC2_RGB, // 4 bpp
+ RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
+ RLTEXGPU_PIXELFORMAT_COMPRESSED_PVRT_RGB, // 4 bpp
+ RLTEXGPU_PIXELFORMAT_COMPRESSED_PVRT_RGBA, // 4 bpp
+ RLTEXGPU_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
+ RLTEXGPU_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA // 2 bpp
} rlGpuTexPixelFormat;
//----------------------------------------------------------------------------------
@@ -139,7 +142,7 @@ RLGPUTEXAPI int rl_save_ktx_to_memory(const char *fileName, void *data, int widt
}
#endif
-#endif // RL_GPUTEX_H
+#endif // RLTEXGPU_H
/***********************************************************************************
*
@@ -147,49 +150,49 @@ RLGPUTEXAPI int rl_save_ktx_to_memory(const char *fileName, void *data, int widt
*
************************************************************************************/
-#if defined(RL_GPUTEX_IMPLEMENTATION)
+#if defined(RLTEXGPU_IMPLEMENTATION)
-#if defined(RL_GPUTEX_SHOW_LOG_INFO) && !defined(RL_GPUTEX_LOG)
+#if defined(RLTEXGPU_SHOW_LOG_INFO) && !defined(RLTEXGPU_LOG)
#include // Required for: printf()
#endif
-#if !defined(RL_GPUTEX_MALLOC) || !defined(RL_GPUTEX_NULL)
+#if !defined(RLTEXGPU_MALLOC) || !defined(RLTEXGPU_NULL)
#include // Required for: NULL, malloc(), calloc(), free()
#endif
-#if !defined(RL_GPUTEX_MEMCPY)
+#if !defined(RLTEXGPU_MEMCPY)
#include // Required for: memcpy()
#endif
-#if defined(RL_GPUTEX_MALLOC) || defined(RL_GPUTEX_FREE)
- #if !defined(RL_GPUTEX_MALLOC) || !defined(RL_GPUTEX_FREE)
- #warning "RL_GPUTEX_MALLOC and RL_GPUTEX_FREE allocation functions are required to be provided"
+#if defined(RLTEXGPU_MALLOC) || defined(RLTEXGPU_FREE)
+ #if !defined(RLTEXGPU_MALLOC) || !defined(RLTEXGPU_FREE)
+ #warning "RLTEXGPU_MALLOC and RLTEXGPU_FREE allocation functions are required to be provided"
#endif
#endif
-#if !defined(RL_GPUTEX_MALLOC)
- #define RL_GPUTEX_MALLOC(sz) malloc(sz)
- #define RL_GPUTEX_FREE(ptr) free(ptr)
+#if !defined(RLTEXGPU_MALLOC)
+ #define RLTEXGPU_MALLOC(sz) malloc(sz)
+ #define RLTEXGPU_FREE(ptr) free(ptr)
#endif
-#if !defined(RL_GPUTEX_NULL)
- #define RL_GPUTEX_NULL NULL
+#if !defined(RLTEXGPU_NULL)
+ #define RLTEXGPU_NULL NULL
#endif
-#if !defined(RL_GPUTEX_MEMCPY)
- #define RL_GPUTEX_MEMCPY(dest, src, num) memcpy(dest, src, num)
+#if !defined(RLTEXGPU_MEMCPY)
+ #define RLTEXGPU_MEMCPY(dest, src, num) memcpy(dest, src, num)
#endif
// Simple warning logging system to avoid LOG() calls if required
// NOTE: Avoiding those calls, also avoids const strings memory usage
-// WARN: This macro expects that newline character is added automatically
-// in order to match the functionality of Raylib's TRACELOG()
-#if defined(RL_GPUTEX_SHOW_LOG_INFO)
- #if !defined(RL_GPUTEX_LOG)
- #define RL_GPUTEX_LOG(...) (void)(printf("RL_GPUTEX: WARNING: " __VA_ARGS__), printf("\n"))
+// WARNING: This macro expects that newline character is added automatically
+// in order to match the functionality of raylib's TRACELOG()
+#if defined(RLTEXGPU_SHOW_LOG_INFO)
+ #if !defined(RLTEXGPU_LOG)
+ #define RLTEXGPU_LOG(...) (void)(printf("RL_GPUTEX: WARNING: " __VA_ARGS__), printf("\n"))
#endif
#else
- #if defined(RL_GPUTEX_LOG)
+ #if defined(RLTEXGPU_LOG)
// Undefine it first in order to supress warnings about macro redefinition
- #undef RL_GPUTEX_LOG
+ #undef RLTEXGPU_LOG
#endif
- #define RL_GPUTEX_LOG(...)
+ #define RLTEXGPU_LOG(...)
#endif
//----------------------------------------------------------------------------------
@@ -204,11 +207,11 @@ void get_gl_texture_formats(int format, unsigned int *gl_internal_format, unsign
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
-#if defined(RL_GPUTEX_SUPPORT_DDS)
+#if defined(RLTEXGPU_SUPPORT_DDS)
// Loading DDS from memory image data (compressed or uncompressed)
void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips)
{
- void *image_data = RL_GPUTEX_NULL; // Image data pointer
+ void *image_data = RLTEXGPU_NULL; // Image data pointer
int image_pixel_size = 0; // Image pixel size
unsigned char *file_data_ptr = (unsigned char *)file_data;
@@ -256,7 +259,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
unsigned int reserved2;
} dds_header;
- if (file_data_ptr != RL_GPUTEX_NULL)
+ if (file_data_ptr != RLTEXGPU_NULL)
{
// Verify the type of file
unsigned char *dds_header_id = file_data_ptr;
@@ -264,7 +267,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
if ((dds_header_id[0] != 'D') || (dds_header_id[1] != 'D') || (dds_header_id[2] != 'S') || (dds_header_id[3] != ' '))
{
- RL_GPUTEX_LOG("DDS file data not valid");
+ RLTEXGPU_LOG("DDS file data not valid");
}
else
{
@@ -275,8 +278,8 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
*width = header->width;
*height = header->height;
- if (*width % 4 != 0) RL_GPUTEX_LOG("DDS file width must be multiple of 4. Image will not display correctly");
- if (*height % 4 != 0) RL_GPUTEX_LOG("DDS file height must be multiple of 4. Image will not display correctly");
+ if (*width % 4 != 0) RLTEXGPU_LOG("DDS file width must be multiple of 4. Image will not display correctly");
+ if (*height % 4 != 0) RLTEXGPU_LOG("DDS file height must be multiple of 4. Image will not display correctly");
image_pixel_size = header->width*header->height;
@@ -289,11 +292,11 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
{
int data_size = image_pixel_size*sizeof(unsigned short);
if (header->mipmap_count > 1) data_size = data_size + data_size/3;
- image_data = RL_GPUTEX_MALLOC(data_size);
+ image_data = RLTEXGPU_MALLOC(data_size);
- RL_GPUTEX_MEMCPY(image_data, file_data_ptr, data_size);
+ RLTEXGPU_MEMCPY(image_data, file_data_ptr, data_size);
- *format = RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G6B5;
+ *format = RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G6B5;
}
else if (header->ddspf.flags == 0x41) // With alpha channel
{
@@ -301,9 +304,9 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
{
int data_size = image_pixel_size*sizeof(unsigned short);
if (header->mipmap_count > 1) data_size = data_size + data_size/3;
- image_data = RL_GPUTEX_MALLOC(data_size);
+ image_data = RLTEXGPU_MALLOC(data_size);
- RL_GPUTEX_MEMCPY(image_data, file_data_ptr, data_size);
+ RLTEXGPU_MEMCPY(image_data, file_data_ptr, data_size);
unsigned char alpha = 0;
@@ -315,15 +318,15 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
((unsigned short *)image_data)[i] += alpha;
}
- *format = RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1;
+ *format = RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1;
}
else if (header->ddspf.a_bit_mask == 0xf000) // 4bit alpha
{
int data_size = image_pixel_size*sizeof(unsigned short);
if (header->mipmap_count > 1) data_size = data_size + data_size/3;
- image_data = RL_GPUTEX_MALLOC(data_size);
+ image_data = RLTEXGPU_MALLOC(data_size);
- RL_GPUTEX_MEMCPY(image_data, file_data_ptr, data_size);
+ RLTEXGPU_MEMCPY(image_data, file_data_ptr, data_size);
unsigned char alpha = 0;
@@ -335,7 +338,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
((unsigned short *)image_data)[i] += alpha;
}
- *format = RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4;
+ *format = RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4;
}
}
}
@@ -343,19 +346,19 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
{
int data_size = image_pixel_size*3*sizeof(unsigned char);
if (header->mipmap_count > 1) data_size = data_size + data_size/3;
- image_data = RL_GPUTEX_MALLOC(data_size);
+ image_data = RLTEXGPU_MALLOC(data_size);
- RL_GPUTEX_MEMCPY(image_data, file_data_ptr, data_size);
+ RLTEXGPU_MEMCPY(image_data, file_data_ptr, data_size);
- *format = RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8;
+ *format = RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8;
}
else if ((header->ddspf.flags == 0x41) && (header->ddspf.rgb_bit_count == 32)) // DDS_RGBA, no compressed
{
int data_size = image_pixel_size*4*sizeof(unsigned char);
if (header->mipmap_count > 1) data_size = data_size + data_size/3;
- image_data = RL_GPUTEX_MALLOC(data_size);
+ image_data = RLTEXGPU_MALLOC(data_size);
- RL_GPUTEX_MEMCPY(image_data, file_data_ptr, data_size);
+ RLTEXGPU_MEMCPY(image_data, file_data_ptr, data_size);
unsigned char blue = 0;
@@ -369,7 +372,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
((unsigned char *)image_data)[i + 2] = blue;
}
- *format = RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
+ *format = RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
}
else if (((header->ddspf.flags == 0x04) || (header->ddspf.flags == 0x05)) && (header->ddspf.fourcc > 0)) // Compressed
{
@@ -379,19 +382,19 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
if (header->mipmap_count > 1) data_size = header->pitch_or_linear_size + header->pitch_or_linear_size/3;
else data_size = header->pitch_or_linear_size;
- image_data = RL_GPUTEX_MALLOC(data_size*sizeof(unsigned char));
+ image_data = RLTEXGPU_MALLOC(data_size*sizeof(unsigned char));
- RL_GPUTEX_MEMCPY(image_data, file_data_ptr, data_size);
+ RLTEXGPU_MEMCPY(image_data, file_data_ptr, data_size);
switch (header->ddspf.fourcc)
{
case FOURCC_DXT1:
{
- if (header->ddspf.flags == 0x04) *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT1_RGB;
- else *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT1_RGBA;
+ if (header->ddspf.flags == 0x04) *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT1_RGB;
+ else *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT1_RGBA;
} break;
- case FOURCC_DXT3: *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT3_RGBA; break;
- case FOURCC_DXT5: *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT5_RGBA; break;
+ case FOURCC_DXT3: *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT3_RGBA; break;
+ case FOURCC_DXT5: *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT5_RGBA; break;
default: break;
}
}
@@ -402,13 +405,13 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
}
#endif
-#if defined(RL_GPUTEX_SUPPORT_PKM)
+#if defined(RLTEXGPU_SUPPORT_PKM)
// Loading PKM image data (ETC1/ETC2 compression)
// NOTE: KTX is the standard Khronos Group compression format (ETC1/ETC2, mipmaps)
// PKM is a much simpler file format used mainly to contain a single ETC1/ETC2 compressed image (no mipmaps)
void *rl_load_pkm_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips)
{
- void *image_data = RL_GPUTEX_NULL; // Image data pointer
+ void *image_data = RLTEXGPU_NULL; // Image data pointer
unsigned char *file_data_ptr = (unsigned char *)file_data;
@@ -439,13 +442,13 @@ void *rl_load_pkm_from_memory(const unsigned char *file_data, unsigned int file_
// NOTE: The extended width and height are the widths rounded up to a multiple of 4
// NOTE: ETC is always 4bit per pixel (64 bit for each 4x4 block of pixels)
- if (file_data_ptr != RL_GPUTEX_NULL)
+ if (file_data_ptr != RLTEXGPU_NULL)
{
pkm_header *header = (pkm_header *)file_data_ptr;
if ((header->id[0] != 'P') || (header->id[1] != 'K') || (header->id[2] != 'M') || (header->id[3] != ' '))
{
- RL_GPUTEX_LOG("PKM file data not valid");
+ RLTEXGPU_LOG("PKM file data not valid");
}
else
{
@@ -465,13 +468,13 @@ void *rl_load_pkm_from_memory(const unsigned char *file_data, unsigned int file_
int data_size = (*width)*(*height)*bpp/8; // Total data size in bytes
- image_data = RL_GPUTEX_MALLOC(data_size*sizeof(unsigned char));
+ image_data = RLTEXGPU_MALLOC(data_size*sizeof(unsigned char));
- RL_GPUTEX_MEMCPY(image_data, file_data_ptr, data_size);
+ RLTEXGPU_MEMCPY(image_data, file_data_ptr, data_size);
- if (header->format == 0) *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC1_RGB;
- else if (header->format == 1) *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC2_RGB;
- else if (header->format == 3) *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA;
+ if (header->format == 0) *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC1_RGB;
+ else if (header->format == 1) *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC2_RGB;
+ else if (header->format == 3) *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA;
}
}
@@ -479,12 +482,12 @@ void *rl_load_pkm_from_memory(const unsigned char *file_data, unsigned int file_
}
#endif
-#if defined(RL_GPUTEX_SUPPORT_KTX)
+#if defined(RLTEXGPU_SUPPORT_KTX)
// Load KTX compressed image data (ETC1/ETC2 compression)
// TODO: Review KTX loading, many things changed!
void *rl_load_ktx_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips)
{
- void *image_data = RL_GPUTEX_NULL; // Image data pointer
+ void *image_data = RLTEXGPU_NULL; // Image data pointer
unsigned char *file_data_ptr = (unsigned char *)file_data;
@@ -522,14 +525,14 @@ void *rl_load_ktx_from_memory(const unsigned char *file_data, unsigned int file_
// NOTE: Before start of every mipmap data block, we have: unsigned int data_size
- if (file_data_ptr != RL_GPUTEX_NULL)
+ if (file_data_ptr != RLTEXGPU_NULL)
{
ktx_header *header = (ktx_header *)file_data_ptr;
if ((header->id[1] != 'K') || (header->id[2] != 'T') || (header->id[3] != 'X') ||
(header->id[4] != ' ') || (header->id[5] != '1') || (header->id[6] != '1'))
{
- RL_GPUTEX_LOG("KTX file data not valid");
+ RLTEXGPU_LOG("KTX file data not valid");
}
else
{
@@ -544,13 +547,13 @@ void *rl_load_ktx_from_memory(const unsigned char *file_data, unsigned int file_
int data_size = ((int *)file_data_ptr)[0];
file_data_ptr += sizeof(int);
- image_data = RL_GPUTEX_MALLOC(data_size*sizeof(unsigned char));
+ image_data = RLTEXGPU_MALLOC(data_size*sizeof(unsigned char));
- RL_GPUTEX_MEMCPY(image_data, file_data_ptr, data_size);
+ RLTEXGPU_MEMCPY(image_data, file_data_ptr, data_size);
- if (header->gl_internal_format == 0x8D64) *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC1_RGB;
- else if (header->gl_internal_format == 0x9274) *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC2_RGB;
- else if (header->gl_internal_format == 0x9278) *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA;
+ if (header->gl_internal_format == 0x8D64) *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC1_RGB;
+ else if (header->gl_internal_format == 0x9274) *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC2_RGB;
+ else if (header->gl_internal_format == 0x9278) *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA;
// TODO: Support uncompressed data formats? Right now it returns format = 0!
}
@@ -608,7 +611,7 @@ int rl_save_ktx(const char *file_name, void *data, int width, int height, int fo
w /= 2; h /= 2;
}
- unsigned char *file_data = RL_GPUTEX_MALLOC(data_size);
+ unsigned char *file_data = RLTEXGPU_MALLOC(data_size);
unsigned char *file_data_ptr = file_data;
ktx_header header = { 0 };
@@ -620,7 +623,7 @@ int rl_save_ktx(const char *file_name, void *data, int width, int height, int fo
const char ktx_identifier[12] = { 0xAB, 'K', 'T', 'X', ' ', '1', '1', 0xBB, '\r', '\n', 0x1A, '\n' };
// Get the image header
- RL_GPUTEX_MEMCPY(header.id, ktx_identifier, 12); // KTX 1.1 signature
+ RLTEXGPU_MEMCPY(header.id, ktx_identifier, 12); // KTX 1.1 signature
header.endianness = 0;
header.gl_type = 0; // Obtained from format
header.gl_type_size = 1;
@@ -642,10 +645,10 @@ int rl_save_ktx(const char *file_name, void *data, int width, int height, int fo
// NOTE: We can save into a .ktx all PixelFormats supported by raylib, including compressed formats like DXT, ETC or ASTC
- if (header.gl_format == -1) RL_GPUTEX_LOG("RL_GPUTEX: GL format not supported for KTX export (%i)", header.gl_format);
+ if (header.gl_format == -1) RLTEXGPU_LOG("RL_GPUTEX: GL format not supported for KTX export (%i)", header.gl_format);
else
{
- RL_GPUTEX_MEMCPY(file_data_ptr, &header, sizeof(ktx_header));
+ RLTEXGPU_MEMCPY(file_data_ptr, &header, sizeof(ktx_header));
file_data_ptr += sizeof(ktx_header);
int temp_width = width;
@@ -657,8 +660,8 @@ int rl_save_ktx(const char *file_name, void *data, int width, int height, int fo
{
unsigned int data_size = get_pixel_data_size(temp_width, temp_height, format);
- RL_GPUTEX_MEMCPY(file_data_ptr, &data_size, sizeof(unsigned int));
- RL_GPUTEX_MEMCPY(file_data_ptr + 4, (unsigned char *)data + data_offset, data_size);
+ RLTEXGPU_MEMCPY(file_data_ptr, &data_size, sizeof(unsigned int));
+ RLTEXGPU_MEMCPY(file_data_ptr + 4, (unsigned char *)data + data_offset, data_size);
temp_width /= 2;
temp_height /= 2;
@@ -671,34 +674,34 @@ int rl_save_ktx(const char *file_name, void *data, int width, int height, int fo
int success = false;
FILE *file = fopen(file_name, "wb");
- if (file != RL_GPUTEX_NULL)
+ if (file != RLTEXGPU_NULL)
{
unsigned int count = (unsigned int)fwrite(file_data, sizeof(unsigned char), data_size, file);
- if (count == 0) RL_GPUTEX_LOG("FILEIO: [%s] Failed to write file", file_name);
- else if (count != data_size) RL_GPUTEX_LOG("FILEIO: [%s] File partially written", file_name);
- else (void)0; // WARN: this branch is handled by Raylib, since rl_gputex only prints warnings
+ if (count == 0) RLTEXGPU_LOG("FILEIO: [%s] Failed to write file", file_name);
+ else if (count != data_size) RLTEXGPU_LOG("FILEIO: [%s] File partially written", file_name);
+ else (void)0;
int result = fclose(file);
- if (result != 0) RL_GPUTEX_LOG("FILEIO: [%s] Failed to close file", file_name);
+ if (result != 0) RLTEXGPU_LOG("FILEIO: [%s] Failed to close file", file_name);
if (result == 0 && count == data_size) success = true;
}
- else RL_GPUTEX_LOG("FILEIO: [%s] Failed to open file", file_name);
+ else RLTEXGPU_LOG("FILEIO: [%s] Failed to open file", file_name);
- RL_GPUTEX_FREE(file_data); // Free file data buffer
+ RLTEXGPU_FREE(file_data); // Free file data buffer
// If all data has been written correctly to file, success = 1
return success;
}
#endif
-#if defined(RL_GPUTEX_SUPPORT_PVR)
+#if defined(RLTEXGPU_SUPPORT_PVR)
// Loading PVR image data (uncompressed or PVRT compression)
// NOTE: PVR v2 not supported, use PVR v3 instead
void *rl_load_pvr_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips)
{
- void *image_data = RL_GPUTEX_NULL; // Image data pointer
+ void *image_data = RLTEXGPU_NULL; // Image data pointer
unsigned char *file_data_ptr = (unsigned char *)file_data;
@@ -756,7 +759,7 @@ void *rl_load_pvr_from_memory(const unsigned char *file_data, unsigned int file_
} PVRMetadata;
#endif
- if (file_data_ptr != RL_GPUTEX_NULL)
+ if (file_data_ptr != RLTEXGPU_NULL)
{
// Check PVR image version
unsigned char pvr_version = file_data_ptr[0];
@@ -768,7 +771,7 @@ void *rl_load_pvr_from_memory(const unsigned char *file_data, unsigned int file_
if ((header->id[0] != 'P') || (header->id[1] != 'V') || (header->id[2] != 'R') || (header->id[3] != 3))
{
- RL_GPUTEX_LOG("PVR file data not valid");
+ RLTEXGPU_LOG("PVR file data not valid");
}
else
{
@@ -779,24 +782,24 @@ void *rl_load_pvr_from_memory(const unsigned char *file_data, unsigned int file_
*mips = header->num_mipmaps;
// Check data format
- if (((header->channels[0] == 'l') && (header->channels[1] == 0)) && (header->channel_depth[0] == 8)) *format = RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
- else if (((header->channels[0] == 'l') && (header->channels[1] == 'a')) && ((header->channel_depth[0] == 8) && (header->channel_depth[1] == 8))) *format = RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
+ if (((header->channels[0] == 'l') && (header->channels[1] == 0)) && (header->channel_depth[0] == 8)) *format = RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
+ else if (((header->channels[0] == 'l') && (header->channels[1] == 'a')) && ((header->channel_depth[0] == 8) && (header->channel_depth[1] == 8))) *format = RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
else if ((header->channels[0] == 'r') && (header->channels[1] == 'g') && (header->channels[2] == 'b'))
{
if (header->channels[3] == 'a')
{
- if ((header->channel_depth[0] == 5) && (header->channel_depth[1] == 5) && (header->channel_depth[2] == 5) && (header->channel_depth[3] == 1)) *format = RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1;
- else if ((header->channel_depth[0] == 4) && (header->channel_depth[1] == 4) && (header->channel_depth[2] == 4) && (header->channel_depth[3] == 4)) *format = RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4;
- else if ((header->channel_depth[0] == 8) && (header->channel_depth[1] == 8) && (header->channel_depth[2] == 8) && (header->channel_depth[3] == 8)) *format = RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
+ if ((header->channel_depth[0] == 5) && (header->channel_depth[1] == 5) && (header->channel_depth[2] == 5) && (header->channel_depth[3] == 1)) *format = RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1;
+ else if ((header->channel_depth[0] == 4) && (header->channel_depth[1] == 4) && (header->channel_depth[2] == 4) && (header->channel_depth[3] == 4)) *format = RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4;
+ else if ((header->channel_depth[0] == 8) && (header->channel_depth[1] == 8) && (header->channel_depth[2] == 8) && (header->channel_depth[3] == 8)) *format = RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
}
else if (header->channels[3] == 0)
{
- if ((header->channel_depth[0] == 5) && (header->channel_depth[1] == 6) && (header->channel_depth[2] == 5)) *format = RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G6B5;
- else if ((header->channel_depth[0] == 8) && (header->channel_depth[1] == 8) && (header->channel_depth[2] == 8)) *format = RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8;
+ if ((header->channel_depth[0] == 5) && (header->channel_depth[1] == 6) && (header->channel_depth[2] == 5)) *format = RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G6B5;
+ else if ((header->channel_depth[0] == 8) && (header->channel_depth[1] == 8) && (header->channel_depth[2] == 8)) *format = RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8;
}
}
- else if (header->channels[0] == 2) *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_PVRT_RGB;
- else if (header->channels[0] == 3) *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_PVRT_RGBA;
+ else if (header->channels[0] == 2) *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_PVRT_RGB;
+ else if (header->channels[0] == 3) *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_PVRT_RGBA;
file_data_ptr += header->metadata_size; // Skip meta data header
@@ -804,36 +807,36 @@ void *rl_load_pvr_from_memory(const unsigned char *file_data, unsigned int file_
int bpp = 0;
switch (*format)
{
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 8; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G6B5:
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 16; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 32; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 24; break;
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_PVRT_RGB:
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 8; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G6B5:
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 16; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 32; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 24; break;
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_PVRT_RGB:
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break;
default: break;
}
int data_size = (*width)*(*height)*bpp/8; // Total data size in bytes
- image_data = RL_GPUTEX_MALLOC(data_size*sizeof(unsigned char));
+ image_data = RLTEXGPU_MALLOC(data_size*sizeof(unsigned char));
- RL_GPUTEX_MEMCPY(image_data, file_data_ptr, data_size);
+ RLTEXGPU_MEMCPY(image_data, file_data_ptr, data_size);
}
}
- else if (pvr_version == 52) RL_GPUTEX_LOG("PVRv2 format not supported, update your files to PVRv3");
+ else if (pvr_version == 52) RLTEXGPU_LOG("PVRv2 format not supported, update your files to PVRv3");
}
return image_data;
}
#endif
-#if defined(RL_GPUTEX_SUPPORT_ASTC)
+#if defined(RLTEXGPU_SUPPORT_ASTC)
// Load ASTC compressed image data (ASTC compression)
void *rl_load_astc_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips)
{
- void *image_data = RL_GPUTEX_NULL; // Image data pointer
+ void *image_data = RLTEXGPU_NULL; // Image data pointer
unsigned char *file_data_ptr = (unsigned char *)file_data;
@@ -856,13 +859,13 @@ void *rl_load_astc_from_memory(const unsigned char *file_data, unsigned int file
unsigned char length[3]; // void *Z-size (1 for 2D images)
} astc_header;
- if (file_data_ptr != RL_GPUTEX_NULL)
+ if (file_data_ptr != RLTEXGPU_NULL)
{
astc_header *header = (astc_header *)file_data_ptr;
if ((header->id[3] != 0x5c) || (header->id[2] != 0xa1) || (header->id[1] != 0xab) || (header->id[0] != 0x13))
{
- RL_GPUTEX_LOG("ASTC file data not valid");
+ RLTEXGPU_LOG("ASTC file data not valid");
}
else
{
@@ -881,14 +884,14 @@ void *rl_load_astc_from_memory(const unsigned char *file_data, unsigned int file
{
int data_size = (*width)*(*height)*bpp/8; // Data size in bytes
- image_data = RL_GPUTEX_MALLOC(data_size*sizeof(unsigned char));
+ image_data = RLTEXGPU_MALLOC(data_size*sizeof(unsigned char));
- RL_GPUTEX_MEMCPY(image_data, file_data_ptr, data_size);
+ RLTEXGPU_MEMCPY(image_data, file_data_ptr, data_size);
- if (bpp == 8) *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA;
- else if (bpp == 2) *format = RL_GPUTEX_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA;
+ if (bpp == 8) *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA;
+ else if (bpp == 2) *format = RLTEXGPU_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA;
}
- else RL_GPUTEX_LOG("ASTC block size configuration not supported");
+ else RLTEXGPU_LOG("ASTC block size configuration not supported");
}
}
@@ -907,27 +910,27 @@ static int get_pixel_data_size(int width, int height, int format)
switch (format)
{
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 8; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G6B5:
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 16; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 32; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 24; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32: bpp = 32; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 32*3; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break;
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT1_RGB:
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT1_RGBA:
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC1_RGB:
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC2_RGB:
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_PVRT_RGB:
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break;
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT3_RGBA:
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT5_RGBA:
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA:
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: bpp = 8; break;
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 8; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G6B5:
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 16; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 32; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 24; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32: bpp = 32; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 32*3; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break;
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT1_RGB:
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT1_RGBA:
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC1_RGB:
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC2_RGB:
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_PVRT_RGB:
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break;
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT3_RGBA:
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT5_RGBA:
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA:
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: bpp = 8; break;
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break;
default: break;
}
@@ -937,8 +940,8 @@ static int get_pixel_data_size(int width, int height, int format)
// if texture is smaller, minimum dataSize is 8 or 16
if ((width < 4) && (height < 4))
{
- if ((format >= RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT3_RGBA)) data_size = 8;
- else if ((format >= RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < RL_GPUTEX_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) data_size = 16;
+ if ((format >= RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT3_RGBA)) data_size = 8;
+ else if ((format >= RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < RLTEXGPU_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) data_size = 16;
}
return data_size;
@@ -959,69 +962,69 @@ void get_gl_texture_formats(int format, unsigned int *gl_internal_format, unsign
{
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_ES2)
// NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *gl_internal_format = GL_LUMINANCE; *gl_format = GL_LUMINANCE; *gl_type = GL_UNSIGNED_BYTE; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *gl_internal_format = GL_LUMINANCE_ALPHA; *gl_format = GL_LUMINANCE_ALPHA; *gl_type = GL_UNSIGNED_BYTE; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G6B5: *gl_internal_format = GL_RGB; *gl_format = GL_RGB; *gl_type = GL_UNSIGNED_SHORT_5_6_5; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8: *gl_internal_format = GL_RGB; *gl_format = GL_RGB; *gl_type = GL_UNSIGNED_BYTE; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *gl_internal_format = GL_RGBA; *gl_format = GL_RGBA; *gl_type = GL_UNSIGNED_SHORT_5_5_5_1; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *gl_internal_format = GL_RGBA; *gl_format = GL_RGBA; *gl_type = GL_UNSIGNED_SHORT_4_4_4_4; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *gl_internal_format = GL_RGBA; *gl_format = GL_RGBA; *gl_type = GL_UNSIGNED_BYTE; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *gl_internal_format = GL_LUMINANCE; *gl_format = GL_LUMINANCE; *gl_type = GL_UNSIGNED_BYTE; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *gl_internal_format = GL_LUMINANCE_ALPHA; *gl_format = GL_LUMINANCE_ALPHA; *gl_type = GL_UNSIGNED_BYTE; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G6B5: *gl_internal_format = GL_RGB; *gl_format = GL_RGB; *gl_type = GL_UNSIGNED_SHORT_5_6_5; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8: *gl_internal_format = GL_RGB; *gl_format = GL_RGB; *gl_type = GL_UNSIGNED_BYTE; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *gl_internal_format = GL_RGBA; *gl_format = GL_RGBA; *gl_type = GL_UNSIGNED_SHORT_5_5_5_1; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *gl_internal_format = GL_RGBA; *gl_format = GL_RGBA; *gl_type = GL_UNSIGNED_SHORT_4_4_4_4; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *gl_internal_format = GL_RGBA; *gl_format = GL_RGBA; *gl_type = GL_UNSIGNED_BYTE; break;
#if !defined(GRAPHICS_API_OPENGL_11)
#if defined(GRAPHICS_API_OPENGL_ES3)
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32: *gl_internal_format = GL_R32F_EXT; *gl_format = GL_RED_EXT; *gl_type = GL_FLOAT; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32G32B32: *gl_internal_format = GL_RGB32F_EXT; *gl_format = GL_RGB; *gl_type = GL_FLOAT; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: *gl_internal_format = GL_RGBA32F_EXT; *gl_format = GL_RGBA; *gl_type = GL_FLOAT; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16: *gl_internal_format = GL_R16F_EXT; *gl_format = GL_RED_EXT; *gl_type = GL_HALF_FLOAT; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16G16B16: *gl_internal_format = GL_RGB16F_EXT; *gl_format = GL_RGB; *gl_type = GL_HALF_FLOAT; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: *gl_internal_format = GL_RGBA16F_EXT; *gl_format = GL_RGBA; *gl_type = GL_HALF_FLOAT; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32: *gl_internal_format = GL_R32F_EXT; *gl_format = GL_RED_EXT; *gl_type = GL_FLOAT; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32G32B32: *gl_internal_format = GL_RGB32F_EXT; *gl_format = GL_RGB; *gl_type = GL_FLOAT; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: *gl_internal_format = GL_RGBA32F_EXT; *gl_format = GL_RGBA; *gl_type = GL_FLOAT; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16: *gl_internal_format = GL_R16F_EXT; *gl_format = GL_RED_EXT; *gl_type = GL_HALF_FLOAT; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16G16B16: *gl_internal_format = GL_RGB16F_EXT; *gl_format = GL_RGB; *gl_type = GL_HALF_FLOAT; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: *gl_internal_format = GL_RGBA16F_EXT; *gl_format = GL_RGBA; *gl_type = GL_HALF_FLOAT; break;
#else
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32: *gl_internal_format = GL_LUMINANCE; *gl_format = GL_LUMINANCE; *gl_type = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32G32B32: *gl_internal_format = GL_RGB; *gl_format = GL_RGB; *gl_type = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: *gl_internal_format = GL_RGBA; *gl_format = GL_RGBA; *gl_type = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32: *gl_internal_format = GL_LUMINANCE; *gl_format = GL_LUMINANCE; *gl_type = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32G32B32: *gl_internal_format = GL_RGB; *gl_format = GL_RGB; *gl_type = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: *gl_internal_format = GL_RGBA; *gl_format = GL_RGBA; *gl_type = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
#if defined(GRAPHICS_API_OPENGL_21)
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16: *gl_internal_format = GL_LUMINANCE; *gl_format = GL_LUMINANCE; *gl_type = GL_HALF_FLOAT_ARB; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16G16B16: *gl_internal_format = GL_RGB; *gl_format = GL_RGB; *gl_type = GL_HALF_FLOAT_ARB; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: *gl_internal_format = GL_RGBA; *gl_format = GL_RGBA; *gl_type = GL_HALF_FLOAT_ARB; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16: *gl_internal_format = GL_LUMINANCE; *gl_format = GL_LUMINANCE; *gl_type = GL_HALF_FLOAT_ARB; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16G16B16: *gl_internal_format = GL_RGB; *gl_format = GL_RGB; *gl_type = GL_HALF_FLOAT_ARB; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: *gl_internal_format = GL_RGBA; *gl_format = GL_RGBA; *gl_type = GL_HALF_FLOAT_ARB; break;
#else // defined(GRAPHICS_API_OPENGL_ES2)
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16: *gl_internal_format = GL_LUMINANCE; *gl_format = GL_LUMINANCE; *gl_type = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16G16B16: *gl_internal_format = GL_RGB; *gl_format = GL_RGB; *gl_type = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: *gl_internal_format = GL_RGBA; *gl_format = GL_RGBA; *gl_type = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16: *gl_internal_format = GL_LUMINANCE; *gl_format = GL_LUMINANCE; *gl_type = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16G16B16: *gl_internal_format = GL_RGB; *gl_format = GL_RGB; *gl_type = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: *gl_internal_format = GL_RGBA; *gl_format = GL_RGBA; *gl_type = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
#endif
#endif
#endif
#elif defined(GRAPHICS_API_OPENGL_33)
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *gl_internal_format = GL_R8; *gl_format = GL_RED; *gl_type = GL_UNSIGNED_BYTE; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *gl_internal_format = GL_RG8; *gl_format = GL_RG; *gl_type = GL_UNSIGNED_BYTE; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G6B5: *gl_internal_format = GL_RGB565; *gl_format = GL_RGB; *gl_type = GL_UNSIGNED_SHORT_5_6_5; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8: *gl_internal_format = GL_RGB8; *gl_format = GL_RGB; *gl_type = GL_UNSIGNED_BYTE; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *gl_internal_format = GL_RGB5_A1; *gl_format = GL_RGBA; *gl_type = GL_UNSIGNED_SHORT_5_5_5_1; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *gl_internal_format = GL_RGBA4; *gl_format = GL_RGBA; *gl_type = GL_UNSIGNED_SHORT_4_4_4_4; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *gl_internal_format = GL_RGBA8; *gl_format = GL_RGBA; *gl_type = GL_UNSIGNED_BYTE; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32: *gl_internal_format = GL_R32F; *gl_format = GL_RED; *gl_type = GL_FLOAT; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32G32B32: *gl_internal_format = GL_RGB32F; *gl_format = GL_RGB; *gl_type = GL_FLOAT; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: *gl_internal_format = GL_RGBA32F; *gl_format = GL_RGBA; *gl_type = GL_FLOAT; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16: *gl_internal_format = GL_R16F; *gl_format = GL_RED; *gl_type = GL_HALF_FLOAT; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16G16B16: *gl_internal_format = GL_RGB16F; *gl_format = GL_RGB; *gl_type = GL_HALF_FLOAT; break;
- case RL_GPUTEX_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: *gl_internal_format = GL_RGBA16F; *gl_format = GL_RGBA; *gl_type = GL_HALF_FLOAT; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *gl_internal_format = GL_R8; *gl_format = GL_RED; *gl_type = GL_UNSIGNED_BYTE; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *gl_internal_format = GL_RG8; *gl_format = GL_RG; *gl_type = GL_UNSIGNED_BYTE; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G6B5: *gl_internal_format = GL_RGB565; *gl_format = GL_RGB; *gl_type = GL_UNSIGNED_SHORT_5_6_5; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8: *gl_internal_format = GL_RGB8; *gl_format = GL_RGB; *gl_type = GL_UNSIGNED_BYTE; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *gl_internal_format = GL_RGB5_A1; *gl_format = GL_RGBA; *gl_type = GL_UNSIGNED_SHORT_5_5_5_1; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *gl_internal_format = GL_RGBA4; *gl_format = GL_RGBA; *gl_type = GL_UNSIGNED_SHORT_4_4_4_4; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *gl_internal_format = GL_RGBA8; *gl_format = GL_RGBA; *gl_type = GL_UNSIGNED_BYTE; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32: *gl_internal_format = GL_R32F; *gl_format = GL_RED; *gl_type = GL_FLOAT; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32G32B32: *gl_internal_format = GL_RGB32F; *gl_format = GL_RGB; *gl_type = GL_FLOAT; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: *gl_internal_format = GL_RGBA32F; *gl_format = GL_RGBA; *gl_type = GL_FLOAT; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16: *gl_internal_format = GL_R16F; *gl_format = GL_RED; *gl_type = GL_HALF_FLOAT; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16G16B16: *gl_internal_format = GL_RGB16F; *gl_format = GL_RGB; *gl_type = GL_HALF_FLOAT; break;
+ case RLTEXGPU_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: *gl_internal_format = GL_RGBA16F; *gl_format = GL_RGBA; *gl_type = GL_HALF_FLOAT; break;
#endif
#if !defined(GRAPHICS_API_OPENGL_11)
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT1_RGB: *gl_internal_format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break;
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT1_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT3_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_DXT5_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC1_RGB: *gl_internal_format = GL_ETC1_RGB8_OES; break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC2_RGB: *gl_internal_format = GL_COMPRESSED_RGB8_ETC2; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA8_ETC2_EAC; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_PVRT_RGB: *gl_internal_format = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_PVRT_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
- case RL_GPUTEX_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA_ASTC_8x8_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT1_RGB: *gl_internal_format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break;
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT1_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT3_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_DXT5_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC1_RGB: *gl_internal_format = GL_ETC1_RGB8_OES; break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC2_RGB: *gl_internal_format = GL_COMPRESSED_RGB8_ETC2; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA8_ETC2_EAC; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_PVRT_RGB: *gl_internal_format = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_PVRT_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
+ case RLTEXGPU_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: *gl_internal_format = GL_COMPRESSED_RGBA_ASTC_8x8_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
#endif
- default: RL_GPUTEX_LOG("GPUTEX: Current format not supported (%i)", format); break;
+ default: RLTEXGPU_LOG("GPUTEX: Current format not supported (%i)", format); break;
}
*/
}
-#endif // RL_GPUTEX_IMPLEMENTATION
+#endif // RLTEXGPU_IMPLEMENTATION
/*
// OpenGL texture data formats
diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c
index 1975a7bfe..9b6881d40 100644
--- a/src/platforms/rcore_desktop_glfw.c
+++ b/src/platforms/rcore_desktop_glfw.c
@@ -1179,6 +1179,7 @@ void SwapScreenBuffer(void)
double GetTime(void)
{
double time = glfwGetTime(); // Elapsed time since glfwInit()
+
return time;
}
diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c
index 935b3fbb2..87ad7d7c4 100755
--- a/src/platforms/rcore_desktop_rgfw.c
+++ b/src/platforms/rcore_desktop_rgfw.c
@@ -174,7 +174,6 @@ extern "C" {
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct {
- double startTime;
RGFW_window *window; // Native display device (physical screen connection)
RGFW_monitor *monitor;
mg_gamepads minigamepad;
@@ -1096,7 +1095,7 @@ void HideCursor(void)
// Enables cursor (unlock cursor)
void EnableCursor(void)
{
- RGFW_window_captureMouse(platform.window, false);
+ RGFW_window_captureRawMouse(platform.window, false);
// Set cursor position in the middle
SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
@@ -1108,7 +1107,7 @@ void EnableCursor(void)
// Disables cursor (lock cursor)
void DisableCursor(void)
{
- RGFW_window_captureMouse(platform.window, true);
+ RGFW_window_captureRawMouse(platform.window, true);
HideCursor();
CORE.Input.Mouse.cursorLocked = true;
@@ -1127,7 +1126,9 @@ void SwapScreenBuffer(void)
// Get elapsed time measure in seconds since InitTimer()
double GetTime(void)
{
- return get_time_seconds() - platform.startTime;
+ double time = get_time_seconds() - CORE.Time.base;
+
+ return time;
}
// Open URL with default system browser (if available)
@@ -1331,7 +1332,7 @@ void PollInputEvents(void)
CORE.Window.currentFbo.width = CORE.Window.render.width;
CORE.Window.currentFbo.height = CORE.Window.render.height;
#elif defined(PLATFORM_WEB_RGFW)
- return;
+ // do nothing but prevent other behavior
#else
SetupViewport(platform.window->w, platform.window->h);
@@ -1628,7 +1629,7 @@ int InitPlatform(void)
RGFW_setGlobalHints_OpenGL(hints);
platform.window = RGFW_createWindow((CORE.Window.title != 0)? CORE.Window.title : " ", 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, flags | RGFW_windowOpenGL);
- platform.startTime = get_time_seconds();
+ CORE.Time.base = get_time_seconds();
#ifndef PLATFORM_WEB_RGFW
i32 screenSizeWidth;
diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c
index 9dbd0b873..92c1979b3 100644
--- a/src/platforms/rcore_desktop_sdl.c
+++ b/src/platforms/rcore_desktop_sdl.c
@@ -60,7 +60,7 @@
#include "SDL.h"
#endif
-#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
#if defined(GRAPHICS_API_OPENGL_ES2)
// It seems it does not need to be included to work
//#include "SDL_opengles2.h"
@@ -1259,7 +1259,7 @@ void DisableCursor(void)
// Swap back buffer with front buffer (screen drawing)
void SwapScreenBuffer(void)
{
-#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
// NOTE: Using a preprocessor condition here because rlCopyFramebuffer() is only declared for software rendering
SDL_Surface *surface = SDL_GetWindowSurface(platform.window);
rlCopyFramebuffer(0, 0, CORE.Window.render.width, CORE.Window.render.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, surface->pixels);
@@ -1276,8 +1276,8 @@ void SwapScreenBuffer(void)
// Get elapsed time measure in seconds
double GetTime(void)
{
- unsigned int ms = SDL_GetTicks(); // Elapsed time in milliseconds since SDL_Init()
- double time = (double)ms/1000;
+ double time = ((double)SDL_GetPerformanceCounter()/(double)SDL_GetPerformanceFrequency()) - CORE.Time.base;
+
return time;
}
@@ -1981,7 +1981,7 @@ int InitPlatform(void)
// NOTE: Some OpenGL context attributes must be set before window creation
- if (rlGetVersion() != RL_OPENGL_11_SOFTWARE)
+ if (rlGetVersion() != RL_OPENGL_SOFTWARE)
{
// Add the flag telling the window to use an OpenGL context
flags |= SDL_WINDOW_OPENGL;
@@ -2044,12 +2044,12 @@ int InitPlatform(void)
#endif
// Init OpenGL context
- if (rlGetVersion() != RL_OPENGL_11_SOFTWARE)
+ if (rlGetVersion() != RL_OPENGL_SOFTWARE)
{
platform.glContext = SDL_GL_CreateContext(platform.window);
}
- if ((platform.window != NULL) && ((rlGetVersion() == RL_OPENGL_11_SOFTWARE) || (platform.glContext != NULL)))
+ if ((platform.window != NULL) && ((rlGetVersion() == RL_OPENGL_SOFTWARE) || (platform.glContext != NULL)))
{
CORE.Window.ready = true;
@@ -2124,12 +2124,14 @@ int InitPlatform(void)
// Initialize timing system
//----------------------------------------------------------------------------
- // NOTE: No need to call InitTimer(), let SDL manage it internally
- CORE.Time.previous = GetTime(); // Get time as double
+ // Get base time from window initialization
+ CORE.Time.base = (double)SDL_GetPerformanceCounter()/(double)SDL_GetPerformanceFrequency();
#if defined(_WIN32) && SUPPORT_WINMM_HIGHRES_TIMER && !SUPPORT_BUSY_WAIT_LOOP
SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "1"); // SDL equivalent of timeBeginPeriod() and timeEndPeriod()
#endif
+
+ // NOTE: No need to call InitTimer(), let SDL manage it internally
//----------------------------------------------------------------------------
// Initialize storage system
@@ -2164,7 +2166,7 @@ static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode)
return mapScancodeToKey[sdlScancode];
}
- return KEY_NULL; // No equivalent key in Raylib
+ return KEY_NULL; // No equivalent key in raylib
}
// Get next codepoint in a byte sequence and bytes processed
diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c
index a56a7f090..afbbedffc 100644
--- a/src/platforms/rcore_desktop_win32.c
+++ b/src/platforms/rcore_desktop_win32.c
@@ -71,7 +71,7 @@
#include // Required for alloca()
-#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
#include
#endif
@@ -1218,7 +1218,7 @@ void SwapScreenBuffer(void)
{
if (!platform.hdc) abort();
-#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
// Update framebuffer
rlCopyFramebuffer(0, 0, CORE.Window.render.width, CORE.Window.render.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, platform.pixels);
@@ -1238,9 +1238,12 @@ void SwapScreenBuffer(void)
// Get elapsed time measure in seconds
double GetTime(void)
{
+ double time = 0.0;
LARGE_INTEGER now = { 0 };
QueryPerformanceCounter(&now);
- return (double)(now.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart;
+ time = (double)(now.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart;
+
+ return time;
}
// Open URL with default system browser (if available)
@@ -1600,7 +1603,7 @@ int InitPlatform(void)
// NOTE: Windows GDI object that represents a drawing surface
platform.hdc = GetDC(platform.hwnd);
- if (rlGetVersion() == RL_OPENGL_11_SOFTWARE) // Using software renderer
+ if (rlGetVersion() == RL_OPENGL_SOFTWARE) // Using software renderer
{
// Initialize software framebuffer
BITMAPINFO bmi = { 0 };
@@ -1646,12 +1649,12 @@ int InitPlatform(void)
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
- if (rlGetVersion() == RL_OPENGL_11_SOFTWARE) // Using software renderer
+ if (rlGetVersion() == RL_OPENGL_SOFTWARE) // Using software renderer
{
TRACELOG(LOG_INFO, "GL: OpenGL device information:");
- TRACELOG(LOG_INFO, " > Vendor: %s", "raylib");
- TRACELOG(LOG_INFO, " > Renderer: %s", "rlsw - OpenGL 1.1 Software Renderer");
- TRACELOG(LOG_INFO, " > Version: %s", "1.0");
+ TRACELOG(LOG_INFO, " > Vendor: %s", glGetString(GL_VENDOR));
+ TRACELOG(LOG_INFO, " > Renderer: %s", glGetString(GL_RENDERER));
+ TRACELOG(LOG_INFO, " > Version: %s", glGetString(GL_VERSION));
TRACELOG(LOG_INFO, " > GLSL: %s", "NOT SUPPORTED");
}
@@ -1716,7 +1719,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
case WM_DESTROY:
{
// Clean up for window destruction
- if (rlGetVersion() == RL_OPENGL_11_SOFTWARE) // Using software renderer
+ if (rlGetVersion() == RL_OPENGL_SOFTWARE) // Using software renderer
{
if (platform.hdcmem)
{
@@ -1867,7 +1870,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
// WARNING: Don't trust the docs, they say this message can not be obtained if not calling DefWindowProc()
// in response to WM_WINDOWPOSCHANGED but looks like when a window is created,
// this message can be obtained without getting WM_WINDOWPOSCHANGED
- HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight);
+ // WARNING: This call fails for Software-Renderer backend
+ //HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight);
} break;
//case WM_MOVE
case WM_WINDOWPOSCHANGED:
@@ -1932,7 +1936,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
} break;
case WM_PAINT:
{
- if (rlGetVersion() == RL_OPENGL_11_SOFTWARE) // Using software renderer
+ if (rlGetVersion() == RL_OPENGL_SOFTWARE) // Using software renderer
{
PAINTSTRUCT ps = { 0 };
HDC hdc = BeginPaint(hwnd, &ps);
diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c
index a32934aa9..faba8956a 100644
--- a/src/platforms/rcore_drm.c
+++ b/src/platforms/rcore_drm.c
@@ -65,7 +65,7 @@
#include // Direct Rendering Manager user-level library interface
#include // Direct Rendering Manager mode setting (KMS) interface
-#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
#include // Generic Buffer Management (native platform for EGL on DRM)
#include "EGL/egl.h" // Native platform windowing system interface
#include "EGL/eglext.h" // EGL extensions
@@ -111,7 +111,7 @@ typedef struct {
int modeIndex; // Index of the used mode of connector->modes
uint32_t prevFB; // Previous DRM framebufer (during frame swapping)
-#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
struct gbm_device *gbmDevice; // GBM device
struct gbm_surface *gbmSurface; // GBM surface
struct gbm_bo *prevBO; // Previous GBM buffer object (during frame swapping)
@@ -796,7 +796,7 @@ void SwapScreenBuffer()
// Swap back buffer with front buffer (screen drawing)
void SwapScreenBuffer(void)
{
-#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
// Hardware rendering buffer swap with EGL
eglSwapBuffers(platform.device, platform.surface);
@@ -1140,7 +1140,7 @@ int InitPlatform(void)
platform.crtc = NULL;
platform.prevFB = 0;
-#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
platform.gbmDevice = NULL;
platform.gbmSurface = NULL;
platform.prevBO = NULL;
@@ -1224,7 +1224,7 @@ int InitPlatform(void)
// WARNING: Accept CONNECTED, UNKNOWN and even those without encoder_id connectors for software mode
if (((con->connection == DRM_MODE_CONNECTED) || (con->connection == DRM_MODE_UNKNOWNCONNECTION)) && (con->count_modes > 0))
{
-#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
// For hardware rendering, an encoder_id is needed
if (con->encoder_id)
{
@@ -1256,7 +1256,7 @@ int InitPlatform(void)
return -1;
}
-#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
drmModeEncoder *enc = drmModeGetEncoder(platform.fd, platform.connector->encoder_id);
if (!enc)
{
@@ -1367,7 +1367,7 @@ int InitPlatform(void)
drmModeFreeResources(res);
res = NULL;
-#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
// Hardware rendering initialization with EGL
platform.gbmDevice = gbm_create_device(platform.fd);
if (!platform.gbmDevice)
@@ -1657,7 +1657,7 @@ void ClosePlatform(void)
platform.prevFB = 0;
}
-#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
if (platform.prevBO)
{
gbm_surface_release_buffer(platform.gbmSurface, platform.prevBO);
@@ -1697,7 +1697,7 @@ void ClosePlatform(void)
platform.fd = -1;
}
-#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
// Close surface, context and display
if (platform.device != EGL_NO_DISPLAY)
{
diff --git a/src/platforms/rcore_memory.c b/src/platforms/rcore_memory.c
index 322841439..1512e7bf4 100644
--- a/src/platforms/rcore_memory.c
+++ b/src/platforms/rcore_memory.c
@@ -486,9 +486,9 @@ void PollInputEvents(void)
int InitPlatform(void)
{
// Memory framebuffer can only work with software renderer
- if (rlGetVersion() != RL_OPENGL_11_SOFTWARE)
+ if (rlGetVersion() != RL_OPENGL_SOFTWARE)
{
- TRACELOG(LOG_WARNING, "DISPLAY: Memory platform requires software renderer (GRAPHICS_API_OPENGL_11_SOFTWARE)");
+ TRACELOG(LOG_WARNING, "DISPLAY: Memory platform requires software renderer (GRAPHICS_API_OPENGL_SOFTWARE)");
TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphics device");
return -1;
}
diff --git a/src/platforms/rcore_template.c b/src/platforms/rcore_template.c
index 40a1922e7..368dd3e77 100644
--- a/src/platforms/rcore_template.c
+++ b/src/platforms/rcore_template.c
@@ -341,7 +341,6 @@ void SwapScreenBuffer(void)
double GetTime(void)
{
double time = 0.0;
-
struct timespec ts = { 0 };
clock_gettime(CLOCK_MONOTONIC, &ts);
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c
index ae847d8c9..8835ecdcc 100644
--- a/src/platforms/rcore_web.c
+++ b/src/platforms/rcore_web.c
@@ -77,7 +77,7 @@ typedef struct {
char canvasId[64]; // Keep current canvas id where wasm app is running
// NOTE: Useful when trying to run multiple wasms in different canvases in same webpage
-#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
unsigned int *pixels; // Pointer to pixel data buffer (RGBA 32bit format)
#endif
} PlatformData;
@@ -949,7 +949,7 @@ void DisableCursor(void)
// Swap back buffer with front buffer (screen drawing)
void SwapScreenBuffer(void)
{
-#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
// Update framebuffer
rlCopyFramebuffer(0, 0, CORE.Window.render.width, CORE.Window.render.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, platform.pixels);
@@ -986,6 +986,7 @@ void SwapScreenBuffer(void)
double GetTime(void)
{
double time = glfwGetTime(); // Elapsed time since glfwInit()
+
return time;
}
@@ -1305,7 +1306,7 @@ int InitPlatform(void)
// Init fullscreen toggle required var:
platform.ourFullscreen = false;
-#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
// Avoid creating a WebGL canvas, avoid calling glfwCreateWindow()
emscripten_set_canvas_element_size(platform.canvasId, CORE.Window.screen.width, CORE.Window.screen.height);
EM_ASM({
diff --git a/src/platforms/rcore_web_emscripten.c b/src/platforms/rcore_web_emscripten.c
index df3234217..3b6064255 100644
--- a/src/platforms/rcore_web_emscripten.c
+++ b/src/platforms/rcore_web_emscripten.c
@@ -927,7 +927,7 @@ void DisableCursor(void)
// Swap back buffer with front buffer (screen drawing)
void SwapScreenBuffer(void)
{
-#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
// Update framebuffer
rlCopyFramebuffer(0, 0, CORE.Window.render.width, CORE.Window.render.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, platform.pixels);
@@ -962,14 +962,7 @@ void SwapScreenBuffer(void)
// Get elapsed time measure in seconds since InitTimer()
double GetTime(void)
{
- double time = 0.0;
- /*
- struct timespec ts = { 0 };
- clock_gettime(CLOCK_MONOTONIC, &ts);
- unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
- time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
- */
- time = emscripten_get_now()*1000.0;
+ double time = emscripten_get_now()*1000.0;
return time;
}
@@ -1195,7 +1188,7 @@ int InitPlatform(void)
if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT)) attribs.antialias = EM_TRUE;
// Check selection OpenGL version
- if (rlGetVersion() == RL_OPENGL_11_SOFTWARE)
+ if (rlGetVersion() == RL_OPENGL_SOFTWARE)
{
// Avoid creating a WebGL canvas, create 2d canvas for software rendering
emscripten_set_canvas_element_size(platform.canvasId, CORE.Window.screen.width, CORE.Window.screen.height);
diff --git a/src/raylib.h b/src/raylib.h
index a1391de19..2e849c917 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -7,6 +7,7 @@
* - Multiplatform: Windows, Linux, macOS, FreeBSD, Web, Android, Raspberry Pi, DRM native...
* - Written in plain C code (C99) in PascalCase/camelCase notation
* - Hardware accelerated with OpenGL (1.1, 2.1, 3.3, 4.3, ES2, ES3 - choose at compile)
+* - Software renderer optional, for systems with no GPU: [rlsw]
* - Custom OpenGL abstraction layer (usable as standalone module): [rlgl]
* - Multiple Fonts formats supported (TTF, OTF, FNT, BDF, Sprite fonts)
* - Many texture formats supportted, including compressed formats (DXT, ETC, ASTC)
@@ -39,7 +40,7 @@
* [rtextures] stb_image_write (Sean Barret) for image writing (BMP, TGA, PNG, JPG)
* [rtextures] stb_image_resize2 (Sean Barret) for image resizing algorithms
* [rtextures] stb_perlin (Sean Barret) for Perlin Noise image generation
-* [rtextures] rl_gputex (Ramon Santamaria) for GPU-compressed texture formats
+* [rtextures] rltexgpu (Ramon Santamaria) for GPU-compressed texture formats
* [rtext] stb_truetype (Sean Barret) for ttf fonts loading
* [rtext] stb_rect_pack (Sean Barret) for rectangles packing
* [rmodels] par_shapes (Philip Rideout) for parametric 3d shapes generation
diff --git a/src/rcore.c b/src/rcore.c
index de1bb371c..5cdc8aca1 100644
--- a/src/rcore.c
+++ b/src/rcore.c
@@ -682,6 +682,16 @@ void InitWindow(int width, int height, const char *title)
TRACELOG(LOG_WARNING, "SYSTEM: Failed to initialize platform");
return;
}
+
+ // Initialize render dimensions for embedded platforms
+ // NOTE: On desktop platforms (GLFW, SDL, etc.), CORE.Window.render.width/height are set during window creation
+ // On embedded platforms with no window manager, InitPlatform() doesn't set these values, so they should be initialized
+ // here from screen dimensions (which are set from the InitWindow parameters)
+ if ((CORE.Window.render.width == 0) || (CORE.Window.render.height == 0))
+ {
+ CORE.Window.render.width = CORE.Window.screen.width;
+ CORE.Window.render.height = CORE.Window.screen.height;
+ }
//--------------------------------------------------------------
// Initialize rlgl default data (buffers and shaders)
diff --git a/src/rlgl.h b/src/rlgl.h
index b40b50b43..13c037132 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -1,6 +1,6 @@
/**********************************************************************************************
*
-* rlgl v5.0 - A multi-OpenGL abstraction layer with an immediate-mode style API
+* rlgl v6.0 - A multi-OpenGL abstraction layer with an immediate-mode style API
*
* DESCRIPTION:
* An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0, ES 3.0)
@@ -21,7 +21,7 @@
* Internal buffer (and resources) must be manually unloaded calling rlglClose()
*
* CONFIGURATION:
-* #define GRAPHICS_API_OPENGL_11_SOFTWARE
+* #define GRAPHICS_API_OPENGL_SOFTWARE
* #define GRAPHICS_API_OPENGL_11
* #define GRAPHICS_API_OPENGL_21
* #define GRAPHICS_API_OPENGL_33
@@ -107,7 +107,7 @@
#ifndef RLGL_H
#define RLGL_H
-#define RLGL_VERSION "5.0"
+#define RLGL_VERSION "6.0"
// Function specifiers in case library is build/used as a shared library
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
@@ -145,7 +145,7 @@
#endif
// Security check in case no GRAPHICS_API_OPENGL_* defined
-#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE) && \
+#if !defined(GRAPHICS_API_OPENGL_SOFTWARE) && \
!defined(GRAPHICS_API_OPENGL_11) && \
!defined(GRAPHICS_API_OPENGL_21) && \
!defined(GRAPHICS_API_OPENGL_33) && \
@@ -156,7 +156,7 @@
#endif
// Security check in case multiple GRAPHICS_API_OPENGL_* defined
-#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_SOFTWARE)
#if defined(GRAPHICS_API_OPENGL_21)
#undef GRAPHICS_API_OPENGL_21
#endif
@@ -172,7 +172,7 @@
#endif
// Software implementation uses OpenGL 1.1 functionality
-#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
#define GRAPHICS_API_OPENGL_11
#endif
@@ -423,7 +423,7 @@ typedef struct rlRenderBatch {
// OpenGL version
typedef enum {
- RL_OPENGL_11_SOFTWARE = 0, // Software rendering
+ RL_OPENGL_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)
@@ -835,9 +835,10 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#endif
#if defined(GRAPHICS_API_OPENGL_11)
- #if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ #if defined(GRAPHICS_API_OPENGL_SOFTWARE)
#define RLSW_IMPLEMENTATION
#define SW_MALLOC(sz) RL_MALLOC(sz)
+ #define SW_CALLOC(n,sz) RL_CALLOC(n, 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
@@ -1857,7 +1858,7 @@ void rlDisableShader(void)
// Enable rendering to texture (fbo)
void rlEnableFramebuffer(unsigned int id)
{
-#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
+#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_SOFTWARE))
glBindFramebuffer(GL_FRAMEBUFFER, id);
#endif
}
@@ -1866,7 +1867,7 @@ void rlEnableFramebuffer(unsigned int id)
unsigned int rlGetActiveFramebuffer(void)
{
GLint fboId = 0;
-#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3))
+#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3) || defined(GRAPHICS_API_OPENGL_SOFTWARE))
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &fboId);
#endif
return fboId;
@@ -1875,7 +1876,7 @@ unsigned int rlGetActiveFramebuffer(void)
// Disable rendering to texture
void rlDisableFramebuffer(void)
{
-#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
+#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_SOFTWARE))
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
}
@@ -1891,7 +1892,7 @@ void rlBlitFramebuffer(int srcX, int srcY, int srcWidth, int srcHeight, int dstX
// Bind framebuffer object (fbo)
void rlBindFramebuffer(unsigned int target, unsigned int framebuffer)
{
-#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
+#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_SOFTWARE))
glBindFramebuffer(target, framebuffer);
#endif
}
@@ -2324,7 +2325,7 @@ void rlglInit(int width, int height)
RLGL.State.currentMatrix = &RLGL.State.modelview;
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
-#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
// Initialize software renderer backend
int result = swInit(width, height);
if (result == 0)
@@ -2386,7 +2387,7 @@ void rlglClose(void)
TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture unloaded successfully", RLGL.State.defaultTextureId);
#endif
-#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
swClose(); // Unload sofware renderer resources
#endif
isGpuReady = false;
@@ -2701,8 +2702,8 @@ int rlGetVersion(void)
{
int glVersion = 0;
-#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
- glVersion = RL_OPENGL_11_SOFTWARE;
+#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
+ glVersion = RL_OPENGL_SOFTWARE;
#elif defined(GRAPHICS_API_OPENGL_11)
glVersion = RL_OPENGL_11;
#endif
@@ -3471,6 +3472,13 @@ unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer)
TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Depth renderbuffer loaded successfully (%i bits)", id, (RLGL.ExtSupported.maxDepthBits >= 24)? RLGL.ExtSupported.maxDepthBits : 16);
}
+#elif defined(GRAPHICS_API_OPENGL_SOFTWARE)
+ // NOTE: Renderbuffers are the same type of object as textures in rlsw
+ // WARNING: Ensure that the depth format is the one specified at rlsw compilation
+ glGenRenderbuffers(1, &id);
+ glBindRenderbuffer(GL_RENDERBUFFER, id);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, width, height);
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
#endif
return id;
@@ -3768,18 +3776,18 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
// Copy framebuffer pixel data to internal buffer
void rlCopyFramebuffer(int x, int y, int width, int height, int format, void *pixels)
{
-#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
unsigned int glInternalFormat, glFormat, glType;
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); // Get OpenGL texture format
- swCopyFramebuffer(x, y, width, height, glFormat, glType, pixels);
+ swReadPixels(x, y, width, height, glFormat, glType, pixels);
#endif
}
// Resize internal framebuffer
void rlResizeFramebuffer(int width, int height)
{
-#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
- swResizeFramebuffer(width, height);
+#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
+ swResize(width, height);
#endif
}
@@ -3829,7 +3837,7 @@ unsigned int rlLoadFramebuffer(void)
unsigned int fboId = 0;
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return fboId; }
-#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
+#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_SOFTWARE))
glGenFramebuffers(1, &fboId); // Create the framebuffer object
glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind any framebuffer
#endif
@@ -3841,7 +3849,7 @@ unsigned int rlLoadFramebuffer(void)
// NOTE: Attach type: 0-Color, 1-Depth renderbuffer, 2-Depth texture
void rlFramebufferAttach(unsigned int id, unsigned int texId, int attachType, int texType, int mipLevel)
{
-#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
+#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_SOFTWARE))
glBindFramebuffer(GL_FRAMEBUFFER, id);
switch (attachType)
@@ -3881,7 +3889,7 @@ bool rlFramebufferComplete(unsigned int id)
{
bool result = false;
-#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
+#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_SOFTWARE))
glBindFramebuffer(GL_FRAMEBUFFER, id);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -3912,7 +3920,7 @@ bool rlFramebufferComplete(unsigned int id)
// NOTE: All attached textures/cubemaps/renderbuffers are also deleted
void rlUnloadFramebuffer(unsigned int id)
{
-#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
+#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_SOFTWARE))
// Query depth attachment to automatically delete texture/renderbuffer
int depthType = 0;
glBindFramebuffer(GL_FRAMEBUFFER, id); // Bind framebuffer to query depth texture type
diff --git a/src/rmodels.c b/src/rmodels.c
index 1c7a5452c..ba28eb839 100644
--- a/src/rmodels.c
+++ b/src/rmodels.c
@@ -1430,7 +1430,7 @@ void UpdateMeshBuffer(Mesh mesh, int index, const void *data, int dataSize, int
// Draw a 3d mesh with material and transform
void DrawMesh(Mesh mesh, Material material, Matrix transform)
{
-#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_SOFTWARE)
#define GL_VERTEX_ARRAY 0x8074
#define GL_NORMAL_ARRAY 0x8075
#define GL_COLOR_ARRAY 0x8076
diff --git a/src/rtextures.c b/src/rtextures.c
index cf19edd1e..45b615cf7 100644
--- a/src/rtextures.c
+++ b/src/rtextures.c
@@ -100,19 +100,19 @@
#endif
#if SUPPORT_FILEFORMAT_DDS
- #define RL_GPUTEX_SUPPORT_DDS
+ #define RLTEXGPU_SUPPORT_DDS
#endif
#if SUPPORT_FILEFORMAT_PKM
- #define RL_GPUTEX_SUPPORT_PKM
+ #define RLTEXGPU_SUPPORT_PKM
#endif
#if SUPPORT_FILEFORMAT_KTX
- #define RL_GPUTEX_SUPPORT_KTX
+ #define RLTEXGPU_SUPPORT_KTX
#endif
#if SUPPORT_FILEFORMAT_PVR
- #define RL_GPUTEX_SUPPORT_PVR
+ #define RLTEXGPU_SUPPORT_PVR
#endif
#if SUPPORT_FILEFORMAT_ASTC
- #define RL_GPUTEX_SUPPORT_ASTC
+ #define RLTEXGPU_SUPPORT_ASTC
#endif
// Image fileformats not supported by default
@@ -161,13 +161,13 @@
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
- #define RL_GPUTEX_MALLOC RL_MALLOC
- #define RL_GPUTEX_FREE RL_FREE
- #define RL_GPUTEX_LOG(...) TRACELOG(LOG_WARNING, "IMAGE: " __VA_ARGS__)
- #define RL_GPUTEX_SHOW_LOG_INFO
- #define RL_GPUTEX_IMPLEMENTATION
- #include "external/rl_gputex.h" // Required for: rl_load_xxx_from_memory()
- // NOTE: Used to read compressed textures data (multiple formats support)
+ #define RLTEXGPU_MALLOC RL_MALLOC
+ #define RLTEXGPU_FREE RL_FREE
+ #define RLTEXGPU_LOG(...) TRACELOG(LOG_WARNING, "IMAGE: " __VA_ARGS__)
+ #define RLTEXGPU_SHOW_LOG_INFO
+ #define RLTEXGPU_IMPLEMENTATION
+ #include "external/rltexgpu.h" // Required for: rl_load_xxx_from_memory()
+ // NOTE: Used to read compressed textures data (multiple formats support)
#if defined(__GNUC__) // GCC and Clang
#pragma GCC diagnostic pop
#endif
diff --git a/tools/rexm/Makefile b/tools/rexm/Makefile
index d7d71f64f..c8f2490c0 100644
--- a/tools/rexm/Makefile
+++ b/tools/rexm/Makefile
@@ -99,8 +99,8 @@ ifeq ($(PLATFORM_OS),WINDOWS)
EMSDK_PATH ?= C:/raylib/emsdk
EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten
CLANG_PATH = $(EMSDK_PATH)/upstream/bin
- PYTHON_PATH = $(EMSDK_PATH)/python/3.9.2-nuget_64bit
- NODE_PATH = $(EMSDK_PATH)/node/20.18.0_64bit/bin
+ PYTHON_PATH = $(EMSDK_PATH)/python/3.13.3_64bit
+ NODE_PATH = $(EMSDK_PATH)/node/22.16.0_64bit/bin
export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH):$$(PATH)
endif
endif
diff --git a/tools/rexm/reports/examples_validation.md b/tools/rexm/reports/examples_validation.md
index e46b93e46..3863ea38d 100644
--- a/tools/rexm/reports/examples_validation.md
+++ b/tools/rexm/reports/examples_validation.md
@@ -109,6 +109,8 @@ Example elements validated:
| shapes_penrose_tile | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_hilbert_curve | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_easings_testbed | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| textures_clipboard_image | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| textures_magnifying_glass | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| textures_logo_raylib | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| textures_srcrec_dstrec | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| textures_image_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@@ -184,7 +186,7 @@ Example elements validated:
| models_directional_billboard | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| models_animation_blend_custom | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| models_animation_blending | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
-| models_animation_timming | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| models_animation_timing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_ascii_rendering | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_basic_lighting | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_model_shader | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@@ -219,6 +221,7 @@ Example elements validated:
| shaders_depth_rendering | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_game_of_life | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_rlgl_compute | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| shaders_cel_shading | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| audio_module_playing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| audio_music_stream | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| audio_raw_stream | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@@ -228,3 +231,4 @@ Example elements validated:
| audio_sound_multi | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| audio_sound_positioning | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| audio_spectrum_visualizer | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| audio_stream_callback | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c
index c681530c9..49d4dce9a 100644
--- a/tools/rexm/rexm.c
+++ b/tools/rexm/rexm.c
@@ -1504,11 +1504,11 @@ int main(int argc, char *argv[])
//ChangeDirectory(exBasePath);
//_putenv("MAKE_PATH=C:\\raylib\\w64devkit\\bin");
//_putenv("EMSDK_PATH = C:\\raylib\\emsdk");
- //_putenv("PYTHON_PATH=$(EMSDK_PATH)\\python\\3.9.2-nuget_64bit");
- //_putenv("NODE_PATH=$(EMSDK_PATH)\\node\\20.18.0_64bit\\bin");
+ //_putenv("PYTHON_PATH=$(EMSDK_PATH)\\python\\3.13.3_64bit");
+ //_putenv("NODE_PATH=$(EMSDK_PATH)\\node\\22.16.0_64bit\\bin");
//_putenv("PATH=%PATH%;$(MAKE_PATH);$(EMSDK_PATH);$(NODE_PATH);$(PYTHON_PATH)");
- _putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin;C:\\raylib\\emsdk\\python\\3.9.2-nuget_64bit;C:\\raylib\\emsdk\\node\\20.18.0_64bit\\bin");
+ _putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin;C:\\raylib\\emsdk\\python\\3.13.3_64bit;C:\\raylib\\emsdk\\node\\22.16.0_64bit\\bin");
#endif
for (int i = 0; i < exBuildListCount; i++)