|
@@ -749,7 +749,7 @@ RLAPI void rlDrawVertexArrayElementsInstanced(int offset, int count, const void
|
|
// Textures management
|
|
// Textures management
|
|
RLAPI unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount); // Load texture data
|
|
RLAPI unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount); // Load texture data
|
|
RLAPI unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer); // Load depth texture/renderbuffer (to be attached to fbo)
|
|
RLAPI unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer); // Load depth texture/renderbuffer (to be attached to fbo)
|
|
-RLAPI unsigned int rlLoadTextureCubemap(const void *data, int size, int format); // Load texture cubemap data
|
|
|
|
|
|
+RLAPI unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mipmapCount); // Load texture cubemap data
|
|
RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data); // Update texture with new data on GPU
|
|
RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data); // Update texture with new data on GPU
|
|
RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats
|
|
RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats
|
|
RLAPI const char *rlGetPixelFormatName(unsigned int format); // Get name string for pixel format
|
|
RLAPI const char *rlGetPixelFormatName(unsigned int format); // Get name string for pixel format
|
|
@@ -3386,11 +3386,17 @@ unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer)
|
|
// Load texture cubemap
|
|
// Load texture cubemap
|
|
// NOTE: Cubemap data is expected to be 6 images in a single data array (one after the other),
|
|
// NOTE: Cubemap data is expected to be 6 images in a single data array (one after the other),
|
|
// expected the following convention: +X, -X, +Y, -Y, +Z, -Z
|
|
// expected the following convention: +X, -X, +Y, -Y, +Z, -Z
|
|
-unsigned int rlLoadTextureCubemap(const void *data, int size, int format)
|
|
|
|
|
|
+unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mipmapCount)
|
|
{
|
|
{
|
|
unsigned int id = 0;
|
|
unsigned int id = 0;
|
|
|
|
|
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
|
|
|
+ int mipSize = size;
|
|
|
|
+
|
|
|
|
+ // NOTE: Added pointer math separately from function to avoid UBSAN complaining
|
|
|
|
+ unsigned char *dataPtr = NULL;
|
|
|
|
+ if (data != NULL) dataPtr = (unsigned char *)data;
|
|
|
|
+
|
|
unsigned int dataSize = rlGetPixelDataSize(size, size, format);
|
|
unsigned int dataSize = rlGetPixelDataSize(size, size, format);
|
|
|
|
|
|
glGenTextures(1, &id);
|
|
glGenTextures(1, &id);
|
|
@@ -3401,9 +3407,12 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format)
|
|
|
|
|
|
if (glInternalFormat != 0)
|
|
if (glInternalFormat != 0)
|
|
{
|
|
{
|
|
- // Load cubemap faces
|
|
|
|
- for (unsigned int i = 0; i < 6; i++)
|
|
|
|
|
|
+ // Load cubemap faces/mipmaps
|
|
|
|
+ for (unsigned int i = 0; i < 6 * mipmapCount; i++)
|
|
{
|
|
{
|
|
|
|
+ int mipmapLevel = i / 6;
|
|
|
|
+ int face = i % 6;
|
|
|
|
+
|
|
if (data == NULL)
|
|
if (data == NULL)
|
|
{
|
|
{
|
|
if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)
|
|
if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)
|
|
@@ -3411,14 +3420,14 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format)
|
|
if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32)
|
|
if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32)
|
|
|| (format == RL_PIXELFORMAT_UNCOMPRESSED_R16) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16))
|
|
|| (format == RL_PIXELFORMAT_UNCOMPRESSED_R16) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16))
|
|
TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported");
|
|
TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported");
|
|
- else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, NULL);
|
|
|
|
|
|
+ else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, glFormat, glType, NULL);
|
|
}
|
|
}
|
|
else TRACELOG(RL_LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format");
|
|
else TRACELOG(RL_LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format");
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, (unsigned char *)data + i*dataSize);
|
|
|
|
- else glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, dataSize, (unsigned char *)data + i*dataSize);
|
|
|
|
|
|
+ if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, glFormat, glType, (unsigned char *)dataPtr + face*dataSize);
|
|
|
|
+ else glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, dataSize, (unsigned char *)dataPtr + face*dataSize);
|
|
}
|
|
}
|
|
|
|
|
|
#if defined(GRAPHICS_API_OPENGL_33)
|
|
#if defined(GRAPHICS_API_OPENGL_33)
|
|
@@ -3437,11 +3446,25 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format)
|
|
glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
|
glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
+ if (face == 5) {
|
|
|
|
+ mipSize /= 2;
|
|
|
|
+ if (data != NULL)
|
|
|
|
+ dataPtr += dataSize * 6; // Increment data pointer to next mipmap
|
|
|
|
+
|
|
|
|
+ // Security check for NPOT textures
|
|
|
|
+ if (mipSize < 1) mipSize = 1;
|
|
|
|
+
|
|
|
|
+ dataSize = rlGetPixelDataSize(mipSize, mipSize, format);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Set cubemap texture sampling parameters
|
|
// Set cubemap texture sampling parameters
|
|
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
|
|
+ if (mipmapCount > 1) {
|
|
|
|
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
|
|
+ } else {
|
|
|
|
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
+ }
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|