Skip to content

Instantly share code, notes, and snippets.

@rygo6
Created April 26, 2026 03:05
Show Gist options
  • Select an option

  • Save rygo6/bd1adddb932ec10518fca5bbebecaef7 to your computer and use it in GitHub Desktop.

Select an option

Save rygo6/bd1adddb932ec10518fca5bbebecaef7 to your computer and use it in GitHub Desktop.
raylib-claude-consistency-audit.md

raylib v6.0 Public API Consistency Audit

Audit of raylib.h public-facing API for naming, parameter, and methodology inconsistencies.


1. Parameter Type Mismatches (same concept, different types)

Circle radius: float vs int

  • DrawCircle(int centerX, int centerY, float radius, Color color) — radius is float
  • ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color) — radius is int

Line thickness: float vs int

  • DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color) — thick is float
  • ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color) — thick is int

Font size: int vs float

  • DrawText(..., int fontSize, ...) and ImageText(..., int fontSize, ...)int
  • DrawTextEx(..., float fontSize, ...) and ImageTextEx(..., float fontSize, ...)float
  • This is arguably deliberate (base=simple int, Ex=precise float), but it means the two versions produce subtly different results for the same fontSize value.

Brightness: int vs float, different ranges

  • ImageColorBrightness(Image *image, int brightness) — int, range -255 to 255
  • ColorBrightness(Color color, float factor) — float, range -1.0f to 1.0f

Contrast: same type but different ranges

  • ImageColorContrast(Image *image, float contrast) — range -100 to 100
  • ColorContrast(Color color, float contrast) — range -1.0f to 1.0f
  • Both are float, but a user would expect the same range for the same concept.

2. Naming Inconsistencies

DrawRectangleGradientV/DrawRectangleGradientH — V means "Vertical", not "Vector"

  • Everywhere else in the API, the V suffix means "Vector2 parameter version" (e.g., DrawCircleV, DrawLineV, DrawPixelV).
  • Here V means "vertical gradient" and H means "horizontal gradient". This is a naming collision.

DrawCircleGradient takes Vector2 directly, breaking the int/V pattern

  • DrawCircle(int centerX, int centerY, ...) — base uses ints
  • DrawCircleV(Vector2 center, ...) — V variant uses Vector2
  • DrawCircleGradient(Vector2 center, ...) — uses Vector2 directly with no int version and no V suffix. Should be either DrawCircleGradient(int centerX, int centerY, ...) or named DrawCircleGradientV.

SetShaderValueV — V means "vector/array count", not Vector2

  • SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count) — the V suffix here adds a count parameter for array uniforms, a third meaning of the V suffix.

DrawPoly comment says "(Vector version)" but there is no non-Vector version

  • DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color) — comment: "Draw a regular polygon (Vector version)". There's no DrawPoly that takes int centerX, int centerY.

GetSplinePointBezierQuad vs DrawSplineBezierQuadratic

  • The draw function uses Quadratic, the evaluate function uses Quad. Same spline type, different abbreviations.

DrawCylinder uses slices, DrawCylinderEx uses sides

  • DrawCylinder(Vector3 position, ..., int slices, Color color)
  • DrawCylinderEx(Vector3 startPos, Vector3 endPos, ..., int sides, Color color)
  • Same concept (circular subdivision count), different parameter names.

3D position parameter naming is inconsistent

  • DrawSphere(Vector3 centerPos, ...)centerPos
  • DrawCube(Vector3 position, ...)position
  • DrawPlane(Vector3 centerPos, ...)centerPos
  • DrawCylinder(Vector3 position, ...)position

Music functions have "Stream" in the name, Sound functions don't

  • PlaySound / StopSound / PauseSound / IsSoundPlaying
  • PlayMusicStream / StopMusicStream / PauseMusicStream / IsMusicStreamPlaying
  • PlayAudioStream / StopAudioStream / PauseAudioStream / IsAudioStreamPlaying
  • Music is its own type (not an AudioStream from the user's perspective), yet it carries the "Stream" suffix inconsistently. IsMusicValid drops "Stream" but IsMusicStreamPlaying keeps it.

color vs tint parameter naming

  • DrawText(..., Color color) but DrawTextEx(..., Color tint)
  • ImageDrawText(..., Color color) but ImageDrawTextEx(..., Color tint)
  • DrawTexture(..., Color tint) — always tint
  • The base text functions use color, the extended versions use tint.

3. Parameter Order Inconsistencies

DrawSphereEx vs DrawCapsule — rings/slices order is reversed

  • DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color)
  • DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color)
  • Both have rings and slices, but in opposite order.

4. Return Type / Const-correctness Issues

Set* functions are all void except one

  • SetGamepadMappings(const char *mappings) returns int. Every other Set* function in the API returns void.

File operation return types are mixed

  • FileExists(...) returns bool
  • FileRename(...) / FileRemove(...) / FileCopy(...) / FileMove(...) return int
  • MakeDirectory(...) returns int (0 on success)
  • ChangeDirectory(...) returns bool (true on success)
  • No consistent convention for success/failure indication.

