Possibly fixed the swizzling bug

This commit is contained in:
msmith-codes 2025-12-21 15:18:25 -05:00
parent 3212becc91
commit a309ecedc2
4 changed files with 192 additions and 1 deletions

View File

@ -0,0 +1,125 @@
#!/usr/bin/env python3
"""Generate a test DDS file with mipmaps to verify swizzling fix"""
import struct
import os
def write_dword(f, value):
"""Write a 32-bit unsigned integer (little-endian)"""
f.write(struct.pack('<I', value))
def write_word(f, value):
"""Write a 16-bit unsigned integer (little-endian)"""
f.write(struct.pack('<H', value))
def generate_bgra_image(width, height):
"""Generate a simple test pattern in BGRA format"""
data = bytearray(width * height * 4)
for y in range(height):
for x in range(width):
idx = (y * width + x) * 4
# Left half red, right half blue (in BGRA format)
if x < width // 2:
data[idx + 0] = 0 # B
data[idx + 1] = 0 # G
data[idx + 2] = 255 # R
data[idx + 3] = 255 # A
else:
data[idx + 0] = 255 # B
data[idx + 1] = 0 # G
data[idx + 2] = 0 # R
data[idx + 3] = 255 # A
return bytes(data)
def generate_mipmap(data, width, height):
"""Generate a mipmap level by downscaling 2x"""
new_width = max(1, width // 2)
new_height = max(1, height // 2)
new_data = bytearray(new_width * new_height * 4)
for y in range(new_height):
for x in range(new_width):
# Simple box filter
src_x = x * 2
src_y = y * 2
idx = (y * new_width + x) * 4
src_idx = (src_y * width + src_x) * 4
# Copy pixel (simple nearest neighbor)
new_data[idx:idx+4] = data[src_idx:src_idx+4]
return bytes(new_data)
def write_dds_file(filename, width, height):
"""Write a DDS file with RGBA format and mipmaps"""
# Calculate mipmap count
mipmap_count = 1
mip_w, mip_h = width, height
while mip_w > 1 or mip_h > 1:
mip_w = max(1, mip_w // 2)
mip_h = max(1, mip_h // 2)
mipmap_count += 1
print(f"Generating DDS: {width}x{height} with {mipmap_count} mipmaps")
with open(filename, 'wb') as f:
# Write DDS magic number
f.write(b'DDS ')
# Write DDS header (124 bytes)
write_dword(f, 124) # dwSize
write_dword(f, 0x1 | 0x2 | 0x4 | 0x1000 | 0x20000) # dwFlags (CAPS, HEIGHT, WIDTH, PIXELFORMAT, MIPMAPCOUNT)
write_dword(f, height) # dwHeight
write_dword(f, width) # dwWidth
write_dword(f, width * 4) # dwPitchOrLinearSize
write_dword(f, 0) # dwDepth
write_dword(f, mipmap_count) # dwMipMapCount
# Reserved1[11]
for _ in range(11):
write_dword(f, 0)
# DDS_PIXELFORMAT (32 bytes)
write_dword(f, 32) # dwSize
write_dword(f, 0x41) # dwFlags (RGBA)
write_dword(f, 0) # dwFourCC
write_dword(f, 32) # dwRGBBitCount
write_dword(f, 0x00FF0000) # dwRBitMask (R at byte 2)
write_dword(f, 0x0000FF00) # dwGBitMask (G at byte 1)
write_dword(f, 0x000000FF) # dwBBitMask (B at byte 0)
write_dword(f, 0xFF000000) # dwABitMask (A at byte 3)
# dwCaps
write_dword(f, 0x1000 | 0x8 | 0x400000) # TEXTURE | COMPLEX | MIPMAP
write_dword(f, 0) # dwCaps2
write_dword(f, 0) # dwCaps3
write_dword(f, 0) # dwCaps4
write_dword(f, 0) # dwReserved2
# Write image data with mipmaps
mip_w, mip_h = width, height
mip_data = generate_bgra_image(width, height)
for mip in range(mipmap_count):
print(f" Mipmap {mip}: {mip_w}x{mip_h} ({len(mip_data)} bytes)")
f.write(mip_data)
if mip < mipmap_count - 1:
mip_data = generate_mipmap(mip_data, mip_w, mip_h)
mip_w = max(1, mip_w // 2)
mip_h = max(1, mip_h // 2)
print(f"✓ Created {filename}")
if __name__ == "__main__":
# Create resources directory if it doesn't exist
os.makedirs("resources", exist_ok=True)
# Generate test DDS file
write_dds_file("resources/test_rgba_mipmaps.dds", 256, 256)
print("\nTest file created!")
print("Left half should be RED, right half should be BLUE")
print("If the fix is working, all mipmap levels will show correct colors")

Binary file not shown.

View File

@ -0,0 +1,66 @@
/*******************************************************************************************
*
* raylib [textures] example - Test DDS loading with mipmaps
*
********************************************************************************************/
#include "raylib.h"
int main(void)
{
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [textures] - DDS mipmaps test");
// Load DDS texture with mipmaps (create one with a distinct color pattern)
Texture2D texture = LoadTexture("resources/test_rgba_mipmaps.dds");
if (texture.id == 0)
{
TraceLog(LOG_ERROR, "Failed to load DDS texture");
}
else
{
TraceLog(LOG_INFO, "DDS texture loaded: %dx%d, mipmaps: %d",
texture.width, texture.height, texture.mipmaps);
}
SetTargetFPS(60);
while (!WindowShouldClose())
{
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw texture at different scales to see mipmap levels
DrawTexturePro(texture,
(Rectangle){0, 0, texture.width, texture.height},
(Rectangle){50, 50, 256, 256},
(Vector2){0, 0}, 0.0f, WHITE);
DrawTexturePro(texture,
(Rectangle){0, 0, texture.width, texture.height},
(Rectangle){350, 50, 128, 128},
(Vector2){0, 0}, 0.0f, WHITE);
DrawTexturePro(texture,
(Rectangle){0, 0, texture.width, texture.height},
(Rectangle){520, 50, 64, 64},
(Vector2){0, 0}, 0.0f, WHITE);
DrawText("256x256", 50, 320, 20, DARKGRAY);
DrawText("128x128", 350, 190, 20, DARKGRAY);
DrawText("64x64", 520, 125, 20, DARKGRAY);
DrawText("If colors look wrong (blue/red swapped), mipmaps have swizzling bug",
10, 400, 10, RED);
EndDrawing();
}
UnloadTexture(texture);
CloseWindow();
return 0;
}

View File

@ -362,7 +362,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
// NOTE: Data comes as A8R8G8B8, it must be reordered R8G8B8A8 (view next comment) // NOTE: Data comes as A8R8G8B8, it must be reordered R8G8B8A8 (view next comment)
// DirecX understand ARGB as a 32bit DWORD but the actual memory byte alignment is BGRA // DirecX understand ARGB as a 32bit DWORD but the actual memory byte alignment is BGRA
// So, we must realign B8G8R8A8 to R8G8B8A8 // So, we must realign B8G8R8A8 to R8G8B8A8
for (int i = 0; i < image_pixel_size*4; i += 4) for (int i = 0; i < data_size; i += 4)
{ {
blue = ((unsigned char *)image_data)[i]; blue = ((unsigned char *)image_data)[i];
((unsigned char *)image_data)[i] = ((unsigned char *)image_data)[i + 2]; ((unsigned char *)image_data)[i] = ((unsigned char *)image_data)[i + 2];