4 Commits

Author SHA1 Message Date
9b2efc4552 [rtextures] Fix ImageDrawCircle asymmetry (#6118)
ImageDrawCircle filled 2*radius pixels wide but 2*radius + 1 tall. Each
horizontal span started at centerX - x with width 2*x, which covers
centerX - x through centerX + x - 1, leaving the column at centerX + x
unwritten. The result was one column short on the right, off-centre, and
inconsistent with ImageDrawCircleLines, which is 2*radius + 1 in both
directions.

Widen the four spans by one pixel so the fill is (2r+1) x (2r+1), centred
on (centerX, centerY) and aligned with ImageDrawCircleLines.

Fixes #6117
2026-09-02 12:31:04 +02:00
5a433a51a3 [rTextures] Add LoadRenderTextureEx with user defined format (#6114)
* Add LoadRenderTextureEx that defines the FBO pixel format

* rlparser: update raylib_api.* by CI

* requested review

* rlparser: update raylib_api.* by CI

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-02 09:42:56 +02:00
237c1f85dd [rtextures] Fix GetPixelColor() reading the wrong bits for R5G5B5A1 blue (#6113)
R5G5B5A1 packs blue in bits 5..1 and alpha in bit 0, which is what
SetPixelColor(), ImageFormat(), LoadImageColors() and GetImageColor()
all do. GetPixelColor() masked bits 4..0 instead, so the decoded blue
was the low four bits of blue shifted up with the alpha bit pulled in
as its LSB.

Packing r == g == b and decoding it back gave (164, 164, 74) for
r=g=b=20; 31 of the 32 possible grey values decoded with unequal
channels. ImageDrawImage() blends through GetPixelColor(), so drawing
onto an R5G5B5A1 image was affected too.

Co-authored-by: Dylan Pulver <dylanpulver@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-09-02 09:42:19 +02:00
656d42c4da Support rlGetActiveFramebuffer() on OpenGL ES 2.0. (#6115)
Alias GL_DRAW_FRAMEBUFFER_BINDING to GL_FRAMEBUFFER_BINDING for ES 2.0,
alongside the existing GL_READ_FRAMEBUFFER/GL_DRAW_FRAMEBUFFER aliases, and
widen the guard to ES 2.0. The guard now matches rlEnableFramebuffer() and
rlDisableFramebuffer().
2026-09-02 09:36:59 +02:00
8 changed files with 305 additions and 242 deletions

View File

@ -1461,6 +1461,7 @@ RLAPI Texture2D LoadTexture(const char *fileName);
RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data
RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported
RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer) RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer)
RLAPI RenderTexture2D LoadRenderTextureEx(int width, int height, int format); // Load texture for rendering (framebuffer), with specific format
RLAPI bool IsTextureValid(Texture2D texture); // Check if texture is valid (loaded in GPU) RLAPI bool IsTextureValid(Texture2D texture); // Check if texture is valid (loaded in GPU)
RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM) RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM)
RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if render texture is valid (loaded in GPU) RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if render texture is valid (loaded in GPU)

View File

@ -994,6 +994,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#if !defined(GRAPHICS_API_OPENGL_ES3) #if !defined(GRAPHICS_API_OPENGL_ES3)
#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER
#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER
#define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING
#endif #endif
#endif #endif
@ -1847,7 +1848,7 @@ void rlEnableFramebuffer(unsigned int id)
unsigned int rlGetActiveFramebuffer(void) unsigned int rlGetActiveFramebuffer(void)
{ {
GLint fboId = 0; GLint fboId = 0;
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3) || defined(GRAPHICS_API_OPENGL_SOFTWARE)) #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_SOFTWARE))
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &fboId); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &fboId);
#endif #endif
return fboId; return fboId;

View File