Missing const on hash functions

  • CompressData(const unsigned char *data, ...) — correctly const
  • ComputeCRC32(unsigned char *data, ...) — missing const
  • ComputeMD5(unsigned char *data, ...) — missing const
  • ComputeSHA1(unsigned char *data, ...) — missing const
  • ComputeSHA256(unsigned char *data, ...) — missing const
  • These functions should not modify the input data.

Missing const on SaveFileData

  • SaveFileData(const char *fileName, void *data, int dataSize)data should be const void *, it's being read not written.

Missing const on GetPixelColor

  • GetPixelColor(void *srcPtr, int format) — srcPtr should be const void *.

5. Duplicate / Overlapping Functions

Fade and ColorAlpha do the same thing

  • Fade(Color color, float alpha) — "Get color with alpha applied"
  • ColorAlpha(Color color, float alpha) — "Get color with alpha applied"
  • Identical signatures, identical descriptions.

GetCodepoint and GetCodepointNext have identical descriptions

  • Both: "Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure"
  • The descriptions don't explain how they differ.

6. Structural / Pattern Inconsistencies

WindowShouldClose breaks the query naming pattern

  • All other boolean queries use Is* prefix: IsWindowReady, IsKeyPressed, IsFileDropped, etc.
  • WindowShouldClose is the notable exception.

GetScreenToWorldRay / GetWorldToScreen asymmetry with 2D

  • 3D: GetScreenToWorldRay, GetWorldToScreen — no "3D" suffix
  • 2D: GetWorldToScreen2D, GetScreenToWorld2D — has "2D" suffix
  • Asymmetric naming.

UpdateSound vs UpdateAudioStream — different unit semantics

  • UpdateSound(Sound sound, const void *data, int sampleCount) — uses sampleCount
  • UpdateAudioStream(AudioStream stream, const void *data, int frameCount) — uses frameCount
  • Samples and frames are different units (frame = samples * channels). Easy to misuse.

No ImageDrawRectangleLines with int parameters

  • ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color) — int version exists
  • ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color) — jumps straight to Rectangle, no int version
  • Unlike DrawRectangleLines(int posX, int posY, int width, int height, Color color) which has an int version.

7. Comment Phrasing and Wording Issues

Verb tense inconsistency — most comments use imperative ("Draw", "Check", "End"), but some use third-person ("Draws", "Checks", "Ends")

"End" vs "Ends":

  • EndDrawing → "End canvas drawing and swap buffers" (imperative)
  • EndMode2D → "Ends 2D mode with custom camera" (third-person)
  • EndMode3D → "Ends 3D mode and returns to default 2D orthographic mode" (third-person)
  • EndTextureMode → "Ends drawing to render texture" (third-person)
  • EndShaderMode → "End custom shader drawing" (imperative)
  • EndBlendMode → "End blending mode" (imperative)

"Check" vs "Checks":

  • All Is*Valid in the audio module use "Checks": IsWaveValid → "Checks if wave data is valid", IsSoundValid → "Checks if a sound is valid", IsMusicValid → "Checks if a music stream is valid", IsAudioStreamValid → "Checks if an audio stream is valid"
  • All other Is* functions use "Check": IsImageValid → "Check if an image is valid", IsTextureValid → "Check if a texture is valid", etc.

"Draw" vs "Draws":

  • DrawTextureNPatch → "Draws a texture (or part of it) that stretches or shrinks nicely" (third-person)
  • All other Draw functions use imperative: "Draw a Texture2D", "Draw a line", etc.

Cursor functions use third-person:

  • ShowCursor → "Shows cursor"
  • EnableCursor → "Enables cursor (unlock cursor)"
  • DisableCursor → "Disables cursor (lock cursor)"
  • But EnableEventWaiting → "Enable waiting for events..." (imperative)

"Updates" instead of "Update":

  • UpdateMusicStream → "Updates buffers for music streaming" (third-person)
  • UpdateAudioStream → "Update audio stream buffers with data" (imperative)

Typos and grammar errors

  • CheckCollisionCircleLine comment: "betweeen" — triple 'e' typo. Should be "between".
  • IsGestureDetected comment: "Check if a gesture have been detected" — should be "has been detected".
  • DrawTextCodepoints comment: "Draw multiple character (codepoint)" — should be "characters" (plural).
  • TextIsEqual comment: "Check if two text string are equal" — should be "strings" (plural).
  • LoadImageFromScreen comment: "Load image from screen buffer and (screenshot)" — dangling "and" with nothing after it.
  • SetMusicPitch comment: "Set pitch for a music" — grammatically wrong, should be "for music" or "for a music stream".
  • SetMusicPan comment: "Set pan for a music" — same issue.
  • GetWorldToScreenEx comment: "Get size position for a 3d world space position" — should be "Get screen space position".
  • SetConfigFlags comment: "Setup init configuration flags (view FLAGS)" — "Setup" should be "Set up" (verb form), and "view FLAGS" is vague.
  • ClearBackground comment: "Set background color (framebuffer clear color)" — describes a "Set" action but the function is named "Clear".