@ -3977,10 +3977,10 @@ void ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color col
while (y >= x) while (y >= x)
{ {
ImageDrawRectangle(dst, centerX - x, centerY + y, x*2, 1, color); ImageDrawRectangle(dst, centerX - x, centerY + y, x*2 + 1, 1, color);
ImageDrawRectangle(dst, centerX - x, centerY - y, x*2, 1, color); ImageDrawRectangle(dst, centerX - x, centerY - y, x*2 + 1, 1, color);
ImageDrawRectangle(dst, centerX - y, centerY + x, y*2, 1, color); ImageDrawRectangle(dst, centerX - y, centerY + x, y*2 + 1, 1, color);
ImageDrawRectangle(dst, centerX - y, centerY - x, y*2, 1, color); ImageDrawRectangle(dst, centerX - y, centerY - x, y*2 + 1, 1, color);
x++; x++;
if (decesionParameter > 0) if (decesionParameter > 0)
@ -4388,12 +4388,24 @@ TextureCubemap LoadTextureCubemap(Image image, int layout)
return cubemap; return cubemap;
} }
// Load texture for rendering (framebuffer) // Load RGBA texture for rendering (framebuffer)
// NOTE: Render texture is loaded by default with RGBA color attachment and depth RenderBuffer
RenderTexture2D LoadRenderTexture(int width, int height) RenderTexture2D LoadRenderTexture(int width, int height)
{
return LoadRenderTextureEx(width, height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8);
}
// Load texture for rendering (framebuffer), with specific format
// NOTE: Render texture is loaded by default with RGBA color attachment and depth RenderBuffer
RLAPI RenderTexture2D LoadRenderTextureEx(int width, int height, int format)
{ {
RenderTexture2D target = { 0 }; RenderTexture2D target = { 0 };
if (format >= PIXELFORMAT_COMPRESSED_DXT1_RGB)
{
TRACELOG(LOG_WARNING, "FBO: Render texture format not supported");
return target;
}
target.id = rlLoadFramebuffer(); // Load an empty framebuffer target.id = rlLoadFramebuffer(); // Load an empty framebuffer
if (target.id > 0) if (target.id > 0)
@ -4401,10 +4413,10 @@ RenderTexture2D LoadRenderTexture(int width, int height)
rlEnableFramebuffer(target.id); rlEnableFramebuffer(target.id);
// Create color texture (default to RGBA) // Create color texture (default to RGBA)
target.texture.id = rlLoadTexture(NULL, width, height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1); target.texture.id = rlLoadTexture(NULL, width, height, format, 1);
target.texture.width = width; target.texture.width = width;
target.texture.height = height; target.texture.height = height;
target.texture.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; target.texture.format = format;
target.texture.mipmaps = 1; target.texture.mipmaps = 1;
// Create depth renderbuffer/texture // Create depth renderbuffer/texture
@ -5333,7 +5345,7 @@ Color GetPixelColor(const void *srcPtr, int format)
{ {
color.r = (unsigned char)((((unsigned short *)srcPtr)[0] >> 11)*255/31); color.r = (unsigned char)((((unsigned short *)srcPtr)[0] >> 11)*255/31);
color.g = (unsigned char)(((((unsigned short *)srcPtr)[0] >> 6) & 0b0000000000011111)*255/31); color.g = (unsigned char)(((((unsigned short *)srcPtr)[0] >> 6) & 0b0000000000011111)*255/31);
color.b = (unsigned char)((((unsigned short *)srcPtr)[0] & 0b0000000000011111)*255/31); color.b = (unsigned char)(((((unsigned short *)srcPtr)[0] >> 1) & 0b0000000000011111)*255/31);
color.a = (((unsigned short *)srcPtr)[0] & 0b0000000000000001)? 255 : 0; color.a = (((unsigned short *)srcPtr)[0] & 0b0000000000000001)? 255 : 0;
} break; } break;

View File

@ -9125,6 +9125,25 @@
} }
] ]
}, },
{
"name": "LoadRenderTextureEx",
"description": "Load texture for rendering (framebuffer), with specific format",
"returnType": "RenderTexture2D",
"params": [
{
"type": "int",
"name": "width"
},
{
"type": "int",
"name": "height"
},
{
"type": "int",
"name": "format"
}
]
},
{ {
"name": "IsTextureValid", "name": "IsTextureValid",
"description": "Check if texture is valid (loaded in GPU)", "description": "Check if texture is valid (loaded in GPU)",

View File

@ -6536,6 +6536,16 @@ return {
{type = "int", name = "height"} {type = "int", name = "height"}
} }
}, },
{
name = "LoadRenderTextureEx",
description = "Load texture for rendering (framebuffer), with specific format",
returnType = "RenderTexture2D",
params = {
{type = "int", name = "width"},
{type = "int", name = "height"},
{type = "int", name = "format"}
}
},
{ {
name = "IsTextureValid", name = "IsTextureValid",
description = "Check if texture is valid (loaded in GPU)", description = "Check if texture is valid (loaded in GPU)",

View File

@ -4930,6 +4930,14 @@
((type "int") (name "width")) ((type "int") (name "width"))
((type "int") (name "height")))) ((type "int") (name "height"))))
((name "LoadRenderTextureEx")
(description "Load texture for rendering (framebuffer), with specific format")
(return-type "RenderTexture2D")
(params
((type "int") (name "width"))
((type "int") (name "height"))
((type "int") (name "format"))))
((name "IsTextureValid") ((name "IsTextureValid")
(description "Check if texture is valid (loaded in GPU)") (description "Check if texture is valid (loaded in GPU)")
(return-type "bool") (return-type "bool")

File diff suppressed because it is too large Load Diff

View File

@ -681,7 +681,7 @@
<Param type="unsigned int" name="frames" desc="" /> <Param type="unsigned int" name="frames" desc="" />
</Callback> </Callback>
</Callbacks> </Callbacks>
<Functions count="617"> <Functions count="618">
<Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context"> <Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context">
<Param type="int" name="width" desc="" /> <Param type="int" name="width" desc="" />
<Param type="int" name="height" desc="" /> <Param type="int" name="height" desc="" />
@ -2306,6 +2306,11 @@
<Param type="int" name="width" desc="" /> <Param type="int" name="width" desc="" />
<Param type="int" name="height" desc="" /> <Param type="int" name="height" desc="" />
</Function> </Function>
<Function name="LoadRenderTextureEx" retType="RenderTexture2D" paramCount="3" desc="Load texture for rendering (framebuffer), with specific format">
<Param type="int" name="width" desc="" />
<Param type="int" name="height" desc="" />
<Param type="int" name="format" desc="" />
</Function>
<Function name="IsTextureValid" retType="bool" paramCount="1" desc="Check if texture is valid (loaded in GPU)"> <Function name="IsTextureValid" retType="bool" paramCount="1" desc="Check if texture is valid (loaded in GPU)">
<Param type="Texture2D" name="texture" desc="" /> <Param type="Texture2D" name="texture" desc="" />
</Function> </Function>