Inconsistent description formats for pan parameter

  • SetSoundPan: "Set pan for a sound (-1.0 left, 0.0 center, 1.0 right)"
  • SetMusicPan: "Set pan for a music (-1.0 left, 0.0 center, 1.0 right)"
  • SetAudioStreamPan: "Set pan for audio stream (-1.0 to 1.0 range, 0.0 is centered)"
  • Three different description styles for identical parameter semantics.

Inconsistent article usage

  • "Check if a key has been pressed once" (with article)
  • "Check if file exists" (no article)
  • "Unload sound" (no article) vs "Unload a sound alias" (with article)
  • No consistent rule for when to include articles.

DrawPoly comment is misleading

  • Comment says "(Vector version)" but there is no non-Vector DrawPoly that takes int centerX, int centerY. The comment implies a variant that doesn't exist.

DrawRectangleRoundedLinesEx vs DrawRectangleRoundedLines comment wording mismatch

  • DrawRectangleRoundedLines: "Draw rectangle lines with rounded edges"
  • DrawRectangleRoundedLinesEx: "Draw rectangle with rounded edges outline"
  • Different phrasing for the same concept hierarchy.

8. Consistency Plan

Priority 1: Bug-risk fixes (const-correctness, parameter types)

These are the most impactful because they can cause real bugs or API misuse.

  1. Add missing const qualifiers:

    • ComputeCRC32(unsigned char *data, ...)ComputeCRC32(const unsigned char *data, ...)
    • Same for ComputeMD5, ComputeSHA1, ComputeSHA256
    • SaveFileData(..., void *data, ...)SaveFileData(..., const void *data, ...)
    • GetPixelColor(void *srcPtr, ...)GetPixelColor(const void *srcPtr, ...)
  2. Unify ImageDraw* parameter types to match Draw* equivalents:

    • ImageDrawCircle/ImageDrawCircleV/ImageDrawCircleLines/ImageDrawCircleLinesV: change int radiusfloat radius to match DrawCircle
    • ImageDrawLineEx: change int thickfloat thick to match DrawLineEx
  3. Unify brightness/contrast ranges:

    • ImageColorBrightness: change to float in range -1.0f to 1.0f (matching ColorBrightness)
    • ImageColorContrast: change range to -1.0f to 1.0f (matching ColorContrast)
    • These are breaking changes, so they should be versioned or documented clearly.
  4. Fix DrawCapsule/DrawCapsuleWires parameter order:

    • Change from (... int slices, int rings, ...)(... int rings, int slices, ...) to match DrawSphereEx/DrawSphereWires
  5. Unify DrawCylinder/DrawCylinderEx subdivision parameter name:

    • DrawCylinderEx/DrawCylinderWiresEx: rename sidesslices to match DrawCylinder/DrawCylinderWires

Priority 2: Naming fixes (breaking but high-value)

These improve learnability and reduce confusion, but require deprecation cycles.

  1. Rename DrawRectangleGradientV / DrawRectangleGradientH:

    • DrawRectangleGradientVertical / DrawRectangleGradientHorizontal
    • This eliminates the V-suffix collision (V=Vector everywhere else).
    • Keep old names as #define aliases for backwards compatibility.
  2. Rename SetShaderValueV:

    • SetShaderValueArray or SetShaderValueCount
    • Eliminates the third meaning of the V suffix.
  3. Rename GetSplinePointBezierQuad:

    • GetSplinePointBezierQuadratic to match DrawSplineBezierQuadratic
  4. Standardize Music function naming:

    • Either drop "Stream" everywhere: PlayMusic, StopMusic, PauseMusic, IsMusicPlaying, LoadMusic, UnloadMusic
    • Or keep it everywhere: rename IsMusicValidIsMusicStreamValid, SetMusicVolumeSetMusicStreamVolume, etc.
    • Dropping "Stream" is cleaner since Music is already a distinct type.
  5. Deprecate Fade in favor of ColorAlpha:

    • Fade is the legacy name, ColorAlpha follows the Color* naming convention.
    • Keep Fade as a #define alias.
  6. Fix DrawCircleGradient to follow the int/V pattern:

    • Add DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer) as the base version.
    • Rename current function to DrawCircleGradientV.
  7. Standardize 3D position parameter names:

    • Pick one convention: position for all, since centerPos is redundant (the position is always the center for these shapes).

Priority 3: Comment fixes (non-breaking, easy wins)

These can all be done in a single pass without any API changes.

  1. Standardize verb tense to imperative (base form):

    • "Ends 2D mode" → "End 2D mode"
    • "Ends 3D mode" → "End 3D mode"
    • "Ends drawing to render texture" → "End drawing to render texture"
    • "Shows cursor" → "Show cursor"
    • "Enables cursor" → "Enable cursor"
    • "Disables cursor" → "Disable cursor"
    • "Checks if..." → "Check if..." (audio module Is*Valid functions)
    • "Draws a texture..." → "Draw a texture..."
    • "Updates buffers..." → "Update buffers..."
  2. Fix typos and grammar:

    • "betweeen" → "between" (CheckCollisionCircleLine)
    • "a gesture have been" → "a gesture has been" (IsGestureDetected)
    • "multiple character" → "multiple characters" (DrawTextCodepoints)
    • "two text string are" → "two text strings are" (TextIsEqual)
    • "screen buffer and (screenshot)" → "screen buffer (screenshot)" (LoadImageFromScreen)
    • "for a music" → "for music" (SetMusicPitch, SetMusicPan)
    • "Get size position" → "Get screen space position" (GetWorldToScreenEx)
    • "Setup init configuration flags (view FLAGS)" → "Set up initial configuration flags" (SetConfigFlags)
  3. Fix misleading comments:

    • ClearBackground: "Set background color" → "Clear background with given color"
    • DrawPoly: Remove "(Vector version)" since no int version exists. → "Draw a regular polygon"
    • GetCodepoint: Differentiate from GetCodepointNext — "Get next codepoint in a UTF-8 encoded string (equivalent to GetCodepointNext)" or clarify that it's a legacy alias.
    • DrawRectangleRoundedLinesEx: "Draw rectangle with rounded edges outline" → "Draw rectangle outline with rounded edges and line thickness"
  4. Standardize pan descriptions:

    • Use a single format everywhere: "Set pan for a sound (-1.0 left, 0.0 center, 1.0 right)"
    • Apply to SetMusicPan and SetAudioStreamPan as well.
  5. Standardize article usage:

    • Adopt one rule: use articles for countable nouns ("Unload a sound", "Check if a file exists"), omit for mass/abstract nouns.

Priority 4: Structural additions (non-breaking, additive)

  1. Add missing colortint consistency:

    • The tint naming is more accurate (color is multiplied with texture/font color).
    • Update DrawText and ImageDrawText parameter names from colortint to match their Ex variants.
  2. Add suffix to 3D screen-space functions for symmetry:

    • Add aliases: GetScreenToWorldRay3D = GetScreenToWorldRay, GetWorldToScreen3D = GetWorldToScreen
    • This makes the 2D/3D naming symmetric.
  3. Unify UpdateSound / UpdateAudioStream unit naming:

    • Both should use frameCount (the standard audio term). sampleCount in UpdateSound is misleading.
    • Or both should clearly document what unit is expected.

9. Modality Gap Analysis

This section identifies families of functions that define a pattern (Base, V, Ex, Lines, Wires, Pro, Rec, etc.) and then finds other functions of the same nature that are missing variants to complete the pattern.

9.1 2D Shape Drawing Modalities

Legend: Base = int params, V = Vector2 params, Lines = outline (int), LinesV = outline (Vector2), LinesEx = outline with thickness, Ex = extended, Pro = origin+rotation, Rec = Rectangle params, Gradient = gradient fill

Shape Base V Lines LinesV LinesEx Ex Pro Rec Gradient
Pixel YES YES - - - - - - -
Line YES YES - - - YES - - -
Circle YES YES YES YES - - - - YES(V only)
Ellipse YES YES YES YES - - - - -
Ring - YES - YES - - - - -
Rectangle YES YES YES - YES(Rec) - YES YES YES
Triangle - YES - YES - - - - -
Poly - YES - YES YES - - - -

Gaps to fill:

  1. DrawCircleLinesEx(Vector2 center, float radius, float lineThick, Color color)

    • Circle has Base/V/Lines/LinesV but no LinesEx with thickness.
    • Rectangle has DrawRectangleLinesEx with thickness — circle should too.
  2. DrawEllipseLinesEx(int centerX, int centerY, float radiusH, float radiusV, float lineThick, Color color) and V variant

    • Ellipse has Lines/LinesV but no thickness variant.
    • Follows the same pattern gap as Circle.
  3. DrawCircleGradient int-param version

    • DrawCircleGradient currently takes Vector2 center directly, breaking the Base/V pattern.
    • Missing: DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer) as the int-based version.
    • Current function should be renamed DrawCircleGradientV or the int version should be added.
  4. DrawEllipseGradient(int centerX, int centerY, float radiusH, float radiusV, Color inner, Color outer) and V variant

    • Circle has a gradient fill, ellipse does not. Ellipse is a generalization of circle — this is a natural gap.
  5. DrawRectangleLinesV(Vector2 position, Vector2 size, Color color)

    • Rectangle has Base/V pair and Lines, but no LinesV.
    • Every other shape with both Base/V and Lines also has LinesV (Circle, Ellipse).
  6. DrawTriangleEx(Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3)

    • ImageDrawTriangleEx exists (per-vertex colors), but the GPU DrawTriangleEx does not.
    • The Image version defines a modality that the GPU version doesn't match.
  7. DrawRingLinesEx(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, float lineThick, Color color)

    • Ring has Base and Lines but no LinesEx with thickness.

9.2 3D Shape Drawing Modalities

Legend: Base = simple params, V = Vector3 size, Ex = two-point/extended, Wires = outline, WiresV = outline with Vector3 size, WiresEx = outline extended

Shape Base V Ex Wires WiresV WiresEx
Cube YES YES - YES YES -
Sphere YES - YES YES* - -
Cylinder YES - YES YES - YES
Capsule YES* - - YES* - -
Model YES - YES YES - YES

*Sphere DrawSphereWires requires rings/slices (like Ex), there is no simple wires version matching DrawSphere. *Capsule always requires all subdivision params — no simple version exists.

Gaps to fill:

  1. DrawSphereWiresSimple(Vector3 centerPos, float radius, Color color) (or just a default-param version)

    • DrawSphere(pos, radius, color) exists as a simple version (uses default rings/slices internally).
    • DrawSphereWires(pos, radius, rings, slices, color) always requires subdivision params.
    • The pattern set by Cube: DrawCube/DrawCubeWires are symmetric (both simple). Sphere breaks this.
  2. DrawCapsuleSimple(Vector3 startPos, Vector3 endPos, float radius, Color color) (or without subdivision params)

    • Capsule has no simple version. Both DrawCapsule and DrawCapsuleWires require slices and rings.
    • DrawSphere provides a simple version with default subdivisions — Capsule should too.
  3. DrawTriangleLines3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color)

    • DrawTriangle3D exists (filled) but no wireframe version.
    • In 2D, DrawTriangle/DrawTriangleLines is a complete pair.
    • DrawTriangleStrip3D exists but there's no DrawTriangleStripLines3D either.
  4. 3D primitives (Line3D, Point3D, Circle3D) lack Ex/variant coverage

    • DrawLine3D has no thickness variant (unlike 2D DrawLineEx).
    • DrawCircle3D has no filled version — it only draws the outline. In 2D, DrawCircle is filled and DrawCircleLines is outline. In 3D the only variant is outline-like.

9.3 ImageDraw vs Draw Parity

Functions that exist in Draw* (GPU rendering) but are missing from ImageDraw* (CPU software rendering):

Draw* function ImageDraw* equivalent Status
DrawCircleGradient ImageDrawCircleGradient MISSING
DrawCircleSector ImageDrawCircleSector MISSING
DrawCircleSectorLines ImageDrawCircleSectorLines MISSING
DrawEllipse ImageDrawEllipse MISSING
DrawEllipseV ImageDrawEllipseV MISSING
DrawEllipseLines ImageDrawEllipseLines MISSING
DrawEllipseLinesV ImageDrawEllipseLinesV MISSING
DrawRing ImageDrawRing MISSING
DrawRingLines ImageDrawRingLines MISSING
DrawRectanglePro ImageDrawRectanglePro MISSING
DrawRectangleGradientV ImageDrawRectangleGradientV MISSING
DrawRectangleGradientH ImageDrawRectangleGradientH MISSING
DrawRectangleGradientEx ImageDrawRectangleGradientEx MISSING
DrawRectangleRounded ImageDrawRectangleRounded MISSING
DrawRectangleRoundedLines ImageDrawRectangleRoundedLines MISSING
DrawPoly ImageDrawPoly MISSING
DrawPolyLines ImageDrawPolyLines MISSING
DrawLineStrip ImageDrawLineStrip MISSING
DrawLineBezier ImageDrawLineBezier MISSING
DrawLineDashed ImageDrawLineDashed MISSING
DrawTextPro ImageDrawTextPro MISSING

And one reverse gap — exists in ImageDraw but not Draw:

ImageDraw* function Draw* equivalent Status
ImageDrawTriangleEx (per-vertex colors) DrawTriangleEx MISSING

9.4 Load/Unload/IsValid/Export Lifecycle

Resource Load FromMemory IsValid Unload Export AsCode ToMemory
Image YES YES YES YES YES YES YES
Texture YES - YES YES - - -
RenderTexture YES - YES YES - - -
Font YES YES YES YES - YES -
Shader YES YES YES YES - - -
Model YES - YES YES - - -
Mesh Gen* - - YES YES YES -
Material YES - YES YES - - -
Wave YES YES YES YES YES YES -
Sound YES - YES YES - - -
Music YES YES YES YES - - -
AudioStream YES - YES YES - - -

Gaps to fill:

  1. IsMeshValid(Mesh mesh)

    • Every other resource type has an Is*Valid function. Mesh is the only one missing it.
  2. LoadTextureFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)

    • Image has LoadImageFromMemory. To load a texture from memory, you must go LoadImageFromMemoryLoadTextureFromImageUnloadImage (3 steps).
    • A convenience function would match the pattern.
  3. LoadModelFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)

    • Image, Wave, Font, Music, and Shader all have *FromMemory variants. Model does not.
  4. LoadSoundFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)

    • Wave has LoadWaveFromMemory. To load a Sound from memory requires LoadWaveFromMemoryLoadSoundFromWaveUnloadWave.
  5. ExportFont(Font font, const char *fileName)

    • Image, Mesh, and Wave all have both Export and ExportAsCode. Font only has ExportFontAsCode.
  6. ExportModel(Model model, const char *fileName)

    • Model has no export at all. ExportMesh exists but only exports individual meshes, not the full model with materials and skeleton.

9.5 Audio Playback Modality

Feature Sound Music AudioStream
Play PlaySound PlayMusicStream PlayAudioStream
Stop StopSound StopMusicStream StopAudioStream
Pause PauseSound PauseMusicStream PauseAudioStream
Resume ResumeSound ResumeMusicStream ResumeAudioStream
IsPlaying IsSoundPlaying IsMusicStreamPlaying IsAudioStreamPlaying
SetVolume SetSoundVolume SetMusicVolume SetAudioStreamVolume
SetPitch SetSoundPitch SetMusicPitch SetAudioStreamPitch
SetPan SetSoundPan SetMusicPan SetAudioStreamPan
Update UpdateSound UpdateMusicStream UpdateAudioStream
Seek - SeekMusicStream -
GetTimeLength - GetMusicTimeLength -
GetTimePlayed - GetMusicTimePlayed -

Gaps to fill:

  1. GetSoundTimeLength(Sound sound)

    • Music has GetMusicTimeLength. Sound has frameCount in the struct but no API to query duration in seconds.
  2. GetSoundTimePlayed(Sound sound)

    • Music has GetMusicTimePlayed. No equivalent for Sound.
  3. SeekSound(Sound sound, float position)

    • Music has SeekMusicStream. Sound has no seek capability.
    • (May be less useful for short sounds, but the modality gap exists.)

9.6 Summary of Highest-Impact Modality Gaps

The following are the gaps most likely to trip up users who learn one part of the API and expect the pattern to hold elsewhere:

Priority Gap Rationale
High IsMeshValid missing Every other resource has it
High DrawSphereWires has no simple form DrawSphere has one; Cube pair is symmetric
High DrawCircleGradient skips int base form Breaks Base/V convention
High ImageDrawCircle uses int radius vs DrawCircle float radius Type mismatch across parallel APIs
High DrawTriangleEx (per-vertex colors) missing from GPU Exists in ImageDraw but not Draw
Medium DrawRectangleLinesV missing Circle/Ellipse have LinesV, Rectangle doesn't
Medium DrawCircleLinesEx (thickness) missing Rectangle has LinesEx, Circle doesn't
Medium DrawTriangleLines3D missing 2D has the pair, 3D doesn't
Medium No ImageDrawEllipse* functions Ellipse exists in Draw but not ImageDraw
Medium LoadTextureFromMemory missing Shortcut for common Image→Texture pipeline
Low GetSoundTimeLength/GetSoundTimePlayed missing Music has them, Sound doesn't
Low ExportFont/ExportModel missing Other resources have Export
Low ImageDrawPoly/ImageDrawRing missing GPU Draw has them, ImageDraw doesn't

10. Implementation Confidence Analysis for Gap Fills

This section tags each gap from Section 9 with an implementation-confidence rating after reading the actual .c implementations. The goal is to isolate gaps that can be filled mechanically (no design decisions required) from those that need API-design input.

10.1 Verification Notes

All Section 1–7 claims were verified against src/rshapes.c, src/rtextures.c, src/rmodels.c, src/raudio.c, src/rcore.c, and src/raylib.h. Additional findings surfaced during verification:

  • Header/impl parameter-name mismatch: raylib.h declares DrawCylinder(..., int slices, ...) and DrawCylinderWires(..., int slices, ...), but rmodels.c:577 and rmodels.c:695 define them with int sides. C allows this (names aren't part of the linkage), but it's an additional source of confusion and an implementation-file fix in its own right.
  • IsRenderTextureValid confirmed present (raylib.h:1447) — not actually a gap.
  • ImageDrawTriangleFan and ImageDrawTriangleStrip confirmed present (raylib.h:1433–1434).
  • DrawSphere implementation (rmodels.c:433) is a one-liner: DrawSphereEx(centerPos, radius, 16, 16, color). This confirms the "default rings/slices" pattern used for auto-filling the sphere-wires simple-form gap.
  • Sound struct (raylib.h:487) embeds AudioStream stream + unsigned int frameCount — identical layout to Music for duration purposes, making GetSoundTimeLength a one-liner.
  • LoadSoundFromWave (raudio.c:944) is a simple composition from Wave → AudioBuffer → Sound, making LoadSoundFromMemory a 3-line wrapper.
  • LoadTextureFromImage (rtextures.c:4126) + LoadImageFromMemory (rtextures.c:411) means LoadTextureFromMemory is also a trivial composition.
  • IsMeshValid pattern derivable from IsModelValid (rmodels.c:1171): check vertices != NULL, vertexCount > 0, vaoId != 0 (and optionally that each set vbo pointer has a matching non-zero VBO slot).

10.2 High-Confidence Implementations (ready to auto-implement)

These gaps have a single obvious implementation derivable directly from existing code. No API-design decisions required. All are additive (new function names), so no breaking changes.

H1 — IsMeshValid(Mesh mesh)rmodels.c, declared in raylib.h near line 1607

bool IsMeshValid(Mesh mesh)
{
    bool result = false;
    if ((mesh.vertices != NULL) &&
        (mesh.vertexCount > 0) &&
        (mesh.vaoId > 0)) result = true;
    // Mirror IsModelValid's per-attribute VBO check
    if (result)
    {
        if ((mesh.vertices != NULL)  && (mesh.vboId[0] == 0)) result = false;
        if ((mesh.texcoords != NULL) && (mesh.vboId[1] == 0)) result = false;
        if ((mesh.normals != NULL)   && (mesh.vboId[2] == 0)) result = false;
        if ((mesh.colors != NULL)    && (mesh.vboId[3] == 0)) result = false;
        if ((mesh.tangents != NULL)  && (mesh.vboId[4] == 0)) result = false;
        if ((mesh.texcoords2 != NULL)&& (mesh.vboId[5] == 0)) result = false;
        if ((mesh.indices != NULL)   && (mesh.vboId[6] == 0)) result = false;
    }
    return result;
}

Pattern is lifted verbatim from IsModelValid (rmodels.c:1171–1200).

H2 — GetSoundTimeLength(Sound sound)raudio.c, declared near raylib.h:1689

float GetSoundTimeLength(Sound sound)
{
    if (sound.stream.sampleRate == 0) return 0.0f;
    return (float)sound.frameCount/sound.stream.sampleRate;
}

Identical formula to GetMusicTimeLength (raudio.c:2076–2083).

H3 — LoadSoundFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)raudio.c

Sound LoadSoundFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)
{
    Wave wave = LoadWaveFromMemory(fileType, fileData, dataSize);
    Sound sound = LoadSoundFromWave(wave);
    UnloadWave(wave);
    return sound;
}

Mirrors the documented 3-step workflow the audit calls out as a gap.

H4 — LoadTextureFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)rtextures.c

Texture2D LoadTextureFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)
{
    Image image = LoadImageFromMemory(fileType, fileData, dataSize);
    Texture2D texture = LoadTextureFromImage(image);
    UnloadImage(image);
    return texture;
}

Same composition pattern.

H5 — DrawTriangleLines3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color)rmodels.c

void DrawTriangleLines3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color)
{
    rlBegin(RL_LINES);
        rlColor4ub(color.r, color.g, color.b, color.a);
        rlVertex3f(v1.x, v1.y, v1.z); rlVertex3f(v2.x, v2.y, v2.z);
        rlVertex3f(v2.x, v2.y, v2.z); rlVertex3f(v3.x, v3.y, v3.z);
        rlVertex3f(v3.x, v3.y, v3.z); rlVertex3f(v1.x, v1.y, v1.z);
    rlEnd();
}

Direct analogue of DrawLine3D (rmodels.c:189) composed three times. No design questions.

H6 — DrawCircleLinesEx(Vector2 center, float radius, float lineThick, Color color)rshapes.c

Implementable as a ring with full sweep:

void DrawCircleLinesEx(Vector2 center, float radius, float lineThick, Color color)
{
    if (lineThick < 0.0f) lineThick = 0.0f;
    float inner = radius - lineThick*0.5f;
    float outer = radius + lineThick*0.5f;
    if (inner < 0.0f) inner = 0.0f;
    DrawRing(center, inner, outer, 0.0f, 360.0f, 36, color);
}

Uses 36 segments to match DrawCircleVDrawCircleSector(..., 36, ...) (rshapes.c:324). Matches DrawRectangleLinesEx modality (thickness-aware outline).

H7 — ImageDrawLineStrip(Image *dst, const Vector2 *points, int pointCount, Color color)rtextures.c

void ImageDrawLineStrip(Image *dst, const Vector2 *points, int pointCount, Color color)
{
    for (int i = 0; i < pointCount - 1; i++)
        ImageDrawLineV(dst, points[i], points[i + 1], color);
}

Matches GPU DrawLineStrip (rshapes.c). One-liner composition.

H8 — ImageDrawRectanglePro(Image *dst, Rectangle rec, Vector2 origin, float rotation, Color color)rtextures.c

Already has ImageDrawTriangle available — compute the 4 rotated corners (identical math to DrawRectanglePro at rshapes.c:738–772), then call ImageDrawTriangle twice to fill the quad. High confidence — the corner math is already written and can be copied verbatim.

H9 — Make Sound variant of SetSoundPan description canonical

Not strictly a gap but a one-line comment fix that's part of gap analysis's audio modality: standardize SetMusicPan / SetAudioStreamPan comment formats to match SetSoundPan.

10.3 Medium-Confidence Implementations (need a design micro-decision)

These have a clear implementation path but require one small API-design choice (e.g., parameter order, default values, naming when the obvious slot is taken).

M1 — DrawCircleGradient int-param version

Blocker: the obvious name is already taken by the Vector2 version. Options:

  • (a) Add DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer) and rename the existing one to DrawCircleGradientV. Breaking change; needs deprecation shim.
  • (b) Add only DrawCircleGradientV as an alias and leave the wrong name in place. Preserves compat but keeps the wart.
  • Decision needed from the maintainer; the implementation itself is one line either way.

M2 — DrawRectangleLinesV(Vector2 position, Vector2 size, Color color)

Blocker: existing DrawRectangleLines takes ints. A float-accurate V variant needs to either (a) delegate to DrawRectangleLinesEx({x,y,w,h}, 1.0f, color) (introduces 1px default thickness — subtle semantic shift from int version) or (b) replicate the RL_LINES code from DrawRectangleLines (rshapes.c:870–883) with float vertices. Implementation is obvious; the pick is stylistic.

M3 — DrawRingLinesEx with thickness

Geometry: two ring outlines at inner and outer of a nominal ring, plus radial line caps. Math is a straightforward extension of DrawRing (rshapes.c:553) but there are ambiguity questions (cap style — straight or rounded?). Medium confidence — needs a style pick.

M4 — ImageDrawCircleGradient

CPU-side radial gradient. Implementable by iterating a bounding box, computing per-pixel distance, and lerping colors. Medium confidence — need to pick color-space (sRGB linear vs gamma).

M5 — ImageDrawEllipse / ImageDrawEllipseV / ImageDrawEllipseLines / ImageDrawEllipseLinesV

Port DrawEllipse (rshapes.c:514) to CPU. The outline version can use a midpoint-ellipse algorithm; the fill version can scan-line. Math is textbook; just takes more code than the simpler gaps.

M6 — ImageDrawRing / ImageDrawRingLines

Annulus fill: iterate bounding box of outer circle, write pixel if innerRadius² ≤ dx²+dy² ≤ outerRadius². Same approach for sector angles. Medium confidence.

M7 — ImageDrawPoly / ImageDrawPolyLines

Regular polygon fill. Can be expressed as fan of ImageDrawTriangle calls from center; outline is a loop of ImageDrawLineV. Medium confidence.

M8 — ImageDrawRectangleGradientV / H / Ex

Per-pixel interpolation between color corners. Straightforward but pick a color-interpolation space (match GPU version — GPU is linear sRGB in fragment blend; CPU should mirror).

M9 — DrawTriangleEx (GPU per-vertex colors)

3-vertex draw with rlColor4ub per vertex (see DrawTriangle3D rmodels.c:232 for the pattern — just one color there). Implementation is 6 lines; "Ex" is shorthand for per-vertex color, no design debate.

void DrawTriangleEx(Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3)
{
    rlBegin(RL_TRIANGLES);
        rlColor4ub(c1.r,c1.g,c1.b,c1.a); rlVertex2f(v1.x, v1.y);
        rlColor4ub(c2.r,c2.g,c2.b,c2.a); rlVertex2f(v2.x, v2.y);
        rlColor4ub(c3.r,c3.g,c3.b,c3.a); rlVertex2f(v3.x, v3.y);
    rlEnd();
}

Actually classify this as High-confidence (H10) — listed here only because the suffix "Ex" currently has a variety of meanings across the API, so the maintainer may prefer a different name (DrawTriangleColors, etc.).

10.4 Low-Confidence / Non-Trivial Gaps (need maintainer input)

Do not auto-implement these — they require design decisions or backend plumbing.

Gap Blocker
DrawSphereWires simple-form Adding a new function with no rings/slices requires picking a name (collides with existing). Same issue for DrawCapsuleSimple. C has no overloading.
GetSoundTimePlayed(Sound) Sound does not track playback cursor itself — would need to query the underlying ma_decoder/AudioBuffer via miniaudio internals. Backend-specific.
SeekSound(Sound, float) Same backend issue as above; Sound is decoded in full at load time, so seeking is writing into the ma_data_source directly.
ExportFont(Font, fileName) Requires choosing a file format. FNT (re-encoding glyphs) and BMFont are candidates. Raylib's glyph rasterization is one-way (TTF → Font); round-tripping needs new serialization code.
ExportModel(Model, fileName) Requires a target format (OBJ loses skeleton, glTF is heavy). Raylib bundles cgltf but only in read mode.
LoadModelFromMemory Model loaders in raylib (OBJ/IQM/glTF/VOX/M3D) consume file paths for embedded texture resolution. Memory loading needs a virtual-path or callback shim.
ExportFontAsCode already exists, but ExportFont (data) does not Same as ExportFont above.
DrawEllipseGradient Needs a choice: radial along ellipse geometry, or linear? No existing precedent.
DrawLineDashed/DrawLineBezier ImageDraw variants CPU rasterization; doable but moderate effort and needs pixel-level sub-stepping decisions.
DrawTextPro ImageDraw variant Requires rotated text rasterization at pixel level — significant new code.
Header/impl slices vs sides mismatch for DrawCylinder* Fix is trivial (rename in .c to match .h), but maintainers may prefer the other direction since sides is arguably more correct for a polygon-count term. Needs a call.

10.5 Summary Recommendation

Safe to auto-implement now (9 items): H1 IsMeshValid, H2 GetSoundTimeLength, H3 LoadSoundFromMemory, H4 LoadTextureFromMemory, H5 DrawTriangleLines3D, H6 DrawCircleLinesEx, H7 ImageDrawLineStrip, H8 ImageDrawRectanglePro, H10 (=M9) DrawTriangleEx.

Each of these is a pure addition that follows an already-established pattern in the code, compiles as a tight wrapper or copy of adjacent logic, and doesn't require the maintainer to weigh in on naming or semantics. All others should wait for a design pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment