mirror of
https://github.com/raysan5/raylib.git
synced 2025-10-08 19:06:27 +00:00
Merge branch 'master' of https://github.com/raysan5/raylib into dr/mini_al
This commit is contained in:
22
src/CMakeLists.txt
Executable file → Normal file
22
src/CMakeLists.txt
Executable file → Normal file
@@ -17,7 +17,8 @@ include_directories(SYSTEM .)
|
||||
file(GLOB raylib_sources *.c)
|
||||
list(REMOVE_ITEM raylib_sources ${CMAKE_CURRENT_SOURCE_DIR}/rglfw.c)
|
||||
|
||||
if(NOT glfw3_FOUND AND "${PLATFORM}" MATCHES "Desktop")
|
||||
# Explicitly check against "ON", because USE_EXTERNAL_GLFW is a tristate option
|
||||
if(NOT glfw3_FOUND AND NOT USE_EXTERNAL_GLFW STREQUAL "ON" AND "${PLATFORM}" MATCHES "Desktop")
|
||||
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
|
||||
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
@@ -32,6 +33,8 @@ if(NOT glfw3_FOUND AND "${PLATFORM}" MATCHES "Desktop")
|
||||
include_directories(external/glfw/include)
|
||||
|
||||
list(APPEND raylib_sources $<TARGET_OBJECTS:glfw_objlib>)
|
||||
else()
|
||||
set(GLFW_PKG_DEPS glfw)
|
||||
endif()
|
||||
|
||||
include(utils)
|
||||
@@ -91,7 +94,7 @@ elseif(${PLATFORM} MATCHES "Android")
|
||||
add_if_flag_compiles(-Wa,--noexecstack CMAKE_C_FLAGS)
|
||||
add_if_flag_compiles(-no-canonical-prefixes CMAKE_C_FLAGS)
|
||||
add_definitions(-DANDROID -D__ANDROID_API__=21)
|
||||
include_directories(external/android/native_app_glue )
|
||||
include_directories(external/android/native_app_glue)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libatomic.a -Wl,--build-id -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -uANativeActivity_onCreate")
|
||||
|
||||
elseif(${PLATFORM} MATCHES "Raspberry Pi")
|
||||
@@ -113,8 +116,8 @@ if(${SHARED})
|
||||
set(CMAKE_MACOSX_RPATH ON)
|
||||
|
||||
target_link_libraries(${RAYLIB}_shared ${LIBS_PRIVATE})
|
||||
if (${PLATFORM} MATCHES "Desktop")
|
||||
target_link_libraries(${RAYLIB}_shared glfw ${GLFW_LIBRARIES})
|
||||
if (${PLATFORM} MATCHES "PLATFORM_DESKTOP")
|
||||
target_link_libraries(${RAYLIB}_shared glfw)
|
||||
endif()
|
||||
if (UNIX AND ${FILESYSTEM_LACKS_SYMLINKS})
|
||||
MESSAGE(WARNING "Can't version UNIX shared library on file system without symlink support")
|
||||
@@ -141,6 +144,8 @@ if(${SHARED})
|
||||
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
add_test("pkg-config" ${PROJECT_SOURCE_DIR}/../cmake/test-pkgconfig.sh)
|
||||
endif(${SHARED})
|
||||
|
||||
if(${STATIC})
|
||||
@@ -150,8 +155,9 @@ if(${STATIC})
|
||||
|
||||
add_library(${RAYLIB} STATIC ${sources})
|
||||
|
||||
set(PKG_CONFIG_LIBS_PRIVATE ${__PKG_CONFIG_LIBS_PRIVATE})
|
||||
if (${PLATFORM} MATCHES "Desktop")
|
||||
set(PKG_CONFIG_LIBS_PRIVATE ${__PKG_CONFIG_LIBS_PRIVATE} ${GLFW_PKG_LIBS})
|
||||
string (REPLACE ";" " " PKG_CONFIG_LIBS_PRIVATE "${PKG_CONFIG_LIBS_PRIVATE}")
|
||||
if (${PLATFORM} MATCHES "PLATFORM_DESKTOP")
|
||||
target_link_libraries(${RAYLIB} glfw ${GLFW_LIBRARIES})
|
||||
endif()
|
||||
|
||||
@@ -163,6 +169,8 @@ if(${STATIC})
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
|
||||
add_test("pkg-config--static" ${PROJECT_SOURCE_DIR}/../cmake/test-pkgconfig.sh --static)
|
||||
endif(${STATIC})
|
||||
|
||||
configure_file(../raylib.pc.in raylib.pc @ONLY)
|
||||
@@ -199,3 +207,5 @@ SET(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/../LICENSE.md")
|
||||
SET(CPACK_PACKAGE_FILE_NAME "raylib-${PROJECT_VERSION}$ENV{RAYLIB_PACKAGE_SUFFIX}")
|
||||
SET(CPACK_GENERATOR "ZIP;TGZ") # Remove this, if you want the NSIS installer on Windows
|
||||
include(CPack)
|
||||
|
||||
enable_testing()
|
||||
|
32
src/Makefile
32
src/Makefile
@@ -6,7 +6,7 @@
|
||||
# PLATFORM_DESKTOP: Windows (Win32, Win64)
|
||||
# PLATFORM_DESKTOP: Linux (32 and 64 bit)
|
||||
# PLATFORM_DESKTOP: OSX/macOS
|
||||
# PLATFORM_DESKTOP: FreeBSD
|
||||
# PLATFORM_DESKTOP: FreeBSD, OpenBSD, NetBSD, DragonFly
|
||||
# PLATFORM_ANDROID: Android (ARM, ARM64)
|
||||
# PLATFORM_RPI: Raspberry Pi (Raspbian)
|
||||
# PLATFORM_WEB: HTML5 (Chrome, Firefox)
|
||||
@@ -111,7 +111,16 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
||||
PLATFORM_OS=LINUX
|
||||
endif
|
||||
ifeq ($(UNAMEOS),FreeBSD)
|
||||
PLATFORM_OS=FREEBSD
|
||||
PLATFORM_OS=BSD
|
||||
endif
|
||||
ifeq ($(UNAMEOS),OpenBSD)
|
||||
PLATFORM_OS=BSD
|
||||
endif
|
||||
ifeq ($(UNAMEOS),NetBSD)
|
||||
PLATFORM_OS=BSD
|
||||
endif
|
||||
ifeq ($(UNAMEOS),DragonFly)
|
||||
PLATFORM_OS=BSD
|
||||
endif
|
||||
ifeq ($(UNAMEOS),Darwin)
|
||||
PLATFORM_OS=OSX
|
||||
@@ -185,8 +194,8 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
||||
ifeq ($(PLATFORM_OS),OSX)
|
||||
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),FREEBSD)
|
||||
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/freebsd
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/bsd
|
||||
endif
|
||||
endif
|
||||
ifeq ($(PLATFORM),PLATFORM_RPI)
|
||||
@@ -231,8 +240,8 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
||||
CC = clang
|
||||
GLFW_CFLAGS = -x objective-c
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),FREEBSD)
|
||||
# FreeBSD default compiler
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
# FreeBSD, OpenBSD, NetBSD, DragonFly default compiler
|
||||
CC = clang
|
||||
endif
|
||||
endif
|
||||
@@ -309,13 +318,14 @@ endif
|
||||
ifeq ($(PLATFORM),PLATFORM_ANDROID)
|
||||
# Compiler flags for arquitecture (only ARM, not ARM64)
|
||||
#CFLAGS += -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16
|
||||
CFLAGS += -target aarch64 -mfix-cortex-a53-835769
|
||||
# Compilation functions attributes options
|
||||
CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIE -fPIC
|
||||
# Compiler options for the linker
|
||||
# -Werror=format-security
|
||||
CFLAGS += -Wa,--noexecstack -Wformat -no-canonical-prefixes
|
||||
# Preprocessor macro definitions
|
||||
CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=21
|
||||
CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=21 -DMAL_NO_OSS
|
||||
endif
|
||||
|
||||
# Define required compilation flags for raylib SHARED lib
|
||||
@@ -345,7 +355,7 @@ endif
|
||||
INCLUDE_PATHS = -I. -Iexternal -Iexternal/glfw/include
|
||||
|
||||
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
||||
ifeq ($(PLATFORM_OS),FREEBSD)
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
INCLUDE_PATHS += -I/usr/local/include
|
||||
LDFLAGS += -L. -Lsrc -L/usr/local/lib -L$(RAYLIB_RELEASE_PATH)
|
||||
endif
|
||||
@@ -415,6 +425,10 @@ ifeq ($(INCLUDE_AUDIO_MODULE),TRUE)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),PLATFORM_ANDROID)
|
||||
OBJS += external/android/native_app_glue/android_native_app_glue.o
|
||||
endif
|
||||
|
||||
# Default target entry
|
||||
all: raylib
|
||||
|
||||
@@ -454,7 +468,7 @@ else
|
||||
cd $(RAYLIB_RELEASE_PATH) && ln -fs libraylib.$(RAYLIB_VERSION).dylib libraylib.$(RAYLIB_API_VERSION).dylib
|
||||
cd $(RAYLIB_RELEASE_PATH) && ln -fs libraylib.$(RAYLIB_VERSION).dylib libraylib.dylib
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),FREEBSD)
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
# WARNING: you should type "gmake clean" before doing this target
|
||||
$(CC) -shared -o $(RAYLIB_RELEASE_PATH)/libraylib.$(RAYLIB_VERSION).so $(OBJS) -Wl,-soname,libraylib.$(RAYLIB_API_VERSION).so -lGL -lpthread
|
||||
@echo "raylib shared library generated (libraylib.$(RAYLIB_VERSION).so)!"
|
||||
|
27
src/audio.c
27
src/audio.c
@@ -17,7 +17,7 @@
|
||||
* Required types and functions are defined in the same module.
|
||||
*
|
||||
* #define USE_OPENAL_BACKEND
|
||||
* Use OpenAL Soft audio backend usage
|
||||
* Use OpenAL Soft audio backend
|
||||
*
|
||||
* #define SUPPORT_FILEFORMAT_WAV
|
||||
* #define SUPPORT_FILEFORMAT_OGG
|
||||
@@ -73,11 +73,6 @@
|
||||
*
|
||||
**********************************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
#if !defined(USE_OPENAL_BACKEND)
|
||||
#define USE_MINI_AL 1 // Set to 1 to use mini_al; 0 to use OpenAL.
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_STANDALONE)
|
||||
#include "audio.h"
|
||||
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end()
|
||||
@@ -87,6 +82,10 @@
|
||||
#include "utils.h" // Required for: fopen() Android mapping
|
||||
#endif
|
||||
|
||||
#if !defined(USE_OPENAL_BACKEND)
|
||||
#define USE_MINI_AL 1 // Set to 1 to use mini_al; 0 to use OpenAL.
|
||||
#endif
|
||||
|
||||
#include "external/mini_al.h" // Implemented in mini_al.c. Cannot implement this here because it conflicts with Win32 APIs such as CloseWindow(), etc.
|
||||
|
||||
#if !defined(USE_MINI_AL) || (USE_MINI_AL == 0)
|
||||
@@ -668,7 +667,7 @@ AudioBuffer *CreateAudioBuffer(mal_format format, mal_uint32 channels, mal_uint3
|
||||
mal_result resultMAL = mal_dsp_init(&dspConfig, &audioBuffer->dsp);
|
||||
if (resultMAL != MAL_SUCCESS)
|
||||
{
|
||||
TraceLog(LOG_ERROR, "LoadSoundFromWave() : Failed to create data conversion pipeline");
|
||||
TraceLog(LOG_ERROR, "CreateAudioBuffer() : Failed to create data conversion pipeline");
|
||||
free(audioBuffer);
|
||||
return NULL;
|
||||
}
|
||||
@@ -696,7 +695,7 @@ void DeleteAudioBuffer(AudioBuffer *audioBuffer)
|
||||
{
|
||||
if (audioBuffer == NULL)
|
||||
{
|
||||
TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer");
|
||||
TraceLog(LOG_ERROR, "DeleteAudioBuffer() : No audio buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -709,7 +708,7 @@ bool IsAudioBufferPlaying(AudioBuffer *audioBuffer)
|
||||
{
|
||||
if (audioBuffer == NULL)
|
||||
{
|
||||
TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer");
|
||||
TraceLog(LOG_ERROR, "IsAudioBufferPlaying() : No audio buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -737,7 +736,7 @@ void StopAudioBuffer(AudioBuffer *audioBuffer)
|
||||
{
|
||||
if (audioBuffer == NULL)
|
||||
{
|
||||
TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer");
|
||||
TraceLog(LOG_ERROR, "StopAudioBuffer() : No audio buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -756,7 +755,7 @@ void PauseAudioBuffer(AudioBuffer *audioBuffer)
|
||||
{
|
||||
if (audioBuffer == NULL)
|
||||
{
|
||||
TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer");
|
||||
TraceLog(LOG_ERROR, "PauseAudioBuffer() : No audio buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -768,7 +767,7 @@ void ResumeAudioBuffer(AudioBuffer *audioBuffer)
|
||||
{
|
||||
if (audioBuffer == NULL)
|
||||
{
|
||||
TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer");
|
||||
TraceLog(LOG_ERROR, "ResumeAudioBuffer() : No audio buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -780,7 +779,7 @@ void SetAudioBufferVolume(AudioBuffer *audioBuffer, float volume)
|
||||
{
|
||||
if (audioBuffer == NULL)
|
||||
{
|
||||
TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer");
|
||||
TraceLog(LOG_ERROR, "SetAudioBufferVolume() : No audio buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -792,7 +791,7 @@ void SetAudioBufferPitch(AudioBuffer *audioBuffer, float pitch)
|
||||
{
|
||||
if (audioBuffer == NULL)
|
||||
{
|
||||
TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer");
|
||||
TraceLog(LOG_ERROR, "SetAudioBufferPitch() : No audio buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -244,8 +244,8 @@ void SetCameraMode(Camera camera, int mode)
|
||||
distance.y = sqrtf(dx*dx + dy*dy);
|
||||
|
||||
// Camera angle calculation
|
||||
cameraAngle.x = asinf(fabsf(dx)/distance.x); // Camera angle in plane XZ (0 aligned with Z, move positive CCW)
|
||||
cameraAngle.y = -asinf(fabsf(dy)/distance.y); // Camera angle in plane XY (0 aligned with X, move positive CW)
|
||||
cameraAngle.x = asinf(fabs(dx)/distance.x); // Camera angle in plane XZ (0 aligned with Z, move positive CCW)
|
||||
cameraAngle.y = -asinf(fabs(dy)/distance.y); // Camera angle in plane XY (0 aligned with X, move positive CW)
|
||||
|
||||
// NOTE: Just testing what cameraAngle means
|
||||
//cameraAngle.x = 0.0f*DEG2RAD; // Camera angle in plane XZ (0 aligned with Z, move positive CCW)
|
||||
|
51
src/core.c
51
src/core.c
@@ -5,7 +5,7 @@
|
||||
* PLATFORMS SUPPORTED:
|
||||
* - PLATFORM_DESKTOP: Windows (Win32, Win64)
|
||||
* - PLATFORM_DESKTOP: Linux (X11 desktop mode)
|
||||
* - PLATFORM_DESKTOP: FreeBSD (X11 desktop)
|
||||
* - PLATFORM_DESKTOP: FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop)
|
||||
* - PLATFORM_DESKTOP: OSX/macOS
|
||||
* - PLATFORM_ANDROID: Android 4.0 (ARM, ARM64)
|
||||
* - PLATFORM_RPI: Raspberry Pi 0,1,2,3 (Raspbian)
|
||||
@@ -15,7 +15,7 @@
|
||||
* CONFIGURATION:
|
||||
*
|
||||
* #define PLATFORM_DESKTOP
|
||||
* Windowing and input system configured for desktop platforms: Windows, Linux, OSX, FreeBSD
|
||||
* Windowing and input system configured for desktop platforms: Windows, Linux, OSX, FreeBSD, OpenBSD, NetBSD, DragonFly
|
||||
* NOTE: Oculus Rift CV1 requires PLATFORM_DESKTOP for mirror rendering - View [rlgl] module to enable it
|
||||
*
|
||||
* #define PLATFORM_ANDROID
|
||||
@@ -57,7 +57,7 @@
|
||||
* Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback()
|
||||
*
|
||||
* DEPENDENCIES:
|
||||
* rglfw - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX. FreeBSD)
|
||||
* rglfw - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX. FreeBSD, OpenBSD, NetBSD, DragonFly)
|
||||
* raymath - 3D math functionality (Vector2, Vector3, Matrix, Quaternion)
|
||||
* camera - Multiple 3D camera modes (free, orbital, 1st person, 3rd person)
|
||||
* gestures - Gestures system for touch-ready devices (or simulated from mouse inputs)
|
||||
@@ -1884,31 +1884,30 @@ static bool InitGraphicsDevice(int width, int height)
|
||||
displayHeight = screenHeight;
|
||||
#endif // defined(PLATFORM_WEB)
|
||||
|
||||
glfwDefaultWindowHints(); // Set default windows hints
|
||||
|
||||
// Check some Window creation flags
|
||||
if (configFlags & FLAG_WINDOW_RESIZABLE) glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // Resizable window
|
||||
else glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable
|
||||
|
||||
if (configFlags & FLAG_WINDOW_DECORATED) glfwWindowHint(GLFW_DECORATED, GL_TRUE); // Border and buttons on Window
|
||||
|
||||
if (configFlags & FLAG_WINDOW_TRANSPARENT)
|
||||
{
|
||||
// TODO: Enable transparent window (not ready yet on GLFW 3.2)
|
||||
}
|
||||
|
||||
if (configFlags & FLAG_MSAA_4X_HINT)
|
||||
{
|
||||
glfwWindowHint(GLFW_SAMPLES, 4); // Enables multisampling x4 (MSAA), default is 0
|
||||
TraceLog(LOG_INFO, "Trying to enable MSAA x4");
|
||||
}
|
||||
|
||||
glfwDefaultWindowHints(); // Set default windows hints:
|
||||
//glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits
|
||||
//glfwWindowHint(GLFW_DEPTH_BITS, 16); // Depthbuffer bits (24 by default)
|
||||
//glfwWindowHint(GLFW_GREEN_BITS, 8); // Framebuffer green color component bits
|
||||
//glfwWindowHint(GLFW_BLUE_BITS, 8); // Framebuffer blue color component bits
|
||||
//glfwWindowHint(GLFW_ALPHA_BITS, 8); // Framebuffer alpha color component bits
|
||||
//glfwWindowHint(GLFW_DEPTH_BITS, 24); // Depthbuffer bits
|
||||
//glfwWindowHint(GLFW_REFRESH_RATE, 0); // Refresh rate for fullscreen window
|
||||
//glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // Default OpenGL API to use. Alternative: GLFW_OPENGL_ES_API
|
||||
//glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // OpenGL API to use. Alternative: GLFW_OPENGL_ES_API
|
||||
//glfwWindowHint(GLFW_AUX_BUFFERS, 0); // Number of auxiliar buffers
|
||||
|
||||
// Check some Window creation flags
|
||||
if (configFlags & FLAG_WINDOW_RESIZABLE) glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // Resizable window
|
||||
else glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable
|
||||
|
||||
if (configFlags & FLAG_WINDOW_UNDECORATED) glfwWindowHint(GLFW_DECORATED, GL_FALSE); // Border and buttons on Window
|
||||
else glfwWindowHint(GLFW_DECORATED, GL_TRUE); // Decorated window
|
||||
|
||||
#if !defined(PLATFORM_WEB) // FLAG_WINDOW_TRANSPARENT not supported on HTML5
|
||||
if (configFlags & FLAG_WINDOW_TRANSPARENT) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer
|
||||
else glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE); // Opaque framebuffer
|
||||
#endif
|
||||
|
||||
if (configFlags & FLAG_MSAA_4X_HINT) glfwWindowHint(GLFW_SAMPLES, 4); // Tries to enable multisampling x4 (MSAA), default is 0
|
||||
|
||||
// NOTE: When asking for an OpenGL context version, most drivers provide highest supported version
|
||||
// with forward compatibility to older OpenGL versions.
|
||||
// For example, if using OpenGL 1.1, driver can provide a 4.3 context forward compatible.
|
||||
@@ -1926,11 +1925,11 @@ static bool InitGraphicsDevice(int width, int height)
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above!
|
||||
// Other values: GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE
|
||||
#if defined(__APPLE__)
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // OSX Requires
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // OSX Requires fordward compatibility
|
||||
#else
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); // Fordward Compatibility Hint: Only 3.3 and above!
|
||||
#endif
|
||||
//glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
|
||||
//glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); // Request OpenGL DEBUG context
|
||||
}
|
||||
|
||||
if (fullscreen)
|
||||
|
@@ -27,11 +27,6 @@ if (WIN32)
|
||||
"$ENV{VULKAN_SDK}/Bin32"
|
||||
"$ENV{VK_SDK_PATH}/Bin32")
|
||||
endif()
|
||||
elseif (APPLE)
|
||||
find_library(VULKAN_LIBRARY vulkan.1 HINTS
|
||||
"$ENV{VULKAN_SDK}/macOS/lib")
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"$ENV{VULKAN_SDK}/macOS/include")
|
||||
else()
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"$ENV{VULKAN_SDK}/include")
|
||||
|
4
src/external/glfw/CMakeLists.txt
vendored
4
src/external/glfw/CMakeLists.txt
vendored
@@ -327,10 +327,10 @@ endif()
|
||||
# Export GLFW library dependencies
|
||||
#--------------------------------------------------------------------
|
||||
foreach(arg ${glfw_PKG_DEPS})
|
||||
set(GLFW_PKG_DEPS "${GLFW_PKG_DEPS} ${arg}")
|
||||
set(GLFW_PKG_DEPS "${GLFW_PKG_DEPS} ${arg}" PARENT_SCOPE)
|
||||
endforeach()
|
||||
foreach(arg ${glfw_PKG_LIBS})
|
||||
set(GLFW_PKG_LIBS "${GLFW_PKG_LIBS} ${arg}")
|
||||
set(GLFW_PKG_LIBS "${GLFW_PKG_LIBS} ${arg}" PARENT_SCOPE)
|
||||
endforeach()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
|
2
src/external/glfw/README.md
vendored
2
src/external/glfw/README.md
vendored
@@ -165,6 +165,8 @@ information on what to include when reporting a bug.
|
||||
- Added `GLFW_HOVERED` window attribute for polling cursor hover state (#1166)
|
||||
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
|
||||
(#749,#842)
|
||||
- Added `GLFW_FOCUS_ON_SHOW` window hint and attribute to control input focus
|
||||
on calling show window (#1189)
|
||||
- Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)
|
||||
- Added `GLFW_LOCK_KEY_MODS` input mode and `GLFW_MOD_*_LOCK` mod bits (#946)
|
||||
- Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint
|
||||
|
20
src/external/glfw/include/GLFW/glfw3.h
vendored
20
src/external/glfw/include/GLFW/glfw3.h
vendored
@@ -819,6 +819,12 @@ extern "C" {
|
||||
* Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib).
|
||||
*/
|
||||
#define GLFW_HOVERED 0x0002000B
|
||||
/*! @brief Input focus on calling show window hint and attribute
|
||||
*
|
||||
* Input focus [window hint](@ref GLFW_FOCUS_ON_SHOW_hint) or
|
||||
* [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib).
|
||||
*/
|
||||
#define GLFW_FOCUS_ON_SHOW 0x0002000C
|
||||
|
||||
/*! @brief Framebuffer bit depth hint.
|
||||
*
|
||||
@@ -3085,6 +3091,11 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window);
|
||||
* hidden. If the window is already visible or is in full screen mode, this
|
||||
* function does nothing.
|
||||
*
|
||||
* By default, windowed mode windows are focused when shown
|
||||
* Set the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint
|
||||
* to change this behavior for all newly created windows, or change the
|
||||
* behavior for an existing window with @ref glfwSetWindowAttrib.
|
||||
*
|
||||
* @param[in] window The window to make visible.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
@@ -3132,6 +3143,10 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window);
|
||||
* initially created. Set the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) to
|
||||
* disable this behavior.
|
||||
*
|
||||
* Also by default, windowed mode windows are focused when shown
|
||||
* with @ref glfwShowWindow. Set the
|
||||
* [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) to disable this behavior.
|
||||
*
|
||||
* __Do not use this function__ to steal focus from other applications unless
|
||||
* you are certain that is what the user wants. Focus stealing can be
|
||||
* extremely disruptive.
|
||||
@@ -3306,8 +3321,9 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
|
||||
*
|
||||
* The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
|
||||
* [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
|
||||
* [GLFW_FLOATING](@ref GLFW_FLOATING_attrib) and
|
||||
* [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib).
|
||||
* [GLFW_FLOATING](@ref GLFW_FLOATING_attrib),
|
||||
* [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and
|
||||
* [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib).
|
||||
*
|
||||
* Some of these attributes are ignored for full screen windows. The new
|
||||
* value will take effect if the window is later made windowed.
|
||||
|
1
src/external/glfw/src/CMakeLists.txt
vendored
1
src/external/glfw/src/CMakeLists.txt
vendored
@@ -163,4 +163,3 @@ if (GLFW_INSTALL)
|
||||
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
|
||||
LIBRARY DESTINATION "lib${LIB_SUFFIX}")
|
||||
endif()
|
||||
|
||||
|
5
src/external/glfw/src/input.c
vendored
5
src/external/glfw/src/input.c
vendored
@@ -32,7 +32,6 @@
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
// Internal key state used for sticky keys
|
||||
#define _GLFW_STICK 3
|
||||
@@ -1086,7 +1085,9 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
|
||||
|
||||
while (*c)
|
||||
{
|
||||
if (isxdigit(*c))
|
||||
if ((*c >= '0' && *c <= '9') ||
|
||||
(*c >= 'a' && *c <= 'f') ||
|
||||
(*c >= 'A' && *c <= 'F'))
|
||||
{
|
||||
char line[1024];
|
||||
|
||||
|
2
src/external/glfw/src/internal.h
vendored
2
src/external/glfw/src/internal.h
vendored
@@ -267,6 +267,7 @@ struct _GLFWwndconfig
|
||||
GLFWbool floating;
|
||||
GLFWbool maximized;
|
||||
GLFWbool centerCursor;
|
||||
GLFWbool focusOnShow;
|
||||
struct {
|
||||
GLFWbool retina;
|
||||
char frameName[256];
|
||||
@@ -372,6 +373,7 @@ struct _GLFWwindow
|
||||
GLFWbool decorated;
|
||||
GLFWbool autoIconify;
|
||||
GLFWbool floating;
|
||||
GLFWbool focusOnShow;
|
||||
GLFWbool shouldClose;
|
||||
void* userPointer;
|
||||
GLFWvidmode videoMode;
|
||||
|
4
src/external/glfw/src/win32_platform.h
vendored
4
src/external/glfw/src/win32_platform.h
vendored
@@ -242,7 +242,9 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
|
||||
#include "egl_context.h"
|
||||
#include "osmesa_context.h"
|
||||
|
||||
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
||||
#if !defined(_GLFW_WNDCLASSNAME)
|
||||
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
||||
#endif
|
||||
|
||||
#define _glfw_dlopen(name) LoadLibraryA(name)
|
||||
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
|
||||
|
13
src/external/glfw/src/window.c
vendored
13
src/external/glfw/src/window.c
vendored
@@ -201,6 +201,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
||||
window->decorated = wndconfig.decorated;
|
||||
window->autoIconify = wndconfig.autoIconify;
|
||||
window->floating = wndconfig.floating;
|
||||
window->focusOnShow = wndconfig.focusOnShow;
|
||||
window->cursorMode = GLFW_CURSOR_NORMAL;
|
||||
|
||||
window->minwidth = GLFW_DONT_CARE;
|
||||
@@ -267,6 +268,7 @@ void glfwDefaultWindowHints(void)
|
||||
_glfw.hints.window.focused = GLFW_TRUE;
|
||||
_glfw.hints.window.autoIconify = GLFW_TRUE;
|
||||
_glfw.hints.window.centerCursor = GLFW_TRUE;
|
||||
_glfw.hints.window.focusOnShow = GLFW_TRUE;
|
||||
|
||||
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
|
||||
// double buffered
|
||||
@@ -370,6 +372,9 @@ GLFWAPI void glfwWindowHint(int hint, int value)
|
||||
case GLFW_CENTER_CURSOR:
|
||||
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
case GLFW_FOCUS_ON_SHOW:
|
||||
_glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
case GLFW_CLIENT_API:
|
||||
_glfw.hints.context.client = value;
|
||||
return;
|
||||
@@ -755,7 +760,9 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle)
|
||||
return;
|
||||
|
||||
_glfwPlatformShowWindow(window);
|
||||
_glfwPlatformFocusWindow(window);
|
||||
|
||||
if (window->focusOnShow)
|
||||
_glfwPlatformFocusWindow(window);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
|
||||
@@ -810,6 +817,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
||||
return _glfwPlatformWindowMaximized(window);
|
||||
case GLFW_HOVERED:
|
||||
return _glfwPlatformWindowHovered(window);
|
||||
case GLFW_FOCUS_ON_SHOW:
|
||||
return window->focusOnShow;
|
||||
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
||||
return _glfwPlatformFramebufferTransparent(window);
|
||||
case GLFW_RESIZABLE:
|
||||
@@ -886,6 +895,8 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowFloating(window, value);
|
||||
}
|
||||
else if (attrib == GLFW_FOCUS_ON_SHOW)
|
||||
window->focusOnShow = value;
|
||||
else
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
|
||||
}
|
||||
|
5
src/external/glfw/src/x11_window.c
vendored
5
src/external/glfw/src/x11_window.c
vendored
@@ -2672,8 +2672,9 @@ void _glfwPlatformPollEvents(void)
|
||||
#if defined(__linux__)
|
||||
_glfwDetectJoystickConnectionLinux();
|
||||
#endif
|
||||
int count = XPending(_glfw.x11.display);
|
||||
while (count--)
|
||||
XPending(_glfw.x11.display);
|
||||
|
||||
while (XQLength(_glfw.x11.display))
|
||||
{
|
||||
XEvent event;
|
||||
XNextEvent(_glfw.x11.display, &event);
|
||||
|
2
src/external/jar_xm.h
vendored
2
src/external/jar_xm.h
vendored
@@ -2365,7 +2365,7 @@ static void jar_xm_tick(jar_xm_context_t* ctx) {
|
||||
float panning, volume;
|
||||
|
||||
panning = ch->panning +
|
||||
(ch->panning_envelope_panning - .5f) * (.5f - fabsf(ch->panning - .5f)) * 2.0f;
|
||||
(ch->panning_envelope_panning - .5f) * (.5f - fabs(ch->panning - .5f)) * 2.0f;
|
||||
|
||||
if(ch->tremor_on) {
|
||||
volume = .0f;
|
||||
|
@@ -1837,9 +1837,9 @@ void DrawBoundingBox(BoundingBox box, Color color)
|
||||
{
|
||||
Vector3 size;
|
||||
|
||||
size.x = fabsf(box.max.x - box.min.x);
|
||||
size.y = fabsf(box.max.y - box.min.y);
|
||||
size.z = fabsf(box.max.z - box.min.z);
|
||||
size.x = fabs(box.max.x - box.min.x);
|
||||
size.y = fabs(box.max.y - box.min.y);
|
||||
size.z = fabs(box.max.z - box.min.z);
|
||||
|
||||
Vector3 center = { box.min.x + size.x/2.0f, box.min.y + size.y/2.0f, box.min.z + size.z/2.0f };
|
||||
|
||||
@@ -2074,7 +2074,7 @@ RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight)
|
||||
|
||||
RayHitInfo result = { 0 };
|
||||
|
||||
if (fabsf(ray.direction.y) > EPSILON)
|
||||
if (fabs(ray.direction.y) > EPSILON)
|
||||
{
|
||||
float distance = (ray.position.y - groundHeight)/-ray.direction.y;
|
||||
|
||||
|
@@ -43,7 +43,7 @@
|
||||
* NOTE 2: Physac requires static C library linkage to avoid dependency on MinGW DLL (-static -lpthread)
|
||||
*
|
||||
* Use the following code to compile:
|
||||
* gcc -o $(NAME_PART).exe $(FILE_NAME) -s $(RAYLIB_DIR)\raylib\raylib_icon -static -lraylib -lpthread -lopengl32 -lgdi32 -std=c99
|
||||
* gcc -o $(NAME_PART).exe $(FILE_NAME) -s -static -lraylib -lpthread -lopengl32 -lgdi32 -std=c99
|
||||
*
|
||||
* VERY THANKS TO:
|
||||
* Ramon Santamaria (github: @raysan5)
|
||||
|
76
src/raylib.h
76
src/raylib.h
@@ -3,6 +3,8 @@
|
||||
* raylib - A simple and easy-to-use library to learn videogames programming (www.raylib.com)
|
||||
*
|
||||
* FEATURES:
|
||||
* - NO external dependencies, all required libraries included with raylib
|
||||
* - Multiple platforms support: Windows, Linux, FreeBSD, OpenBSD, NetBSD, DragonFly, MacOS, UWP, Android, Raspberry Pi, HTML5.
|
||||
* - Written in plain C code (C99) in PascalCase/camelCase notation
|
||||
* - Hardware accelerated with OpenGL (1.1, 2.1, 3.3 or ES2 - choose at compile)
|
||||
* - Unique OpenGL abstraction layer (usable as standalone module): [rlgl]
|
||||
@@ -12,10 +14,8 @@
|
||||
* - Flexible Materials system, supporting classic maps and PBR maps
|
||||
* - Shaders support, including Model shaders and Postprocessing shaders
|
||||
* - Powerful math module for Vector, Matrix and Quaternion operations: [raymath]
|
||||
* - Audio loading and playing with streaming support (WAV, OGG, FLAC, XM, MOD)
|
||||
* - Multiple platforms support: Windows, Linux, FreeBSD, MacOS, UWP, Android, Raspberry Pi, HTML5.
|
||||
* - Audio loading and playing with streaming support (WAV, OGG, MP3, FLAC, XM, MOD)
|
||||
* - VR stereo rendering with configurable HMD device parameters
|
||||
* - NO external dependencies, all required libraries included with raylib
|
||||
* - Complete bindings to LUA (raylib-lua) and Go (raylib-go)
|
||||
*
|
||||
* NOTES:
|
||||
@@ -33,14 +33,15 @@
|
||||
* stb_image_resize (Sean Barret) for image resizing algorythms [textures]
|
||||
* stb_image_write (Sean Barret) for image writting (PNG) [utils]
|
||||
* stb_truetype (Sean Barret) for ttf fonts loading [text]
|
||||
* stb_rect_pack (Sean Barret) for rectangles packing [text]
|
||||
* stb_vorbis (Sean Barret) for OGG audio loading [audio]
|
||||
* stb_perlin (Sean Barret) for Perlin noise image generation [textures]
|
||||
* par_shapes (Philip Rideout) for parametric 3d shapes generation [models]
|
||||
* jar_xm (Joshua Reisenauer) for XM audio module loading [audio]
|
||||
* jar_mod (Joshua Reisenauer) for MOD audio module loading [audio]
|
||||
* dr_flac (David Reid) for FLAC audio file loading [audio]
|
||||
* dr_mp3 (David Reid) for MP3 audio file loading [audio]
|
||||
* rgif (Charlie Tangora, Ramon Santamaria) for GIF recording [core]
|
||||
* tinfl for data decompression (DEFLATE algorithm) [rres]
|
||||
*
|
||||
*
|
||||
* LICENSE: zlib/libpng
|
||||
@@ -92,7 +93,7 @@
|
||||
#define FLAG_SHOW_LOGO 1 // Set to show raylib logo at startup
|
||||
#define FLAG_FULLSCREEN_MODE 2 // Set to run program in fullscreen
|
||||
#define FLAG_WINDOW_RESIZABLE 4 // Set to allow resizable window
|
||||
#define FLAG_WINDOW_DECORATED 8 // Set to show window decoration (frame and buttons)
|
||||
#define FLAG_WINDOW_UNDECORATED 8 // Set to disable window decoration (frame and buttons)
|
||||
#define FLAG_WINDOW_TRANSPARENT 16 // Set to allow transparent window
|
||||
#define FLAG_MSAA_4X_HINT 32 // Set to try enabling MSAA 4X
|
||||
#define FLAG_VSYNC_HINT 64 // Set to try enabling V-Sync on GPU
|
||||
@@ -331,6 +332,8 @@ typedef struct Vector4 {
|
||||
float w;
|
||||
} Vector4;
|
||||
|
||||
typedef Vector4 Quaternion;
|
||||
|
||||
// Matrix type (OpenGL style 4x4 - right handed, column major)
|
||||
typedef struct Matrix {
|
||||
float m0, m4, m8, m12;
|
||||
@@ -389,6 +392,7 @@ typedef struct CharInfo {
|
||||
int offsetX; // Character offset X when drawing
|
||||
int offsetY; // Character offset Y when drawing
|
||||
int advanceX; // Character advance position X
|
||||
unsigned char *data; // Character pixel data (grayscale)
|
||||
} CharInfo;
|
||||
|
||||
// Font type, includes texture and charSet array data
|
||||
@@ -539,12 +543,12 @@ typedef struct VrDeviceInfo {
|
||||
// Enumerators Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Trace log type
|
||||
typedef enum {
|
||||
typedef enum {
|
||||
LOG_INFO = 1,
|
||||
LOG_WARNING = 2,
|
||||
LOG_ERROR = 4,
|
||||
LOG_DEBUG = 8,
|
||||
LOG_OTHER = 16
|
||||
LOG_WARNING = 2,
|
||||
LOG_ERROR = 4,
|
||||
LOG_DEBUG = 8,
|
||||
LOG_OTHER = 16
|
||||
} LogType;
|
||||
|
||||
// Shader location point type
|
||||
@@ -636,16 +640,16 @@ typedef enum {
|
||||
} TextureFilterMode;
|
||||
|
||||
// Texture parameters: wrap mode
|
||||
typedef enum {
|
||||
WRAP_REPEAT = 0,
|
||||
WRAP_CLAMP,
|
||||
WRAP_MIRROR
|
||||
typedef enum {
|
||||
WRAP_REPEAT = 0,
|
||||
WRAP_CLAMP,
|
||||
WRAP_MIRROR
|
||||
} TextureWrapMode;
|
||||
|
||||
// Color blending modes (pre-defined)
|
||||
typedef enum {
|
||||
BLEND_ALPHA = 0,
|
||||
BLEND_ADDITIVE,
|
||||
typedef enum {
|
||||
BLEND_ALPHA = 0,
|
||||
BLEND_ADDITIVE,
|
||||
BLEND_MULTIPLIED
|
||||
} BlendMode;
|
||||
|
||||
@@ -899,6 +903,7 @@ RLAPI void UnloadImage(Image image);
|
||||
RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM)
|
||||
RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM)
|
||||
RLAPI Color *GetImageData(Image image); // Get pixel data from image as a Color struct array
|
||||
RLAPI Vector4 *GetImageDataNormalized(Image image); // Get pixel data from image as Vector4 array (float normalized)
|
||||
RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes (image or texture)
|
||||
RLAPI Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image
|
||||
RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data
|
||||
@@ -912,8 +917,9 @@ RLAPI void ImageAlphaClear(Image *image, Color color, float threshold);
|
||||
RLAPI void ImageAlphaCrop(Image *image, float threshold); // Crop image depending on alpha value
|
||||
RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel
|
||||
RLAPI void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle
|
||||
RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize and image (bilinear filtering)
|
||||
RLAPI void ImageResizeNN(Image *image,int newWidth,int newHeight); // Resize and image (Nearest-Neighbor scaling algorithm)
|
||||
RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (bilinear filtering)
|
||||
RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm)
|
||||
RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color color); // Resize canvas and fill with color
|
||||
RLAPI void ImageMipmaps(Image *image); // Generate all mipmap levels for a provided image
|
||||
RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
||||
RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font)
|
||||
@@ -924,11 +930,14 @@ RLAPI void ImageDrawText(Image *dst, Vector2 position, const char *text, int fon
|
||||
RLAPI void ImageDrawTextEx(Image *dst, Vector2 position, Font font, const char *text, float fontSize, float spacing, Color color); // Draw text (custom sprite font) within an image (destination)
|
||||
RLAPI void ImageFlipVertical(Image *image); // Flip image vertically
|
||||
RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally
|
||||
RLAPI void ImageRotateCW(Image *image); // Rotate image clockwise 90deg
|
||||
RLAPI void ImageRotateCCW(Image *image); // Rotate image counter-clockwise 90deg
|
||||
RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint
|
||||
RLAPI void ImageColorInvert(Image *image); // Modify image color: invert
|
||||
RLAPI void ImageColorGrayscale(Image *image); // Modify image color: grayscale
|
||||
RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100)
|
||||
RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255)
|
||||
RLAPI void ImageColorReplace(Image *image, Color color, Color replace); // Modify image color: replace color
|
||||
|
||||
// Image generation functions
|
||||
RLAPI Image GenImageColor(int width, int height, Color color); // Generate image: plain color
|
||||
@@ -951,29 +960,30 @@ RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint);
|
||||
RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters
|
||||
RLAPI void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle
|
||||
RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Font Loading and Text Drawing Functions (Module: text)
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
// Font loading/unloading functions
|
||||
RLAPI Font GetDefaultFont(void); // Get the default Font
|
||||
RLAPI Font LoadFont(const char *fileName); // Load Font from file into GPU memory (VRAM)
|
||||
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load Font from file with extended parameters
|
||||
RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM)
|
||||
RLAPI Font GetDefaultFont(void); // Get the default Font
|
||||
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
|
||||
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load font from file with extended parameters
|
||||
RLAPI CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, bool sdf); // Load font data for further use
|
||||
RLAPI Image GenImageFontAtlas(CharInfo *chars, int fontSize, int charsCount, int padding, int packMethod); // Generate image font atlas using chars info
|
||||
RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM)
|
||||
|
||||
// Text drawing functions
|
||||
RLAPI void DrawFPS(int posX, int posY); // Shows current FPS
|
||||
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
||||
RLAPI void DrawTextEx(Font font, const char* text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using Font and additional parameters
|
||||
RLAPI void DrawFPS(int posX, int posY); // Shows current FPS
|
||||
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
||||
RLAPI void DrawTextEx(Font font, const char* text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
||||
|
||||
// Text misc. functions
|
||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
||||
RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed'
|
||||
RLAPI const char *SubText(const char *text, int position, int length); // Get a piece of a text string
|
||||
RLAPI int GetGlyphIndex(Font font, int character); // Returns index position for a unicode character on sprite font
|
||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
||||
RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed'
|
||||
RLAPI const char *SubText(const char *text, int position, int length); // Get a piece of a text string
|
||||
RLAPI int GetGlyphIndex(Font font, int character); // Get index position for a unicode character on sprite font
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Basic 3d Shapes Drawing Functions (Module: models)
|
||||
@@ -1013,7 +1023,7 @@ RLAPI void ExportMesh(const char *fileName, Mesh mesh);
|
||||
|
||||
// Mesh manipulation functions
|
||||
RLAPI BoundingBox MeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits
|
||||
RLAPI void MeshTangents(Mesh *mesh); // Compute mesh tangents
|
||||
RLAPI void MeshTangents(Mesh *mesh); // Compute mesh tangents
|
||||
RLAPI void MeshBinormals(Mesh *mesh); // Compute mesh binormals
|
||||
|
||||
// Mesh generation functions
|
||||
|
Binary file not shown.
156
src/raymath.h
156
src/raymath.h
@@ -12,9 +12,9 @@
|
||||
* #define RAYMATH_HEADER_ONLY
|
||||
* Define static inline functions code, so #include header suffices for use.
|
||||
* This may use up lots of memory.
|
||||
*
|
||||
*
|
||||
* #define RAYMATH_STANDALONE
|
||||
* Avoid raylib.h header inclusion in this file.
|
||||
* Avoid raylib.h header inclusion in this file.
|
||||
* Vector3 and Matrix data types are defined internally in raymath module.
|
||||
*
|
||||
*
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
// Return float vector for Vector3
|
||||
#ifndef Vector3ToFloat
|
||||
#define Vector3ToFloat(vec) (Vector3ToFloatV(vec).v)
|
||||
#define Vector3ToFloat(vec) (Vector3ToFloatV(vec).v)
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
@@ -114,6 +114,14 @@
|
||||
float y;
|
||||
float z;
|
||||
} Vector3;
|
||||
|
||||
// Quaternion type
|
||||
typedef struct Quaternion {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
} Quaternion;
|
||||
|
||||
// Matrix type (OpenGL style 4x4 - right handed, column major)
|
||||
typedef struct Matrix {
|
||||
@@ -128,14 +136,6 @@
|
||||
typedef struct float3 { float v[3]; } float3;
|
||||
typedef struct float16 { float v[16]; } float16;
|
||||
|
||||
// Quaternion type
|
||||
typedef struct Quaternion {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
} Quaternion;
|
||||
|
||||
#include <math.h> // Required for: sinf(), cosf(), tan(), fabs()
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
@@ -143,7 +143,7 @@ typedef struct Quaternion {
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Clamp float value
|
||||
RMDEF float Clamp(float value, float min, float max)
|
||||
RMDEF float Clamp(float value, float min, float max)
|
||||
{
|
||||
const float res = value < min ? min : value;
|
||||
return res > max ? max : res;
|
||||
@@ -154,15 +154,15 @@ RMDEF float Clamp(float value, float min, float max)
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Vector with components value 0.0f
|
||||
RMDEF Vector2 Vector2Zero(void)
|
||||
{
|
||||
RMDEF Vector2 Vector2Zero(void)
|
||||
{
|
||||
Vector2 result = { 0.0f, 0.0f };
|
||||
return result;
|
||||
}
|
||||
|
||||
// Vector with components value 1.0f
|
||||
RMDEF Vector2 Vector2One(void)
|
||||
{
|
||||
RMDEF Vector2 Vector2One(void)
|
||||
{
|
||||
Vector2 result = { 1.0f, 1.0f };
|
||||
return result;
|
||||
}
|
||||
@@ -243,31 +243,31 @@ RMDEF Vector2 Vector2Normalize(Vector2 v)
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Vector with components value 0.0f
|
||||
RMDEF Vector3 Vector3Zero(void)
|
||||
{
|
||||
RMDEF Vector3 Vector3Zero(void)
|
||||
{
|
||||
Vector3 result = { 0.0f, 0.0f, 0.0f };
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Vector with components value 1.0f
|
||||
RMDEF Vector3 Vector3One(void)
|
||||
{
|
||||
RMDEF Vector3 Vector3One(void)
|
||||
{
|
||||
Vector3 result = { 1.0f, 1.0f, 1.0f };
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Add two vectors
|
||||
RMDEF Vector3 Vector3Add(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
Vector3 result = { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Substract two vectors
|
||||
RMDEF Vector3 Vector3Subtract(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
Vector3 result = { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Multiply vector by scalar
|
||||
@@ -279,7 +279,7 @@ RMDEF Vector3 Vector3Multiply(Vector3 v, float scalar)
|
||||
|
||||
// Multiply vector by vector
|
||||
RMDEF Vector3 Vector3MultiplyV(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
{
|
||||
Vector3 result = { v1.x*v2.x, v1.y*v2.y, v1.z*v2.z };
|
||||
return result;
|
||||
}
|
||||
@@ -296,17 +296,17 @@ RMDEF Vector3 Vector3Perpendicular(Vector3 v)
|
||||
{
|
||||
Vector3 result = { 0 };
|
||||
|
||||
float min = fabsf(v.x);
|
||||
float min = fabs(v.x);
|
||||
Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f};
|
||||
|
||||
if (fabsf(v.y) < min)
|
||||
if (fabs(v.y) < min)
|
||||
{
|
||||
min = fabsf(v.y);
|
||||
min = fabs(v.y);
|
||||
Vector3 tmp = {0.0f, 1.0f, 0.0f};
|
||||
cardinalAxis = tmp;
|
||||
}
|
||||
|
||||
if (fabsf(v.z) < min)
|
||||
if (fabs(v.z) < min)
|
||||
{
|
||||
Vector3 tmp = {0.0f, 0.0f, 1.0f};
|
||||
cardinalAxis = tmp;
|
||||
@@ -359,7 +359,7 @@ RMDEF Vector3 Vector3Negate(Vector3 v)
|
||||
RMDEF Vector3 Vector3Normalize(Vector3 v)
|
||||
{
|
||||
Vector3 result = v;
|
||||
|
||||
|
||||
float length, ilength;
|
||||
length = Vector3Length(v);
|
||||
if (length == 0.0f) length = 1.0f;
|
||||
@@ -394,10 +394,22 @@ RMDEF Vector3 Vector3Transform(Vector3 v, Matrix mat)
|
||||
result.x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12;
|
||||
result.y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13;
|
||||
result.z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14;
|
||||
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// Transform a vector by quaternion rotation
|
||||
RMDEF Vector3 Vector3RotateByQuaternion(Vector3 v, Quaternion q)
|
||||
{
|
||||
Vector3 result = { 0 };
|
||||
|
||||
result.x = v.x*(q.x*q.x + q.w*q.w - q.y*q.y - q.z*q.z) + v.y*(2*q.x*q.y - 2*q.w*q.z) + v.z*(2*q.x*q.z + 2*q.w*q.y);
|
||||
result.y = v.x*(2*q.w*q.z + 2*q.x*q.y) + v.y*(q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z) + v.z*(-2*q.w*q.x + 2*q.y*q.z);
|
||||
result.z = v.x*(-2*q.w*q.y + 2*q.x*q.z) + v.y*(2*q.w*q.x + 2*q.y*q.z)+ v.z*(q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculate linear interpolation between two vectors
|
||||
RMDEF Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount)
|
||||
{
|
||||
@@ -432,11 +444,11 @@ RMDEF Vector3 Vector3Reflect(Vector3 v, Vector3 normal)
|
||||
RMDEF Vector3 Vector3Min(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
Vector3 result = { 0 };
|
||||
|
||||
|
||||
result.x = fminf(v1.x, v2.x);
|
||||
result.y = fminf(v1.y, v2.y);
|
||||
result.z = fminf(v1.z, v2.z);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -444,11 +456,11 @@ RMDEF Vector3 Vector3Min(Vector3 v1, Vector3 v2)
|
||||
RMDEF Vector3 Vector3Max(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
Vector3 result = { 0 };
|
||||
|
||||
|
||||
result.x = fmaxf(v1.x, v2.x);
|
||||
result.y = fmaxf(v1.y, v2.y);
|
||||
result.z = fmaxf(v1.z, v2.z);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -457,7 +469,7 @@ RMDEF Vector3 Vector3Max(Vector3 v1, Vector3 v2)
|
||||
RMDEF Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c)
|
||||
{
|
||||
//Vector v0 = b - a, v1 = c - a, v2 = p - a;
|
||||
|
||||
|
||||
Vector3 v0 = Vector3Subtract(b, a);
|
||||
Vector3 v1 = Vector3Subtract(c, a);
|
||||
Vector3 v2 = Vector3Subtract(p, a);
|
||||
@@ -466,15 +478,15 @@ RMDEF Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c)
|
||||
float d11 = Vector3DotProduct(v1, v1);
|
||||
float d20 = Vector3DotProduct(v2, v0);
|
||||
float d21 = Vector3DotProduct(v2, v1);
|
||||
|
||||
|
||||
float denom = d00*d11 - d01*d01;
|
||||
|
||||
|
||||
Vector3 result = { 0 };
|
||||
|
||||
|
||||
result.y = (d11*d20 - d01*d21)/denom;
|
||||
result.z = (d00*d21 - d01*d20)/denom;
|
||||
result.x = 1.0f - (result.z + result.y);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -598,7 +610,7 @@ RMDEF Matrix MatrixInvert(Matrix mat)
|
||||
RMDEF Matrix MatrixNormalize(Matrix mat)
|
||||
{
|
||||
Matrix result = { 0 };
|
||||
|
||||
|
||||
float det = MatrixDeterminant(mat);
|
||||
|
||||
result.m0 = mat.m0/det;
|
||||
@@ -617,15 +629,15 @@ RMDEF Matrix MatrixNormalize(Matrix mat)
|
||||
result.m13 = mat.m13/det;
|
||||
result.m14 = mat.m14/det;
|
||||
result.m15 = mat.m15/det;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns identity matrix
|
||||
RMDEF Matrix MatrixIdentity(void)
|
||||
{
|
||||
Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
@@ -685,9 +697,9 @@ RMDEF Matrix MatrixSubstract(Matrix left, Matrix right)
|
||||
// Returns translation matrix
|
||||
RMDEF Matrix MatrixTranslate(float x, float y, float z)
|
||||
{
|
||||
Matrix result = { 1.0f, 0.0f, 0.0f, x,
|
||||
0.0f, 1.0f, 0.0f, y,
|
||||
0.0f, 0.0f, 1.0f, z,
|
||||
Matrix result = { 1.0f, 0.0f, 0.0f, x,
|
||||
0.0f, 1.0f, 0.0f, y,
|
||||
0.0f, 0.0f, 1.0f, z,
|
||||
0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
return result;
|
||||
@@ -724,12 +736,12 @@ RMDEF Matrix MatrixRotate(Vector3 axis, float angle)
|
||||
result.m5 = y*y*t + cosres;
|
||||
result.m6 = z*y*t + x*sinres;
|
||||
result.m7 = 0.0f;
|
||||
|
||||
|
||||
result.m8 = x*z*t + y*sinres;
|
||||
result.m9 = y*z*t - x*sinres;
|
||||
result.m10 = z*z*t + cosres;
|
||||
result.m11 = 0.0f;
|
||||
|
||||
|
||||
result.m12 = 0.0f;
|
||||
result.m13 = 0.0f;
|
||||
result.m14 = 0.0f;
|
||||
@@ -789,9 +801,9 @@ RMDEF Matrix MatrixRotateZ(float angle)
|
||||
// Returns scaling matrix
|
||||
RMDEF Matrix MatrixScale(float x, float y, float z)
|
||||
{
|
||||
Matrix result = { x, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, y, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, z, 0.0f,
|
||||
Matrix result = { x, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, y, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, z, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
return result;
|
||||
@@ -859,11 +871,11 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top,
|
||||
// NOTE: Angle should be provided in radians
|
||||
RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far)
|
||||
{
|
||||
double top = near*tan(fovy*0.5);
|
||||
double top = near*tan(fovy*0.5);
|
||||
double right = top*aspect;
|
||||
Matrix result = MatrixFrustum(-right, right, -top, top, near, far);
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns orthographic projection matrix
|
||||
@@ -906,7 +918,7 @@ RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up)
|
||||
x = Vector3Normalize(x);
|
||||
Vector3 y = Vector3CrossProduct(z, x);
|
||||
y = Vector3Normalize(y);
|
||||
|
||||
|
||||
result.m0 = x.x;
|
||||
result.m1 = x.y;
|
||||
result.m2 = x.z;
|
||||
@@ -976,7 +988,7 @@ RMDEF float QuaternionLength(Quaternion q)
|
||||
RMDEF Quaternion QuaternionNormalize(Quaternion q)
|
||||
{
|
||||
Quaternion result = { 0 };
|
||||
|
||||
|
||||
float length, ilength;
|
||||
length = QuaternionLength(q);
|
||||
if (length == 0.0f) length = 1.0f;
|
||||
@@ -986,7 +998,7 @@ RMDEF Quaternion QuaternionNormalize(Quaternion q)
|
||||
result.y = q.y*ilength;
|
||||
result.z = q.z*ilength;
|
||||
result.w = q.w*ilength;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -996,17 +1008,17 @@ RMDEF Quaternion QuaternionInvert(Quaternion q)
|
||||
Quaternion result = q;
|
||||
float length = QuaternionLength(q);
|
||||
float lengthSq = length*length;
|
||||
|
||||
|
||||
if (lengthSq != 0.0)
|
||||
{
|
||||
float i = 1.0f/lengthSq;
|
||||
|
||||
|
||||
result.x *= -i;
|
||||
result.y *= -i;
|
||||
result.z *= -i;
|
||||
result.w *= i;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1044,7 +1056,7 @@ RMDEF Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount)
|
||||
{
|
||||
Quaternion result = QuaternionLerp(q1, q2, amount);
|
||||
result = QuaternionNormalize(result);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1096,13 +1108,13 @@ RMDEF Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to)
|
||||
result.y = cross.y;
|
||||
result.z = cross.y;
|
||||
result.w = 1.0f + cos2Theta; // NOTE: Added QuaternioIdentity()
|
||||
|
||||
|
||||
// Normalize to essentially nlerp the original and identity to 0.5
|
||||
result = QuaternionNormalize(result);
|
||||
|
||||
result = QuaternionNormalize(result);
|
||||
|
||||
// Above lines are equivalent to:
|
||||
//Quaternion result = QuaternionNlerp(q, QuaternionIdentity(), 0.5f);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1172,7 +1184,7 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q)
|
||||
float x2 = x + x;
|
||||
float y2 = y + y;
|
||||
float z2 = z + z;
|
||||
|
||||
|
||||
float length = QuaternionLength(q);
|
||||
float lengthSquared = length*length;
|
||||
|
||||
@@ -1204,7 +1216,7 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q)
|
||||
result.m13 = 0.0f;
|
||||
result.m14 = 0.0f;
|
||||
result.m15 = 1.0f;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1219,7 +1231,7 @@ RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)
|
||||
angle *= 0.5f;
|
||||
|
||||
axis = Vector3Normalize(axis);
|
||||
|
||||
|
||||
float sinres = sinf(angle);
|
||||
float cosres = cosf(angle);
|
||||
|
||||
@@ -1277,7 +1289,7 @@ RMDEF Quaternion QuaternionFromEuler(float roll, float pitch, float yaw)
|
||||
q.y = x0*y1*z0 + x1*y0*z1;
|
||||
q.z = x0*y0*z1 - x1*y1*z0;
|
||||
q.w = x0*y0*z0 + x1*y1*z1;
|
||||
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
@@ -1300,9 +1312,9 @@ RMDEF Vector3 QuaternionToEuler(Quaternion q)
|
||||
|
||||
// yaw (z-axis rotation)
|
||||
float z0 = 2.0f*(q.w*q.z + q.x*q.y);
|
||||
float z1 = 1.0f - 2.0f*(q.y*q.y + q.z*q.z);
|
||||
float z1 = 1.0f - 2.0f*(q.y*q.y + q.z*q.z);
|
||||
result.z = atan2f(z0, z1)*RAD2DEG;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1315,7 +1327,7 @@ RMDEF Quaternion QuaternionTransform(Quaternion q, Matrix mat)
|
||||
result.y = mat.m1*q.x + mat.m5*q.y + mat.m9*q.z + mat.m13*q.w;
|
||||
result.z = mat.m2*q.x + mat.m6*q.y + mat.m10*q.z + mat.m14*q.w;
|
||||
result.w = mat.m3*q.x + mat.m7*q.y + mat.m11*q.z + mat.m15*q.w;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@@ -37,7 +37,7 @@
|
||||
#define _GLFW_X11
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
|
||||
#define _GLFW_X11
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
@@ -91,7 +91,7 @@
|
||||
#include "external/glfw/src/osmesa_context.c"
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__) || defined(__DragonFly__)
|
||||
#include "external/glfw/src/x11_init.c"
|
||||
#include "external/glfw/src/x11_monitor.c"
|
||||
#include "external/glfw/src/x11_window.c"
|
||||
|
196
src/rlgl.c
196
src/rlgl.c
@@ -2,8 +2,8 @@
|
||||
*
|
||||
* rlgl - raylib OpenGL abstraction layer
|
||||
*
|
||||
* rlgl is a wrapper for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) to
|
||||
* pseudo-OpenGL 1.1 style functions (rlVertex, rlTranslate, rlRotate...).
|
||||
* rlgl is a wrapper for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) to
|
||||
* pseudo-OpenGL 1.1 style functions (rlVertex, rlTranslate, rlRotate...).
|
||||
*
|
||||
* When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal
|
||||
* VBO buffers (and VAOs if available). It requires calling 3 functions:
|
||||
@@ -657,7 +657,7 @@ void rlEnd(void)
|
||||
// as well as depth buffer bit-depth (16bit or 24bit or 32bit)
|
||||
// Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits)
|
||||
currentDepth += (1.0f/20000.0f);
|
||||
|
||||
|
||||
// Verify internal buffers limits
|
||||
// NOTE: This check is combined with usage of rlCheckBufferLimit()
|
||||
if ((lines.vCounter/2 >= MAX_LINES_BATCH - 2) ||
|
||||
@@ -829,7 +829,7 @@ void rlEnableTexture(unsigned int id)
|
||||
if (draws[drawsCounter - 1].textureId != id)
|
||||
{
|
||||
if (draws[drawsCounter - 1].vertexCount > 0) drawsCounter++;
|
||||
|
||||
|
||||
if (drawsCounter >= MAX_DRAWS_BY_TEXTURE)
|
||||
{
|
||||
rlglDraw();
|
||||
@@ -1126,7 +1126,7 @@ void rlglInit(int width, int height)
|
||||
// Check NPOT textures support
|
||||
// NOTE: Only check on OpenGL ES, OpenGL 3.3 has NPOT textures full support as core feature
|
||||
if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) texNPOTSupported = true;
|
||||
|
||||
|
||||
// Check texture float support
|
||||
if (strcmp(extList[i], (const char *)"GL_OES_texture_float") == 0) texFloatSupported = true;
|
||||
#endif
|
||||
@@ -1158,7 +1158,7 @@ void rlglInit(int width, int height)
|
||||
|
||||
// Clamp mirror wrap mode supported
|
||||
if (strcmp(extList[i], (const char *)"GL_EXT_texture_mirror_clamp") == 0) texClampMirrorSupported = true;
|
||||
|
||||
|
||||
// Debug marker support
|
||||
if(strcmp(extList[i], (const char *)"GL_EXT_debug_marker") == 0) debugMarkerSupported = true;
|
||||
}
|
||||
@@ -1271,9 +1271,9 @@ void rlglClose(void)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
UnloadShaderDefault(); // Unload default shader
|
||||
UnloadBuffersDefault(); // Unload default buffers (lines, triangles, quads)
|
||||
UnloadBuffersDefault(); // Unload default buffers (lines, triangles, quads)
|
||||
glDeleteTextures(1, &whiteTexture); // Unload default texture
|
||||
|
||||
|
||||
TraceLog(LOG_INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture);
|
||||
|
||||
free(draws);
|
||||
@@ -1438,30 +1438,30 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
|
||||
#endif
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
|
||||
|
||||
int mipWidth = width;
|
||||
int mipHeight = height;
|
||||
int mipOffset = 0; // Mipmap data offset
|
||||
|
||||
|
||||
TraceLog(LOG_DEBUG, "Load texture from data memory address: 0x%x", data);
|
||||
|
||||
|
||||
// Load the different mipmap levels
|
||||
for (int i = 0; i < mipmapCount; i++)
|
||||
{
|
||||
unsigned int mipSize = GetPixelDataSize(mipWidth, mipHeight, format);
|
||||
|
||||
|
||||
int glInternalFormat, glFormat, glType;
|
||||
GetGlFormats(format, &glInternalFormat, &glFormat, &glType);
|
||||
|
||||
|
||||
TraceLog(LOG_DEBUG, "Load mipmap level %i (%i x %i), size: %i, offset: %i", i, mipWidth, mipHeight, mipSize, mipOffset);
|
||||
|
||||
|
||||
if (glInternalFormat != -1)
|
||||
{
|
||||
if (format < COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, glFormat, glType, (unsigned char *)data + mipOffset);
|
||||
#if !defined(GRAPHICS_API_OPENGL_11)
|
||||
#if !defined(GRAPHICS_API_OPENGL_11)
|
||||
else glCompressedTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, mipSize, (unsigned char *)data + mipOffset);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_33)
|
||||
if (format == UNCOMPRESSED_GRAYSCALE)
|
||||
{
|
||||
@@ -1479,11 +1479,11 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
mipWidth /= 2;
|
||||
mipHeight /= 2;
|
||||
mipOffset += mipSize;
|
||||
|
||||
|
||||
// Security check for NPOT textures
|
||||
if (mipWidth < 1) mipWidth = 1;
|
||||
if (mipHeight < 1) mipHeight = 1;
|
||||
@@ -1539,7 +1539,7 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
|
||||
void rlUpdateTexture(unsigned int id, int width, int height, int format, const void *data)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
|
||||
|
||||
int glInternalFormat, glFormat, glType;
|
||||
GetGlFormats(format, &glInternalFormat, &glFormat, &glType);
|
||||
|
||||
@@ -1671,7 +1671,7 @@ void rlGenerateMipmaps(Texture2D *texture)
|
||||
{
|
||||
// Retrieve texture data from VRAM
|
||||
void *data = rlReadTexturePixels(*texture);
|
||||
|
||||
|
||||
// NOTE: data size is reallocated to fit mipmaps data
|
||||
// NOTE: CPU mipmap generation only supports RGBA 32bit data
|
||||
int mipmapCount = GenerateMipmaps(data, texture->width, texture->height);
|
||||
@@ -1696,7 +1696,7 @@ void rlGenerateMipmaps(Texture2D *texture)
|
||||
|
||||
texture->mipmaps = mipmapCount + 1;
|
||||
free(data); // Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data
|
||||
|
||||
|
||||
TraceLog(LOG_WARNING, "[TEX ID %i] Mipmaps [%i] generated manually on CPU side", texture->id, texture->mipmaps);
|
||||
}
|
||||
else TraceLog(LOG_WARNING, "[TEX ID %i] Mipmaps could not be generated for texture format", texture->id);
|
||||
@@ -1943,27 +1943,27 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform)
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
// Bind shader program
|
||||
glUseProgram(material.shader.id);
|
||||
glUseProgram(material.shader.id);
|
||||
|
||||
// Matrices and other values required by shader
|
||||
//-----------------------------------------------------
|
||||
// Calculate and send to shader model matrix (used by PBR shader)
|
||||
if (material.shader.locs[LOC_MATRIX_MODEL] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_MODEL], transform);
|
||||
|
||||
|
||||
// Upload to shader material.colDiffuse
|
||||
if (material.shader.locs[LOC_COLOR_DIFFUSE] != -1)
|
||||
glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255.0f,
|
||||
(float)material.maps[MAP_DIFFUSE].color.g/255.0f,
|
||||
(float)material.maps[MAP_DIFFUSE].color.b/255.0f,
|
||||
glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255.0f,
|
||||
(float)material.maps[MAP_DIFFUSE].color.g/255.0f,
|
||||
(float)material.maps[MAP_DIFFUSE].color.b/255.0f,
|
||||
(float)material.maps[MAP_DIFFUSE].color.a/255.0f);
|
||||
|
||||
// Upload to shader material.colSpecular (if available)
|
||||
if (material.shader.locs[LOC_COLOR_SPECULAR] != -1)
|
||||
glUniform4f(material.shader.locs[LOC_COLOR_SPECULAR], (float)material.maps[MAP_SPECULAR].color.r/255.0f,
|
||||
(float)material.maps[MAP_SPECULAR].color.g/255.0f,
|
||||
(float)material.maps[MAP_SPECULAR].color.b/255.0f,
|
||||
if (material.shader.locs[LOC_COLOR_SPECULAR] != -1)
|
||||
glUniform4f(material.shader.locs[LOC_COLOR_SPECULAR], (float)material.maps[MAP_SPECULAR].color.r/255.0f,
|
||||
(float)material.maps[MAP_SPECULAR].color.g/255.0f,
|
||||
(float)material.maps[MAP_SPECULAR].color.b/255.0f,
|
||||
(float)material.maps[MAP_SPECULAR].color.a/255.0f);
|
||||
|
||||
|
||||
if (material.shader.locs[LOC_MATRIX_VIEW] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_VIEW], modelview);
|
||||
if (material.shader.locs[LOC_MATRIX_PROJECTION] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_PROJECTION], projection);
|
||||
|
||||
@@ -2054,7 +2054,7 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform)
|
||||
#if defined(SUPPORT_VR_SIMULATOR)
|
||||
if (vrStereoRender) eyesCount = 2;
|
||||
#endif
|
||||
|
||||
|
||||
for (int eye = 0; eye < eyesCount; eye++)
|
||||
{
|
||||
if (eyesCount == 1) modelview = matModelView;
|
||||
@@ -2072,7 +2072,7 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform)
|
||||
if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw
|
||||
else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount);
|
||||
}
|
||||
|
||||
|
||||
// Unbind all binded texture maps
|
||||
for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
|
||||
{
|
||||
@@ -2168,7 +2168,7 @@ void *rlReadTexturePixels(Texture2D texture)
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
|
||||
// Other texture info: GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE
|
||||
*/
|
||||
|
||||
|
||||
// NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding.
|
||||
// Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting.
|
||||
// GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.)
|
||||
@@ -2178,7 +2178,7 @@ void *rlReadTexturePixels(Texture2D texture)
|
||||
int glInternalFormat, glFormat, glType;
|
||||
GetGlFormats(texture.format, &glInternalFormat, &glFormat, &glType);
|
||||
unsigned int size = GetPixelDataSize(texture.width, texture.height, texture.format);
|
||||
|
||||
|
||||
if ((glInternalFormat != -1) && (texture.format < COMPRESSED_DXT1_RGB))
|
||||
{
|
||||
pixels = (unsigned char *)malloc(size);
|
||||
@@ -2224,7 +2224,7 @@ void *rlReadTexturePixels(Texture2D texture)
|
||||
//glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
//glDisable(GL_BLEND);
|
||||
|
||||
|
||||
glViewport(0, 0, texture.width, texture.height);
|
||||
rlOrtho(0.0, texture.width, texture.height, 0.0, 0.0, 1.0);
|
||||
|
||||
@@ -2234,17 +2234,17 @@ void *rlReadTexturePixels(Texture2D texture)
|
||||
GenDrawQuad();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glUseProgram(0);
|
||||
|
||||
|
||||
pixels = (unsigned char *)malloc(texture.width*texture.height*4*sizeof(unsigned char));
|
||||
|
||||
glReadPixels(0, 0, texture.width, texture.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Bind framebuffer 0, which means render to back buffer
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
|
||||
// Reset viewport dimensions to default
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
|
||||
#endif // GET_TEXTURE_FBO_OPTION
|
||||
|
||||
// Clean up temporal fbo
|
||||
@@ -2349,9 +2349,9 @@ Shader LoadShader(const char *vsFileName, const char *fsFileName)
|
||||
|
||||
if (vsFileName != NULL) vShaderStr = LoadText(vsFileName);
|
||||
if (fsFileName != NULL) fShaderStr = LoadText(fsFileName);
|
||||
|
||||
|
||||
shader = LoadShaderCode(vShaderStr, fShaderStr);
|
||||
|
||||
|
||||
if (vShaderStr != NULL) free(vShaderStr);
|
||||
if (fShaderStr != NULL) free(fShaderStr);
|
||||
|
||||
@@ -2366,16 +2366,16 @@ Shader LoadShaderCode(char *vsCode, char *fsCode)
|
||||
|
||||
// NOTE: All locations must be reseted to -1 (no location)
|
||||
for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
|
||||
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
unsigned int vertexShaderId = defaultVShaderId;
|
||||
unsigned int fragmentShaderId = defaultFShaderId;
|
||||
|
||||
|
||||
if (vsCode != NULL) vertexShaderId = CompileShader(vsCode, GL_VERTEX_SHADER);
|
||||
if (fsCode != NULL) fragmentShaderId = CompileShader(fsCode, GL_FRAGMENT_SHADER);
|
||||
|
||||
|
||||
if ((vertexShaderId == defaultVShaderId) && (fragmentShaderId == defaultFShaderId)) shader = defaultShader;
|
||||
else
|
||||
else
|
||||
{
|
||||
shader.id = LoadShaderProgram(vertexShaderId, fragmentShaderId);
|
||||
|
||||
@@ -2387,17 +2387,17 @@ Shader LoadShaderCode(char *vsCode, char *fsCode)
|
||||
TraceLog(LOG_WARNING, "Custom shader could not be loaded");
|
||||
shader = defaultShader;
|
||||
}
|
||||
|
||||
|
||||
// After shader loading, we TRY to set default location names
|
||||
if (shader.id > 0) SetShaderDefaultLocations(&shader);
|
||||
}
|
||||
|
||||
|
||||
// Get available shader uniforms
|
||||
// NOTE: This information is useful for debug...
|
||||
int uniformCount = -1;
|
||||
|
||||
|
||||
glGetProgramiv(shader.id, GL_ACTIVE_UNIFORMS, &uniformCount);
|
||||
|
||||
|
||||
for(int i = 0; i < uniformCount; i++)
|
||||
{
|
||||
int namelen = -1;
|
||||
@@ -2407,16 +2407,16 @@ Shader LoadShaderCode(char *vsCode, char *fsCode)
|
||||
|
||||
// Get the name of the uniforms
|
||||
glGetActiveUniform(shader.id, i,sizeof(name) - 1, &namelen, &num, &type, name);
|
||||
|
||||
|
||||
name[namelen] = 0;
|
||||
|
||||
// Get the location of the named uniform
|
||||
GLuint location = glGetUniformLocation(shader.id, name);
|
||||
|
||||
|
||||
TraceLog(LOG_DEBUG, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
@@ -2524,7 +2524,7 @@ void SetMatrixModelview(Matrix view)
|
||||
}
|
||||
|
||||
// Return internal modelview matrix
|
||||
Matrix GetMatrixModelview()
|
||||
Matrix GetMatrixModelview()
|
||||
{
|
||||
Matrix matrix = MatrixIdentity();
|
||||
#if defined(GRAPHICS_API_OPENGL_11)
|
||||
@@ -2541,16 +2541,16 @@ Matrix GetMatrixModelview()
|
||||
Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size)
|
||||
{
|
||||
Texture2D cubemap = { 0 };
|
||||
#if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
#if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
// NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader
|
||||
// Other locations should be setup externally in shader before calling the function
|
||||
|
||||
|
||||
// Set up depth face culling and cubemap seamless
|
||||
glDisable(GL_CULL_FACE);
|
||||
#if defined(GRAPHICS_API_OPENGL_33)
|
||||
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); // Flag not supported on OpenGL ES 2.0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Setup framebuffer
|
||||
unsigned int fbo, rbo;
|
||||
@@ -2565,7 +2565,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size)
|
||||
// NOTE: faces are stored with 16 bit floating point values
|
||||
glGenTextures(1, &cubemap.id);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id);
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL);
|
||||
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);
|
||||
@@ -2607,7 +2607,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size)
|
||||
|
||||
// Unbind framebuffer and textures
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
|
||||
// Reset viewport dimensions to default
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
//glEnable(GL_CULL_FACE);
|
||||
@@ -2623,11 +2623,11 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size)
|
||||
Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size)
|
||||
{
|
||||
Texture2D irradiance = { 0 };
|
||||
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
// NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader
|
||||
// Other locations should be setup externally in shader before calling the function
|
||||
|
||||
|
||||
// Setup framebuffer
|
||||
unsigned int fbo, rbo;
|
||||
glGenFramebuffers(1, &fbo);
|
||||
@@ -2636,18 +2636,18 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size)
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
|
||||
|
||||
|
||||
// Create an irradiance cubemap, and re-scale capture FBO to irradiance scale
|
||||
glGenTextures(1, &irradiance.id);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, irradiance.id);
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL);
|
||||
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_R, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
|
||||
// Create projection (transposed) and different views for each face
|
||||
Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, 0.01, 1000.0);
|
||||
//MatrixTranspose(&fboProjection);
|
||||
@@ -2680,7 +2680,7 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size)
|
||||
|
||||
// Unbind framebuffer and textures
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
|
||||
// Reset viewport dimensions to default
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
@@ -2695,13 +2695,13 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size)
|
||||
Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size)
|
||||
{
|
||||
Texture2D prefilter = { 0 };
|
||||
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
// NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader
|
||||
// Other locations should be setup externally in shader before calling the function
|
||||
// TODO: Locations should be taken out of this function... too shader dependant...
|
||||
int roughnessLoc = GetShaderLocation(shader, "roughness");
|
||||
|
||||
|
||||
// Setup framebuffer
|
||||
unsigned int fbo, rbo;
|
||||
glGenFramebuffers(1, &fbo);
|
||||
@@ -2710,11 +2710,11 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size)
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
|
||||
|
||||
|
||||
// Create a prefiltered HDR environment map
|
||||
glGenTextures(1, &prefilter.id);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, prefilter.id);
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL);
|
||||
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);
|
||||
@@ -2724,7 +2724,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size)
|
||||
|
||||
// Generate mipmaps for the prefiltered HDR texture
|
||||
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||
|
||||
|
||||
// Create projection (transposed) and different views for each face
|
||||
Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, 0.01, 1000.0);
|
||||
//MatrixTranspose(&fboProjection);
|
||||
@@ -2744,7 +2744,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size)
|
||||
SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_PROJECTION], fboProjection);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
|
||||
#define MAX_MIPMAP_LEVELS 5 // Max number of prefilter texture mipmaps
|
||||
|
||||
for (unsigned int mip = 0; mip < MAX_MIPMAP_LEVELS; mip++)
|
||||
@@ -2752,7 +2752,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size)
|
||||
// Resize framebuffer according to mip-level size.
|
||||
unsigned int mipWidth = size*powf(0.5f, mip);
|
||||
unsigned int mipHeight = size*powf(0.5f, mip);
|
||||
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight);
|
||||
glViewport(0, 0, mipWidth, mipHeight);
|
||||
@@ -2771,7 +2771,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size)
|
||||
|
||||
// Unbind framebuffer and textures
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
|
||||
// Reset viewport dimensions to default
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
@@ -2804,7 +2804,7 @@ Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size)
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, brdf.id, 0);
|
||||
|
||||
|
||||
glViewport(0, 0, size, size);
|
||||
glUseProgram(shader.id);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
@@ -2812,10 +2812,10 @@ Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size)
|
||||
|
||||
// Unbind framebuffer and textures
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
|
||||
// Reset viewport dimensions to default
|
||||
glViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
|
||||
brdf.width = size;
|
||||
brdf.height = size;
|
||||
#endif
|
||||
@@ -2853,7 +2853,7 @@ void EndBlendMode(void)
|
||||
VrDeviceInfo GetVrDeviceInfo(int vrDeviceType)
|
||||
{
|
||||
VrDeviceInfo hmd = { 0 }; // Current VR device info
|
||||
|
||||
|
||||
switch (vrDeviceType)
|
||||
{
|
||||
case HMD_DEFAULT_DEVICE:
|
||||
@@ -2881,7 +2881,7 @@ VrDeviceInfo GetVrDeviceInfo(int vrDeviceType)
|
||||
hmd.chromaAbCorrection[1] = -0.004f; // HMD chromatic aberration correction parameter 1
|
||||
hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2
|
||||
hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3
|
||||
|
||||
|
||||
TraceLog(LOG_INFO, "Initializing VR Simulator (Oculus Rift CV1)");
|
||||
} break;
|
||||
case HMD_OCULUS_RIFT_DK2:
|
||||
@@ -2903,9 +2903,9 @@ VrDeviceInfo GetVrDeviceInfo(int vrDeviceType)
|
||||
hmd.chromaAbCorrection[1] = -0.004f; // HMD chromatic aberration correction parameter 1
|
||||
hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2
|
||||
hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3
|
||||
|
||||
|
||||
TraceLog(LOG_INFO, "Initializing VR Simulator (Oculus Rift DK2)");
|
||||
} break;
|
||||
} break;
|
||||
case HMD_OCULUS_GO:
|
||||
{
|
||||
// TODO: Provide device display and lens parameters
|
||||
@@ -2920,7 +2920,7 @@ VrDeviceInfo GetVrDeviceInfo(int vrDeviceType)
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
||||
return hmd;
|
||||
}
|
||||
|
||||
@@ -2932,12 +2932,12 @@ void InitVrSimulator(VrDeviceInfo info)
|
||||
// Initialize framebuffer and textures for stereo rendering
|
||||
// NOTE: Screen size should match HMD aspect ratio
|
||||
vrConfig.stereoFbo = rlLoadRenderTexture(screenWidth, screenHeight);
|
||||
|
||||
|
||||
#if defined(SUPPORT_DISTORTION_SHADER)
|
||||
// Load distortion shader
|
||||
unsigned int vertexShaderId = CompileShader(distortionVShaderStr, GL_VERTEX_SHADER);
|
||||
unsigned int fragmentShaderId = CompileShader(distortionFShaderStr, GL_FRAGMENT_SHADER);
|
||||
|
||||
|
||||
vrConfig.distortionShader.id = LoadShaderProgram(vertexShaderId, fragmentShaderId);
|
||||
if (vrConfig.distortionShader.id > 0) SetShaderDefaultLocations(&vrConfig.distortionShader);
|
||||
#endif
|
||||
@@ -2997,7 +2997,7 @@ void ToggleVrMode(void)
|
||||
if (!vrSimulatorReady)
|
||||
{
|
||||
vrStereoRender = false;
|
||||
|
||||
|
||||
// Reset viewport and default projection-modelview matrices
|
||||
rlViewport(0, 0, screenWidth, screenHeight);
|
||||
projection = MatrixOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0);
|
||||
@@ -3031,7 +3031,7 @@ void BeginVrDrawing(void)
|
||||
|
||||
//glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye)
|
||||
rlClearScreenBuffers(); // Clear current framebuffer(s)
|
||||
|
||||
|
||||
vrStereoRender = true;
|
||||
}
|
||||
#endif
|
||||
@@ -3044,7 +3044,7 @@ void EndVrDrawing(void)
|
||||
if (vrSimulatorReady)
|
||||
{
|
||||
vrStereoRender = false; // Disable stereo render
|
||||
|
||||
|
||||
rlDisableRenderTexture(); // Unbind current framebuffer
|
||||
|
||||
rlClearScreenBuffers(); // Clear current framebuffer
|
||||
@@ -3096,7 +3096,7 @@ void EndVrDrawing(void)
|
||||
// Update and draw render texture fbo with distortion to backbuffer
|
||||
UpdateBuffersDefault();
|
||||
DrawBuffersDefault();
|
||||
|
||||
|
||||
// Restore defaultShader
|
||||
currentShader = defaultShader;
|
||||
|
||||
@@ -3104,7 +3104,7 @@ void EndVrDrawing(void)
|
||||
rlViewport(0, 0, screenWidth, screenHeight);
|
||||
projection = MatrixOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0);
|
||||
modelview = MatrixIdentity();
|
||||
|
||||
|
||||
rlDisableDepthTest();
|
||||
}
|
||||
#endif
|
||||
@@ -3216,7 +3216,7 @@ static unsigned int LoadShaderProgram(unsigned int vShaderId, unsigned int fShad
|
||||
static Shader LoadShaderDefault(void)
|
||||
{
|
||||
Shader shader = { 0 };
|
||||
|
||||
|
||||
// NOTE: All locations must be reseted to -1 (no location)
|
||||
for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
|
||||
|
||||
@@ -3282,10 +3282,10 @@ static Shader LoadShaderDefault(void)
|
||||
// NOTE: Compiled vertex/fragment shaders are kept for re-use
|
||||
defaultVShaderId = CompileShader(defaultVShaderStr, GL_VERTEX_SHADER); // Compile default vertex shader
|
||||
defaultFShaderId = CompileShader(defaultFShaderStr, GL_FRAGMENT_SHADER); // Compile default fragment shader
|
||||
|
||||
|
||||
shader.id = LoadShaderProgram(defaultVShaderId, defaultFShaderId);
|
||||
|
||||
if (shader.id > 0)
|
||||
if (shader.id > 0)
|
||||
{
|
||||
TraceLog(LOG_INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id);
|
||||
|
||||
@@ -3298,7 +3298,7 @@ static Shader LoadShaderDefault(void)
|
||||
shader.locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader.id, "mvp");
|
||||
shader.locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader.id, "colDiffuse");
|
||||
shader.locs[LOC_MAP_DIFFUSE] = glGetUniformLocation(shader.id, "texture0");
|
||||
|
||||
|
||||
// NOTE: We could also use below function but in case DEFAULT_ATTRIB_* points are
|
||||
// changed for external custom shaders, we just use direct bindings above
|
||||
//SetShaderDefaultLocations(&shader);
|
||||
@@ -3349,7 +3349,7 @@ static void UnloadShaderDefault(void)
|
||||
glDetachShader(defaultShader.id, defaultFShaderId);
|
||||
glDeleteShader(defaultVShaderId);
|
||||
glDeleteShader(defaultFShaderId);
|
||||
|
||||
|
||||
glDeleteProgram(defaultShader.id);
|
||||
}
|
||||
|
||||
@@ -3601,7 +3601,7 @@ static void DrawBuffersDefault(void)
|
||||
{
|
||||
Matrix matProjection = projection;
|
||||
Matrix matModelView = modelview;
|
||||
|
||||
|
||||
int eyesCount = 1;
|
||||
#if defined(SUPPORT_VR_SIMULATOR)
|
||||
if (vrStereoRender) eyesCount = 2;
|
||||
@@ -3825,7 +3825,7 @@ static void GenDrawQuad(void)
|
||||
{
|
||||
unsigned int quadVAO = 0;
|
||||
unsigned int quadVBO = 0;
|
||||
|
||||
|
||||
float vertices[] = {
|
||||
// Positions // Texture Coords
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
@@ -3853,7 +3853,7 @@ static void GenDrawQuad(void)
|
||||
glBindVertexArray(quadVAO);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
glDeleteBuffers(1, &quadVBO);
|
||||
glDeleteVertexArrays(1, &quadVAO);
|
||||
}
|
||||
@@ -3926,7 +3926,7 @@ static void GenDrawCube(void)
|
||||
glBindVertexArray(cubeVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
glDeleteBuffers(1, &cubeVBO);
|
||||
glDeleteVertexArrays(1, &cubeVAO);
|
||||
}
|
||||
@@ -3948,7 +3948,7 @@ static void SetStereoConfig(VrDeviceInfo hmd)
|
||||
|
||||
// Compute distortion scale parameters
|
||||
// NOTE: To get lens max radius, lensShift must be normalized to [-1..1]
|
||||
float lensRadius = fabsf(-1.0f - 4.0f*lensShift);
|
||||
float lensRadius = fabs(-1.0f - 4.0f*lensShift);
|
||||
float lensRadiusSq = lensRadius*lensRadius;
|
||||
float distortionScale = hmd.lensDistortionValues[0] +
|
||||
hmd.lensDistortionValues[1]*lensRadiusSq +
|
||||
@@ -4031,7 +4031,7 @@ static void GetGlFormats(int format, int *glInternalFormat, int *glFormat, int *
|
||||
*glInternalFormat = -1;
|
||||
*glFormat = -1;
|
||||
*glType = -1;
|
||||
|
||||
|
||||
switch (format)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
|
58
src/rlgl.h
58
src/rlgl.h
@@ -2,10 +2,10 @@
|
||||
*
|
||||
* rlgl - raylib OpenGL abstraction layer
|
||||
*
|
||||
* rlgl is a wrapper for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) to
|
||||
* pseudo-OpenGL 1.1 style functions (rlVertex, rlTranslate, rlRotate...).
|
||||
* rlgl is a wrapper for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) to
|
||||
* pseudo-OpenGL 1.1 style functions (rlVertex, rlTranslate, rlRotate...).
|
||||
*
|
||||
* When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal
|
||||
* When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal
|
||||
* VBO buffers (and VAOs if available). It requires calling 3 functions:
|
||||
* rlglInit() - Initialize internal buffers and auxiliar resources
|
||||
* rlglDraw() - Process internal buffers and send required draw calls
|
||||
@@ -18,7 +18,7 @@
|
||||
* #define GRAPHICS_API_OPENGL_33
|
||||
* #define GRAPHICS_API_OPENGL_ES2
|
||||
* Use selected OpenGL graphics backend, should be supported by platform
|
||||
* Those preprocessor defines are only used on rlgl module, if OpenGL version is
|
||||
* Those preprocessor defines are only used on rlgl module, if OpenGL version is
|
||||
* required by any other module, use rlGetVersion() tocheck it
|
||||
*
|
||||
* #define RLGL_STANDALONE
|
||||
@@ -124,7 +124,7 @@
|
||||
#define RL_WRAP_CLAMP_MIRROR 0x8742 // GL_MIRROR_CLAMP_EXT
|
||||
|
||||
// Matrix modes (equivalent to OpenGL)
|
||||
#define RL_MODELVIEW 0x1700 // GL_MODELVIEW
|
||||
#define RL_MODELVIEW 0x1700 // GL_MODELVIEW
|
||||
#define RL_PROJECTION 0x1701 // GL_PROJECTION
|
||||
#define RL_TEXTURE 0x1702 // GL_TEXTURE
|
||||
|
||||
@@ -153,7 +153,7 @@ typedef unsigned char byte;
|
||||
unsigned char b;
|
||||
unsigned char a;
|
||||
} Color;
|
||||
|
||||
|
||||
// Rectangle type
|
||||
typedef struct Rectangle {
|
||||
int x;
|
||||
@@ -161,7 +161,7 @@ typedef unsigned char byte;
|
||||
int width;
|
||||
int height;
|
||||
} Rectangle;
|
||||
|
||||
|
||||
// Texture2D type
|
||||
// NOTE: Data stored in GPU memory
|
||||
typedef struct Texture2D {
|
||||
@@ -194,11 +194,11 @@ typedef unsigned char byte;
|
||||
unsigned int vaoId; // OpenGL Vertex Array Object id
|
||||
unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data)
|
||||
} Mesh;
|
||||
|
||||
|
||||
// Shader and material limits
|
||||
#define MAX_SHADER_LOCATIONS 32
|
||||
#define MAX_MATERIAL_MAPS 12
|
||||
|
||||
|
||||
// Shader type (generic)
|
||||
typedef struct Shader {
|
||||
unsigned int id; // Shader program id
|
||||
@@ -226,7 +226,7 @@ typedef unsigned char byte;
|
||||
Vector3 up; // Camera up vector (rotation over its axis)
|
||||
float fovy; // Camera field-of-view apperture in Y (degrees)
|
||||
} Camera;
|
||||
|
||||
|
||||
// Head-Mounted-Display device parameters
|
||||
typedef struct VrDeviceInfo {
|
||||
int hResolution; // HMD horizontal resolution in pixels
|
||||
@@ -240,16 +240,16 @@ typedef unsigned char byte;
|
||||
float lensDistortionValues[4]; // HMD lens distortion constant parameters
|
||||
float chromaAbCorrection[4]; // HMD chromatic aberration correction parameters
|
||||
} VrDeviceInfo;
|
||||
|
||||
|
||||
// TraceLog message types
|
||||
typedef enum {
|
||||
LOG_INFO = 0,
|
||||
LOG_ERROR,
|
||||
LOG_WARNING,
|
||||
LOG_DEBUG,
|
||||
LOG_OTHER
|
||||
typedef enum {
|
||||
LOG_INFO = 0,
|
||||
LOG_ERROR,
|
||||
LOG_WARNING,
|
||||
LOG_DEBUG,
|
||||
LOG_OTHER
|
||||
} TraceLogType;
|
||||
|
||||
|
||||
// Texture formats (support depends on OpenGL version)
|
||||
typedef enum {
|
||||
UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
|
||||
@@ -278,7 +278,7 @@ typedef unsigned char byte;
|
||||
// Texture parameters: filter mode
|
||||
// NOTE 1: Filtering considers mipmaps if available in the texture
|
||||
// NOTE 2: Filter is accordingly set for minification and magnification
|
||||
typedef enum {
|
||||
typedef enum {
|
||||
FILTER_POINT = 0, // No filter, just pixel aproximation
|
||||
FILTER_BILINEAR, // Linear filtering
|
||||
FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
|
||||
@@ -286,19 +286,19 @@ typedef unsigned char byte;
|
||||
FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x
|
||||
FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x
|
||||
} TextureFilterMode;
|
||||
|
||||
|
||||
// Texture parameters: wrap mode
|
||||
typedef enum {
|
||||
WRAP_REPEAT = 0,
|
||||
WRAP_CLAMP,
|
||||
WRAP_MIRROR
|
||||
typedef enum {
|
||||
WRAP_REPEAT = 0,
|
||||
WRAP_CLAMP,
|
||||
WRAP_MIRROR
|
||||
} TextureWrapMode;
|
||||
|
||||
// Color blending modes (pre-defined)
|
||||
typedef enum {
|
||||
BLEND_ALPHA = 0,
|
||||
BLEND_ADDITIVE,
|
||||
BLEND_MULTIPLIED
|
||||
typedef enum {
|
||||
BLEND_ALPHA = 0,
|
||||
BLEND_ADDITIVE,
|
||||
BLEND_MULTIPLIED
|
||||
} BlendMode;
|
||||
|
||||
// Shader location point type
|
||||
@@ -465,7 +465,7 @@ void SetShaderValuei(Shader shader, int uniformLoc, const int *value, int size);
|
||||
void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4)
|
||||
void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix)
|
||||
void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix)
|
||||
Matrix GetMatrixModelview(); // Get internal modelview matrix
|
||||
Matrix GetMatrixModelview(); // Get internal modelview matrix
|
||||
|
||||
|
||||
// Texture maps generation (PBR)
|
||||
|
12
src/shapes.c
12
src/shapes.c
@@ -648,8 +648,8 @@ bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2)
|
||||
{
|
||||
bool collision = false;
|
||||
|
||||
float dx = fabsf((rec1.x + rec1.width/2) - (rec2.x + rec2.width/2));
|
||||
float dy = fabsf((rec1.y + rec1.height/2) - (rec2.y + rec2.height/2));
|
||||
float dx = fabs((rec1.x + rec1.width/2) - (rec2.x + rec2.width/2));
|
||||
float dy = fabs((rec1.y + rec1.height/2) - (rec2.y + rec2.height/2));
|
||||
|
||||
if ((dx <= (rec1.width/2 + rec2.width/2)) && ((dy <= (rec1.height/2 + rec2.height/2)))) collision = true;
|
||||
|
||||
@@ -678,8 +678,8 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
|
||||
int recCenterX = rec.x + rec.width/2;
|
||||
int recCenterY = rec.y + rec.height/2;
|
||||
|
||||
float dx = fabsf(center.x - recCenterX);
|
||||
float dy = fabsf(center.y - recCenterY);
|
||||
float dx = fabs(center.x - recCenterX);
|
||||
float dy = fabs(center.y - recCenterY);
|
||||
|
||||
if (dx > (rec.width/2.0f + radius)) { return false; }
|
||||
if (dy > (rec.height/2.0f + radius)) { return false; }
|
||||
@@ -700,8 +700,8 @@ Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
|
||||
|
||||
if (CheckCollisionRecs(rec1, rec2))
|
||||
{
|
||||
float dxx = fabsf(rec1.x - rec2.x);
|
||||
float dyy = fabsf(rec1.y - rec2.y);
|
||||
float dxx = fabs(rec1.x - rec2.x);
|
||||
float dyy = fabs(rec1.y - rec2.y);
|
||||
|
||||
if (rec1.x <= rec2.x)
|
||||
{
|
||||
|
361
src/text.c
361
src/text.c
@@ -47,15 +47,13 @@
|
||||
#include "utils.h" // Required for: fopen() Android mapping
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||
// Following libs are used on LoadTTF()
|
||||
#define STBTT_STATIC // Define stb_truetype functions static to this module
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap()
|
||||
#endif
|
||||
#define STB_RECT_PACK_IMPLEMENTATION
|
||||
#include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging
|
||||
|
||||
// Rectangle packing functions (not used at the moment)
|
||||
//#define STB_RECT_PACK_IMPLEMENTATION
|
||||
//#include "stb_rect_pack.h"
|
||||
#define STBTT_STATIC
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include "external/stb_truetype.h" // Required for: ttf font data reading
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
@@ -89,7 +87,7 @@ static Font LoadImageFont(Image image, Color key, int firstChar); // Load a Imag
|
||||
static Font LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||
static Font LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load spritefont from TTF data
|
||||
//static Font LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load spritefont from TTF data
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_DEFAULT_FONT)
|
||||
@@ -276,32 +274,40 @@ Font LoadFont(const char *fileName)
|
||||
// Default hardcoded values for ttf file loading
|
||||
#define DEFAULT_TTF_FONTSIZE 32 // Font first character (32 - space)
|
||||
#define DEFAULT_TTF_NUMCHARS 95 // ASCII 32..126 is 95 glyphs
|
||||
#define DEFAULT_FIRST_CHAR 32 // Expected first char for image spritefont
|
||||
#define DEFAULT_FIRST_CHAR 32 // Expected first char for image sprite font
|
||||
|
||||
Font spriteFont = { 0 };
|
||||
Font font = { 0 };
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||
if (IsFileExtension(fileName, ".ttf")) spriteFont = LoadFontEx(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL);
|
||||
if (IsFileExtension(fileName, ".ttf"))
|
||||
{
|
||||
font.baseSize = DEFAULT_TTF_FONTSIZE;
|
||||
font.charsCount = DEFAULT_TTF_NUMCHARS;
|
||||
font.chars = LoadFontData(fileName, font.baseSize, NULL, font.charsCount, false);
|
||||
Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 4, 0);
|
||||
font.texture = LoadTextureFromImage(atlas);
|
||||
UnloadImage(atlas);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||
if (IsFileExtension(fileName, ".fnt")) spriteFont = LoadBMFont(fileName);
|
||||
if (IsFileExtension(fileName, ".fnt")) font = LoadBMFont(fileName);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Image image = LoadImage(fileName);
|
||||
if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, DEFAULT_FIRST_CHAR);
|
||||
if (image.data != NULL) font = LoadImageFont(image, MAGENTA, DEFAULT_FIRST_CHAR);
|
||||
UnloadImage(image);
|
||||
}
|
||||
|
||||
if (spriteFont.texture.id == 0)
|
||||
if (font.texture.id == 0)
|
||||
{
|
||||
TraceLog(LOG_WARNING, "[%s] Font could not be loaded, using default font", fileName);
|
||||
spriteFont = GetDefaultFont();
|
||||
font = GetDefaultFont();
|
||||
}
|
||||
else SetTextureFilter(spriteFont.texture, FILTER_POINT); // By default we set point filter (best performance)
|
||||
else SetTextureFilter(font.texture, FILTER_POINT); // By default we set point filter (best performance)
|
||||
|
||||
return spriteFont;
|
||||
return font;
|
||||
}
|
||||
|
||||
// Load Font from TTF font file with generation parameters
|
||||
@@ -309,31 +315,212 @@ Font LoadFont(const char *fileName)
|
||||
// if array is NULL, default char set is selected 32..126
|
||||
Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars)
|
||||
{
|
||||
Font spriteFont = { 0 };
|
||||
int totalChars = 95; // Default charset [32..126]
|
||||
Font font = { 0 };
|
||||
|
||||
font.baseSize = fontSize;
|
||||
font.charsCount = (charsCount > 0) ? charsCount : 95;
|
||||
font.chars = LoadFontData(fileName, font.baseSize, fontChars, font.charsCount, false);
|
||||
Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 0, 0);
|
||||
font.texture = LoadTextureFromImage(atlas);
|
||||
UnloadImage(atlas);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||
if (IsFileExtension(fileName, ".ttf"))
|
||||
// Load font data for further use
|
||||
// NOTE: Requires TTF font and can generate SDF data
|
||||
CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, bool sdf)
|
||||
{
|
||||
// NOTE: Using some SDF generation default values,
|
||||
// trades off precision with ability to handle *smaller* sizes
|
||||
#define SDF_CHAR_PADDING 4
|
||||
#define SDF_ON_EDGE_VALUE 128
|
||||
#define SDF_PIXEL_DIST_SCALE 64.0f
|
||||
|
||||
CharInfo *chars = (CharInfo *)malloc(charsCount*sizeof(CharInfo));
|
||||
|
||||
// Load font data (including pixel data) from TTF file
|
||||
// NOTE: Loaded information should be enough to generate font image atlas,
|
||||
// using any packaging method
|
||||
FILE *fontFile = fopen(fileName, "rb"); // Load font file
|
||||
|
||||
fseek(fontFile, 0, SEEK_END);
|
||||
long size = ftell(fontFile); // Get file size
|
||||
fseek(fontFile, 0, SEEK_SET); // Reset file pointer
|
||||
|
||||
unsigned char *fontBuffer = (unsigned char *)malloc(size);
|
||||
|
||||
fread(fontBuffer, size, 1, fontFile);
|
||||
fclose(fontFile);
|
||||
|
||||
// Init font for data reading
|
||||
stbtt_fontinfo fontInfo;
|
||||
if (!stbtt_InitFont(&fontInfo, fontBuffer, 0)) TraceLog(LOG_WARNING, "Failed to init font!");
|
||||
|
||||
// Calculate font scale factor
|
||||
float scaleFactor = stbtt_ScaleForPixelHeight(&fontInfo, fontSize);
|
||||
|
||||
// Calculate font basic metrics
|
||||
// NOTE: ascent is equivalent to font baseline
|
||||
int ascent, descent, lineGap;
|
||||
stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
|
||||
ascent *= scaleFactor;
|
||||
descent *= scaleFactor;
|
||||
|
||||
// Fill fontChars in case not provided externally
|
||||
// NOTE: By default we fill charsCount consecutevely, starting at 32 (Space)
|
||||
int genFontChars = false;
|
||||
if (fontChars == NULL) genFontChars = true;
|
||||
if (genFontChars)
|
||||
{
|
||||
if (charsCount != 0) totalChars = charsCount;
|
||||
fontChars = (int *)malloc(charsCount*sizeof(int));
|
||||
for (int i = 0; i < charsCount; i++) fontChars[i] = i + 32;
|
||||
}
|
||||
|
||||
// NOTE: Using simple packaging, one char after another
|
||||
for (int i = 0; i < charsCount; i++)
|
||||
{
|
||||
int chw = 0, chh = 0; // Character width and height (on generation)
|
||||
int ch = fontChars[i]; // Character value to get info for
|
||||
chars[i].value = ch;
|
||||
|
||||
if (fontChars == NULL)
|
||||
// Render a unicode codepoint to a bitmap
|
||||
// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
|
||||
// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
|
||||
// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
|
||||
|
||||
if (!sdf) chars[i].data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
|
||||
else if (ch != 32) chars[i].data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, SDF_CHAR_PADDING, SDF_ON_EDGE_VALUE, SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
|
||||
|
||||
chars[i].rec.width = (float)chw;
|
||||
chars[i].rec.height = (float)chh;
|
||||
chars[i].offsetY += ascent;
|
||||
|
||||
// Get bounding box for character (may be offset to account for chars that dip above or below the line)
|
||||
int chX1, chY1, chX2, chY2;
|
||||
stbtt_GetCodepointBitmapBox(&fontInfo, ch, scaleFactor, scaleFactor, &chX1, &chY1, &chX2, &chY2);
|
||||
|
||||
TraceLog(LOG_DEBUG, "Character box measures: %i, %i, %i, %i", chX1, chY1, chX2 - chX1, chY2 - chY1);
|
||||
TraceLog(LOG_DEBUG, "Character offsetY: %i", ascent + chY1);
|
||||
|
||||
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
|
||||
chars[i].advanceX *= scaleFactor;
|
||||
}
|
||||
|
||||
free(fontBuffer);
|
||||
if (genFontChars) free(fontChars);
|
||||
|
||||
return chars;
|
||||
}
|
||||
|
||||
// Generate image font atlas using chars info
|
||||
// NOTE: Packing method: 0-Default, 1-Skyline
|
||||
Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int padding, int packMethod)
|
||||
{
|
||||
Image atlas = { 0 };
|
||||
|
||||
// Calculate texture size based on required pixel area
|
||||
// NOTE: Texture is forced to be squared and POT
|
||||
float requiredArea = 0;
|
||||
for (int i = 0; i < charsCount; i++) requiredArea += ((chars[i].rec.width + 2*padding)*(chars[i].rec.height + 2*padding));
|
||||
float guessSize = sqrtf(requiredArea)*1.25f;
|
||||
int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
|
||||
|
||||
atlas.width = textureSize; // Atlas bitmap width
|
||||
atlas.height = textureSize; // Atlas bitmap height
|
||||
atlas.data = (unsigned char *)calloc(1, atlas.width*atlas.height); // Create a bitmap to store characters (8 bpp)
|
||||
atlas.format = UNCOMPRESSED_GRAYSCALE;
|
||||
atlas.mipmaps = 1;
|
||||
|
||||
if (packMethod == 0) // Use basic packing algorythm
|
||||
{
|
||||
int offsetX = padding;
|
||||
int offsetY = padding;
|
||||
|
||||
// NOTE: Using simple packaging, one char after another
|
||||
for (int i = 0; i < charsCount; i++)
|
||||
{
|
||||
fontChars = (int *)malloc(totalChars*sizeof(int));
|
||||
for (int i = 0; i < totalChars; i++) fontChars[i] = i + 32; // Default first character: SPACE[32]
|
||||
// Copy pixel data from fc.data to atlas
|
||||
for (int y = 0; y < (int)chars[i].rec.height; y++)
|
||||
{
|
||||
for (int x = 0; x < (int)chars[i].rec.width; x++)
|
||||
{
|
||||
((unsigned char *)atlas.data)[(offsetY + y)*atlas.width + (offsetX + x)] = chars[i].data[y*(int)chars[i].rec.width + x];
|
||||
}
|
||||
}
|
||||
|
||||
chars[i].rec.x = offsetX;
|
||||
chars[i].rec.y = offsetY;
|
||||
|
||||
// Move atlas position X for next character drawing
|
||||
offsetX += ((int)chars[i].advanceX + 2*padding);
|
||||
|
||||
if (offsetX >= (atlas.width - (int)chars[i].rec.width - padding))
|
||||
{
|
||||
offsetX = padding;
|
||||
offsetY += (fontSize + 2*padding);
|
||||
|
||||
if (offsetY > (atlas.height - fontSize - padding)) break;
|
||||
}
|
||||
}
|
||||
|
||||
spriteFont = LoadTTF(fileName, fontSize, totalChars, fontChars);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (spriteFont.texture.id == 0)
|
||||
else if (packMethod == 1) // Use Skyline rect packing algorythm (stb_pack_rect)
|
||||
{
|
||||
TraceLog(LOG_WARNING, "[%s] Font could not be generated, using default font", fileName);
|
||||
spriteFont = GetDefaultFont();
|
||||
stbrp_context *context = (stbrp_context *)malloc(sizeof(*context));
|
||||
stbrp_node *nodes = (stbrp_node *)malloc(charsCount*sizeof(*nodes));
|
||||
|
||||
stbrp_init_target(context, atlas.width, atlas.height, nodes, charsCount);
|
||||
stbrp_rect *rects = (stbrp_rect *)malloc(charsCount*sizeof(stbrp_rect));
|
||||
|
||||
// Fill rectangles for packaging
|
||||
for (int i = 0; i < charsCount; i++)
|
||||
{
|
||||
rects[i].id = i;
|
||||
rects[i].w = (int)chars[i].rec.width + 2*padding;
|
||||
rects[i].h = (int)chars[i].rec.height + 2*padding;
|
||||
}
|
||||
|
||||
// Package rectangles into atlas
|
||||
stbrp_pack_rects(context, rects, charsCount);
|
||||
|
||||
for (int i = 0; i < charsCount; i++)
|
||||
{
|
||||
chars[i].rec.x = rects[i].x + padding;
|
||||
chars[i].rec.y = rects[i].y + padding;
|
||||
|
||||
if (rects[i].was_packed)
|
||||
{
|
||||
// Copy pixel data from fc.data to atlas
|
||||
for (int y = 0; y < (int)chars[i].rec.height; y++)
|
||||
{
|
||||
for (int x = 0; x < (int)chars[i].rec.width; x++)
|
||||
{
|
||||
((unsigned char *)atlas.data)[(rects[i].y + padding + y)*atlas.width + (rects[i].x + padding + x)] = chars[i].data[y*(int)chars[i].rec.width + x];
|
||||
}
|
||||
}
|
||||
}
|
||||
else TraceLog(LOG_WARNING, "Character could not be packed: %i", i);
|
||||
}
|
||||
|
||||
free(nodes);
|
||||
free(context);
|
||||
}
|
||||
|
||||
// Convert image data from GRAYSCALE to GRAY_ALPHA
|
||||
// WARNING: ImageAlphaMask(&atlas, atlas) does not work in this case, requires manual operation
|
||||
unsigned char *dataGrayAlpha = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)*2); // Two channels
|
||||
|
||||
for (int i = 0, k = 0; i < atlas.width*atlas.height; i++, k += 2)
|
||||
{
|
||||
dataGrayAlpha[k] = 255;
|
||||
dataGrayAlpha[k + 1] = ((unsigned char *)atlas.data)[i];
|
||||
}
|
||||
|
||||
return spriteFont;
|
||||
free(atlas.data);
|
||||
atlas.data = dataGrayAlpha;
|
||||
atlas.format = UNCOMPRESSED_GRAY_ALPHA;
|
||||
|
||||
return atlas;
|
||||
}
|
||||
|
||||
// Unload Font from GPU memory (VRAM)
|
||||
@@ -807,108 +994,4 @@ static Font LoadBMFont(const char *fileName)
|
||||
|
||||
return font;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||
// Generate a sprite font from TTF file data (font size required)
|
||||
// TODO: Review texture packing method and generation (use oversampling)
|
||||
static Font LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars)
|
||||
{
|
||||
#define MAX_TTF_SIZE 16 // Maximum ttf file size in MB
|
||||
|
||||
// NOTE: Font texture size is predicted (being as much conservative as possible)
|
||||
// Predictive method consist of supposing same number of chars by line-column (sqrtf)
|
||||
// and a maximum character width of 3/4 of fontSize... it worked ok with all my tests...
|
||||
|
||||
// Calculate next power-of-two value
|
||||
float guessSize = ceilf((float)fontSize*3/4)*ceilf(sqrtf((float)charsCount));
|
||||
int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
|
||||
|
||||
TraceLog(LOG_INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize);
|
||||
|
||||
unsigned char *ttfBuffer = (unsigned char *)malloc(MAX_TTF_SIZE*1024*1024);
|
||||
unsigned char *dataBitmap = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)); // One channel bitmap returned!
|
||||
stbtt_bakedchar *charData = (stbtt_bakedchar *)malloc(sizeof(stbtt_bakedchar)*charsCount);
|
||||
|
||||
Font font = { 0 };
|
||||
|
||||
FILE *ttfFile = fopen(fileName, "rb");
|
||||
|
||||
if (ttfFile == NULL)
|
||||
{
|
||||
TraceLog(LOG_WARNING, "[%s] TTF file could not be opened", fileName);
|
||||
return font;
|
||||
}
|
||||
|
||||
// NOTE: We try reading up to 16 MB of elements of 1 byte
|
||||
fread(ttfBuffer, 1, MAX_TTF_SIZE*1024*1024, ttfFile);
|
||||
|
||||
// Find font baseline (vertical origin of the font)
|
||||
// NOTE: This value is required because y-offset depends on it!
|
||||
stbtt_fontinfo fontInfo;
|
||||
int ascent, baseline;
|
||||
float scale;
|
||||
|
||||
stbtt_InitFont(&fontInfo, ttfBuffer, 0);
|
||||
scale = stbtt_ScaleForPixelHeight(&fontInfo, fontSize);
|
||||
stbtt_GetFontVMetrics(&fontInfo, &ascent, 0, 0);
|
||||
baseline = (int)(ascent*scale);
|
||||
|
||||
if (fontChars[0] != 32) TraceLog(LOG_WARNING, "TTF spritefont loading: first character is not SPACE(32) character");
|
||||
|
||||
// NOTE: Using stb_truetype crappy packing method, no guarantee the font fits the image...
|
||||
// TODO: Replace this function by a proper packing method and support random chars order,
|
||||
// we already receive a list (fontChars) with the ordered expected characters
|
||||
int result = stbtt_BakeFontBitmap(ttfBuffer, 0, fontSize, dataBitmap, textureSize, textureSize, fontChars[0], charsCount, charData);
|
||||
|
||||
//if (result > 0) TraceLog(LOG_INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result);
|
||||
if (result < 0) TraceLog(LOG_WARNING, "TTF spritefont loading: Not all the characters fit in the font");
|
||||
|
||||
free(ttfBuffer);
|
||||
|
||||
// Convert image data from grayscale to to UNCOMPRESSED_GRAY_ALPHA
|
||||
unsigned char *dataGrayAlpha = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)*2); // Two channels
|
||||
|
||||
for (int i = 0, k = 0; i < textureSize*textureSize; i++, k += 2)
|
||||
{
|
||||
dataGrayAlpha[k] = 0xff;
|
||||
dataGrayAlpha[k + 1] = dataBitmap[i];
|
||||
}
|
||||
|
||||
free(dataBitmap);
|
||||
|
||||
// Sprite font generation from TTF extracted data
|
||||
Image image;
|
||||
image.width = textureSize;
|
||||
image.height = textureSize;
|
||||
image.mipmaps = 1;
|
||||
image.format = UNCOMPRESSED_GRAY_ALPHA;
|
||||
image.data = dataGrayAlpha;
|
||||
font.texture = LoadTextureFromImage(image); // Load image into texture
|
||||
UnloadImage(image); // Unloads image data (dataGrayAlpha)
|
||||
|
||||
|
||||
// Fill font characters info data
|
||||
font.baseSize = fontSize;
|
||||
font.charsCount = charsCount;
|
||||
font.chars = (CharInfo *)malloc(font.charsCount*sizeof(CharInfo));
|
||||
|
||||
for (int i = 0; i < font.charsCount; i++)
|
||||
{
|
||||
font.chars[i].value = fontChars[i];
|
||||
|
||||
font.chars[i].rec.x = (int)charData[i].x0;
|
||||
font.chars[i].rec.y = (int)charData[i].y0;
|
||||
font.chars[i].rec.width = (int)charData[i].x1 - (int)charData[i].x0;
|
||||
font.chars[i].rec.height = (int)charData[i].y1 - (int)charData[i].y0;
|
||||
|
||||
font.chars[i].offsetX = charData[i].xoff;
|
||||
font.chars[i].offsetY = baseline + charData[i].yoff;
|
||||
font.chars[i].advanceX = (int)charData[i].xadvance;
|
||||
}
|
||||
|
||||
free(charData);
|
||||
|
||||
return font;
|
||||
}
|
||||
#endif
|
||||
#endif
|
475
src/textures.c
475
src/textures.c
@@ -405,87 +405,231 @@ void UnloadRenderTexture(RenderTexture2D target)
|
||||
}
|
||||
|
||||
// Get pixel data from image in the form of Color struct array
|
||||
// TODO: Support float pixel data retrieval
|
||||
Color *GetImageData(Image image)
|
||||
{
|
||||
Color *pixels = (Color *)malloc(image.width*image.height*sizeof(Color));
|
||||
|
||||
for (int i = 0, k = 0; i < image.width*image.height; i++)
|
||||
if (image.format >= COMPRESSED_DXT1_RGB) TraceLog(LOG_WARNING, "Pixel data retrieval not supported for compressed image formats");
|
||||
else
|
||||
{
|
||||
switch (image.format)
|
||||
if ((image.format == UNCOMPRESSED_R32) ||
|
||||
(image.format == UNCOMPRESSED_R32G32B32) ||
|
||||
(image.format == UNCOMPRESSED_R32G32B32A32)) TraceLog(LOG_WARNING, "32bit pixel format converted to 8bit per channel");
|
||||
|
||||
for (int i = 0, k = 0; i < image.width*image.height; i++)
|
||||
{
|
||||
case UNCOMPRESSED_GRAYSCALE:
|
||||
switch (image.format)
|
||||
{
|
||||
pixels[i].r = ((unsigned char *)image.data)[i];
|
||||
pixels[i].g = ((unsigned char *)image.data)[i];
|
||||
pixels[i].b = ((unsigned char *)image.data)[i];
|
||||
pixels[i].a = 255;
|
||||
case UNCOMPRESSED_GRAYSCALE:
|
||||
{
|
||||
pixels[i].r = ((unsigned char *)image.data)[i];
|
||||
pixels[i].g = ((unsigned char *)image.data)[i];
|
||||
pixels[i].b = ((unsigned char *)image.data)[i];
|
||||
pixels[i].a = 255;
|
||||
|
||||
} break;
|
||||
case UNCOMPRESSED_GRAY_ALPHA:
|
||||
{
|
||||
pixels[i].r = ((unsigned char *)image.data)[k];
|
||||
pixels[i].g = ((unsigned char *)image.data)[k];
|
||||
pixels[i].b = ((unsigned char *)image.data)[k];
|
||||
pixels[i].a = ((unsigned char *)image.data)[k + 1];
|
||||
} break;
|
||||
case UNCOMPRESSED_GRAY_ALPHA:
|
||||
{
|
||||
pixels[i].r = ((unsigned char *)image.data)[k];
|
||||
pixels[i].g = ((unsigned char *)image.data)[k];
|
||||
pixels[i].b = ((unsigned char *)image.data)[k];
|
||||
pixels[i].a = ((unsigned char *)image.data)[k + 1];
|
||||
|
||||
k += 2;
|
||||
} break;
|
||||
case UNCOMPRESSED_R5G5B5A1:
|
||||
{
|
||||
unsigned short pixel = ((unsigned short *)image.data)[i];
|
||||
k += 2;
|
||||
} break;
|
||||
case UNCOMPRESSED_R5G5B5A1:
|
||||
{
|
||||
unsigned short pixel = ((unsigned short *)image.data)[i];
|
||||
|
||||
pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31));
|
||||
pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111000000) >> 6)*(255/31));
|
||||
pixels[i].b = (unsigned char)((float)((pixel & 0b0000000000111110) >> 1)*(255/31));
|
||||
pixels[i].a = (unsigned char)((pixel & 0b0000000000000001)*255);
|
||||
pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31));
|
||||
pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111000000) >> 6)*(255/31));
|
||||
pixels[i].b = (unsigned char)((float)((pixel & 0b0000000000111110) >> 1)*(255/31));
|
||||
pixels[i].a = (unsigned char)((pixel & 0b0000000000000001)*255);
|
||||
|
||||
} break;
|
||||
case UNCOMPRESSED_R5G6B5:
|
||||
{
|
||||
unsigned short pixel = ((unsigned short *)image.data)[i];
|
||||
} break;
|
||||
case UNCOMPRESSED_R5G6B5:
|
||||
{
|
||||
unsigned short pixel = ((unsigned short *)image.data)[i];
|
||||
|
||||
pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31));
|
||||
pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111100000) >> 5)*(255/63));
|
||||
pixels[i].b = (unsigned char)((float)(pixel & 0b0000000000011111)*(255/31));
|
||||
pixels[i].a = 255;
|
||||
pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31));
|
||||
pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111100000) >> 5)*(255/63));
|
||||
pixels[i].b = (unsigned char)((float)(pixel & 0b0000000000011111)*(255/31));
|
||||
pixels[i].a = 255;
|
||||
|
||||
} break;
|
||||
case UNCOMPRESSED_R4G4B4A4:
|
||||
{
|
||||
unsigned short pixel = ((unsigned short *)image.data)[i];
|
||||
} break;
|
||||
case UNCOMPRESSED_R4G4B4A4:
|
||||
{
|
||||
unsigned short pixel = ((unsigned short *)image.data)[i];
|
||||
|
||||
pixels[i].r = (unsigned char)((float)((pixel & 0b1111000000000000) >> 12)*(255/15));
|
||||
pixels[i].g = (unsigned char)((float)((pixel & 0b0000111100000000) >> 8)*(255/15));
|
||||
pixels[i].b = (unsigned char)((float)((pixel & 0b0000000011110000) >> 4)*(255/15));
|
||||
pixels[i].a = (unsigned char)((float)(pixel & 0b0000000000001111)*(255/15));
|
||||
pixels[i].r = (unsigned char)((float)((pixel & 0b1111000000000000) >> 12)*(255/15));
|
||||
pixels[i].g = (unsigned char)((float)((pixel & 0b0000111100000000) >> 8)*(255/15));
|
||||
pixels[i].b = (unsigned char)((float)((pixel & 0b0000000011110000) >> 4)*(255/15));
|
||||
pixels[i].a = (unsigned char)((float)(pixel & 0b0000000000001111)*(255/15));
|
||||
|
||||
} break;
|
||||
case UNCOMPRESSED_R8G8B8A8:
|
||||
{
|
||||
pixels[i].r = ((unsigned char *)image.data)[k];
|
||||
pixels[i].g = ((unsigned char *)image.data)[k + 1];
|
||||
pixels[i].b = ((unsigned char *)image.data)[k + 2];
|
||||
pixels[i].a = ((unsigned char *)image.data)[k + 3];
|
||||
} break;
|
||||
case UNCOMPRESSED_R8G8B8A8:
|
||||
{
|
||||
pixels[i].r = ((unsigned char *)image.data)[k];
|
||||
pixels[i].g = ((unsigned char *)image.data)[k + 1];
|
||||
pixels[i].b = ((unsigned char *)image.data)[k + 2];
|
||||
pixels[i].a = ((unsigned char *)image.data)[k + 3];
|
||||
|
||||
k += 4;
|
||||
} break;
|
||||
case UNCOMPRESSED_R8G8B8:
|
||||
{
|
||||
pixels[i].r = (unsigned char)((unsigned char *)image.data)[k];
|
||||
pixels[i].g = (unsigned char)((unsigned char *)image.data)[k + 1];
|
||||
pixels[i].b = (unsigned char)((unsigned char *)image.data)[k + 2];
|
||||
pixels[i].a = 255;
|
||||
k += 4;
|
||||
} break;
|
||||
case UNCOMPRESSED_R8G8B8:
|
||||
{
|
||||
pixels[i].r = (unsigned char)((unsigned char *)image.data)[k];
|
||||
pixels[i].g = (unsigned char)((unsigned char *)image.data)[k + 1];
|
||||
pixels[i].b = (unsigned char)((unsigned char *)image.data)[k + 2];
|
||||
pixels[i].a = 255;
|
||||
|
||||
k += 3;
|
||||
} break;
|
||||
default: TraceLog(LOG_WARNING, "Format not supported for pixel data retrieval"); break;
|
||||
k += 3;
|
||||
} break;
|
||||
case UNCOMPRESSED_R32:
|
||||
{
|
||||
pixels[i].r = (unsigned char)(((float *)image.data)[k]*255.0f);
|
||||
pixels[i].g = 0;
|
||||
pixels[i].b = 0;
|
||||
pixels[i].a = 255;
|
||||
|
||||
} break;
|
||||
case UNCOMPRESSED_R32G32B32:
|
||||
{
|
||||
pixels[i].r = (unsigned char)(((float *)image.data)[k]*255.0f);
|
||||
pixels[i].g = (unsigned char)(((float *)image.data)[k + 1]*255.0f);
|
||||
pixels[i].b = (unsigned char)(((float *)image.data)[k + 2]*255.0f);
|
||||
pixels[i].a = 255;
|
||||
|
||||
k += 3;
|
||||
}
|
||||
case UNCOMPRESSED_R32G32B32A32:
|
||||
{
|
||||
pixels[i].r = (unsigned char)(((float *)image.data)[k]*255.0f);
|
||||
pixels[i].g = (unsigned char)(((float *)image.data)[k]*255.0f);
|
||||
pixels[i].b = (unsigned char)(((float *)image.data)[k]*255.0f);
|
||||
pixels[i].a = (unsigned char)(((float *)image.data)[k]*255.0f);
|
||||
|
||||
k += 4;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pixels;
|
||||
}
|
||||
|
||||
// Get pixel data from image as Vector4 array (float normalized)
|
||||
Vector4 *GetImageDataNormalized(Image image)
|
||||
{
|
||||
Vector4 *pixels = (Vector4 *)malloc(image.width*image.height*sizeof(Vector4));
|
||||
|
||||
if (image.format >= COMPRESSED_DXT1_RGB) TraceLog(LOG_WARNING, "Pixel data retrieval not supported for compressed image formats");
|
||||
else
|
||||
{
|
||||
for (int i = 0, k = 0; i < image.width*image.height; i++)
|
||||
{
|
||||
switch (image.format)
|
||||
{
|
||||
case UNCOMPRESSED_GRAYSCALE:
|
||||
{
|
||||
pixels[i].x = (float)((unsigned char *)image.data)[i]/255.0f;
|
||||
pixels[i].y = (float)((unsigned char *)image.data)[i]/255.0f;
|
||||
pixels[i].z = (float)((unsigned char *)image.data)[i]/255.0f;
|
||||
pixels[i].w = 1.0f;
|
||||
|
||||
} break;
|
||||
case UNCOMPRESSED_GRAY_ALPHA:
|
||||
{
|
||||
pixels[i].x = (float)((unsigned char *)image.data)[k]/255.0f;
|
||||
pixels[i].y = (float)((unsigned char *)image.data)[k]/255.0f;
|
||||
pixels[i].z = (float)((unsigned char *)image.data)[k]/255.0f;
|
||||
pixels[i].w = (float)((unsigned char *)image.data)[k + 1]/255.0f;
|
||||
|
||||
k += 2;
|
||||
} break;
|
||||
case UNCOMPRESSED_R5G5B5A1:
|
||||
{
|
||||
unsigned short pixel = ((unsigned short *)image.data)[i];
|
||||
|
||||
pixels[i].x = (float)((pixel & 0b1111100000000000) >> 11)*(1.0f/31);
|
||||
pixels[i].y = (float)((pixel & 0b0000011111000000) >> 6)*(1.0f/31);
|
||||
pixels[i].z = (float)((pixel & 0b0000000000111110) >> 1)*(1.0f/31);
|
||||
pixels[i].w = ((pixel & 0b0000000000000001) == 0) ? 0.0f : 1.0f;
|
||||
|
||||
} break;
|
||||
case UNCOMPRESSED_R5G6B5:
|
||||
{
|
||||
unsigned short pixel = ((unsigned short *)image.data)[i];
|
||||
|
||||
pixels[i].x = (float)((pixel & 0b1111100000000000) >> 11)*(1.0f/31);
|
||||
pixels[i].y = (float)((pixel & 0b0000011111100000) >> 5)*(1.0f/63);
|
||||
pixels[i].z = (float)(pixel & 0b0000000000011111)*(1.0f/31);
|
||||
pixels[i].w = 1.0f;
|
||||
|
||||
} break;
|
||||
case UNCOMPRESSED_R4G4B4A4:
|
||||
{
|
||||
unsigned short pixel = ((unsigned short *)image.data)[i];
|
||||
|
||||
pixels[i].x = (float)((pixel & 0b1111000000000000) >> 12)*(1.0f/15);
|
||||
pixels[i].y = (float)((pixel & 0b0000111100000000) >> 8)*(1.0f/15);
|
||||
pixels[i].z = (float)((pixel & 0b0000000011110000) >> 4)*(1.0f/15);
|
||||
pixels[i].w = (float)(pixel & 0b0000000000001111)*(1.0f/15);
|
||||
|
||||
} break;
|
||||
case UNCOMPRESSED_R8G8B8A8:
|
||||
{
|
||||
pixels[i].x = (float)((unsigned char *)image.data)[k]/255.0f;
|
||||
pixels[i].y = (float)((unsigned char *)image.data)[k + 1]/255.0f;
|
||||
pixels[i].z = (float)((unsigned char *)image.data)[k + 2]/255.0f;
|
||||
pixels[i].w = (float)((unsigned char *)image.data)[k + 3]/255.0f;
|
||||
|
||||
k += 4;
|
||||
} break;
|
||||
case UNCOMPRESSED_R8G8B8:
|
||||
{
|
||||
pixels[i].x = (float)((unsigned char *)image.data)[k]/255.0f;
|
||||
pixels[i].y = (float)((unsigned char *)image.data)[k + 1]/255.0f;
|
||||
pixels[i].z = (float)((unsigned char *)image.data)[k + 2]/255.0f;
|
||||
pixels[i].w = 1.0f;
|
||||
|
||||
k += 3;
|
||||
} break;
|
||||
case UNCOMPRESSED_R32:
|
||||
{
|
||||
pixels[i].x = ((float *)image.data)[k];
|
||||
pixels[i].y = 0.0f;
|
||||
pixels[i].z = 0.0f;
|
||||
pixels[i].w = 1.0f;
|
||||
|
||||
} break;
|
||||
case UNCOMPRESSED_R32G32B32:
|
||||
{
|
||||
pixels[i].x = ((float *)image.data)[k];
|
||||
pixels[i].y = ((float *)image.data)[k + 1];
|
||||
pixels[i].z = ((float *)image.data)[k + 2];
|
||||
pixels[i].w = 1.0f;
|
||||
|
||||
k += 3;
|
||||
}
|
||||
case UNCOMPRESSED_R32G32B32A32:
|
||||
{
|
||||
pixels[i].x = ((float *)image.data)[k];
|
||||
pixels[i].y = ((float *)image.data)[k + 1];
|
||||
pixels[i].z = ((float *)image.data)[k + 2];
|
||||
pixels[i].w = ((float *)image.data)[k + 3];
|
||||
|
||||
k += 4;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pixels;
|
||||
}
|
||||
|
||||
// Get pixel data size in bytes (image or texture)
|
||||
// NOTE: Size depends on pixel format
|
||||
int GetPixelDataSize(int width, int height, int format)
|
||||
@@ -567,8 +711,10 @@ void ExportImage(const char *fileName, Image image)
|
||||
{
|
||||
// NOTE: Getting Color array as RGBA unsigned char values
|
||||
unsigned char *imgData = (unsigned char *)GetImageData(image);
|
||||
|
||||
// NOTE: SavePNG() not supported by some platforms: PLATFORM_WEB, PLATFORM_ANDROID
|
||||
SavePNG(fileName, imgData, image.width, image.height, 4);
|
||||
// FIXME ^ this fails on PLATFORM_WEB, what should we do?
|
||||
|
||||
free(imgData);
|
||||
}
|
||||
|
||||
@@ -644,8 +790,7 @@ void ImageToPOT(Image *image, Color fillColor)
|
||||
|
||||
int format = image->format; // Store image data format to reconvert later
|
||||
|
||||
// TODO: Image width and height changes... do we want to store new values or keep the old ones?
|
||||
// NOTE: Issues when using image.width and image.height for sprite animations...
|
||||
// NOTE: Image size changes, new width and height
|
||||
*image = LoadImageEx(pixelsPOT, potWidth, potHeight);
|
||||
|
||||
free(pixelsPOT); // Free POT pixels data
|
||||
@@ -657,11 +802,11 @@ void ImageToPOT(Image *image, Color fillColor)
|
||||
// Convert image data to desired format
|
||||
void ImageFormat(Image *image, int newFormat)
|
||||
{
|
||||
if (image->format != newFormat)
|
||||
if ((newFormat != 0) && (image->format != newFormat))
|
||||
{
|
||||
if ((image->format < COMPRESSED_DXT1_RGB) && (newFormat < COMPRESSED_DXT1_RGB))
|
||||
{
|
||||
Color *pixels = GetImageData(*image);
|
||||
Vector4 *pixels = GetImageDataNormalized(*image); // Supports 8 to 32 bit per channel
|
||||
|
||||
free(image->data); // WARNING! We loose mipmaps data --> Regenerated at the end...
|
||||
image->data = NULL;
|
||||
@@ -677,18 +822,18 @@ void ImageFormat(Image *image, int newFormat)
|
||||
|
||||
for (int i = 0; i < image->width*image->height; i++)
|
||||
{
|
||||
((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[i].r*0.299f + (float)pixels[i].g*0.587f + (float)pixels[i].b*0.114f);
|
||||
((unsigned char *)image->data)[i] = (unsigned char)((pixels[i].x*0.299f + pixels[i].y*0.587f + pixels[i].z*0.114f)*255.0f);
|
||||
}
|
||||
|
||||
} break;
|
||||
case UNCOMPRESSED_GRAY_ALPHA:
|
||||
{
|
||||
image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char));
|
||||
image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char));
|
||||
|
||||
for (int i = 0; i < image->width*image->height*2; i += 2, k++)
|
||||
for (int i = 0; i < image->width*image->height*2; i += 2, k++)
|
||||
{
|
||||
((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
|
||||
((unsigned char *)image->data)[i + 1] = pixels[k].a;
|
||||
((unsigned char *)image->data)[i] = (unsigned char)((pixels[k].x*0.299f + (float)pixels[k].y*0.587f + (float)pixels[k].z*0.114f)*255.0f);
|
||||
((unsigned char *)image->data)[i + 1] = (unsigned char)(pixels[k].w*255.0f);
|
||||
}
|
||||
|
||||
} break;
|
||||
@@ -702,9 +847,9 @@ void ImageFormat(Image *image, int newFormat)
|
||||
|
||||
for (int i = 0; i < image->width*image->height; i++)
|
||||
{
|
||||
r = (unsigned char)(round((float)pixels[i].r*31.0f/255));
|
||||
g = (unsigned char)(round((float)pixels[i].g*63.0f/255));
|
||||
b = (unsigned char)(round((float)pixels[i].b*31.0f/255));
|
||||
r = (unsigned char)(round(pixels[i].x*31.0f));
|
||||
g = (unsigned char)(round(pixels[i].y*63.0f));
|
||||
b = (unsigned char)(round(pixels[i].z*31.0f));
|
||||
|
||||
((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b;
|
||||
}
|
||||
@@ -716,9 +861,9 @@ void ImageFormat(Image *image, int newFormat)
|
||||
|
||||
for (int i = 0, k = 0; i < image->width*image->height*3; i += 3, k++)
|
||||
{
|
||||
((unsigned char *)image->data)[i] = pixels[k].r;
|
||||
((unsigned char *)image->data)[i + 1] = pixels[k].g;
|
||||
((unsigned char *)image->data)[i + 2] = pixels[k].b;
|
||||
((unsigned char *)image->data)[i] = (unsigned char)(pixels[k].x*255.0f);
|
||||
((unsigned char *)image->data)[i + 1] = (unsigned char)(pixels[k].y*255.0f);
|
||||
((unsigned char *)image->data)[i + 2] = (unsigned char)(pixels[k].z*255.0f);
|
||||
}
|
||||
} break;
|
||||
case UNCOMPRESSED_R5G5B5A1:
|
||||
@@ -734,10 +879,10 @@ void ImageFormat(Image *image, int newFormat)
|
||||
|
||||
for (int i = 0; i < image->width*image->height; i++)
|
||||
{
|
||||
r = (unsigned char)(round((float)pixels[i].r*31.0f/255));
|
||||
g = (unsigned char)(round((float)pixels[i].g*31.0f/255));
|
||||
b = (unsigned char)(round((float)pixels[i].b*31.0f/255));
|
||||
a = (pixels[i].a > ALPHA_THRESHOLD) ? 1 : 0;
|
||||
r = (unsigned char)(round(pixels[i].x*31.0f));
|
||||
g = (unsigned char)(round(pixels[i].y*31.0f));
|
||||
b = (unsigned char)(round(pixels[i].z*31.0f));
|
||||
a = (pixels[i].w > ((float)ALPHA_THRESHOLD/255.0f)) ? 1 : 0;
|
||||
|
||||
((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1 | (unsigned short)a;
|
||||
}
|
||||
@@ -754,10 +899,10 @@ void ImageFormat(Image *image, int newFormat)
|
||||
|
||||
for (int i = 0; i < image->width*image->height; i++)
|
||||
{
|
||||
r = (unsigned char)(round((float)pixels[i].r*15.0f/255));
|
||||
g = (unsigned char)(round((float)pixels[i].g*15.0f/255));
|
||||
b = (unsigned char)(round((float)pixels[i].b*15.0f/255));
|
||||
a = (unsigned char)(round((float)pixels[i].a*15.0f/255));
|
||||
r = (unsigned char)(round(pixels[i].x*15.0f));
|
||||
g = (unsigned char)(round(pixels[i].y*15.0f));
|
||||
b = (unsigned char)(round(pixels[i].z*15.0f));
|
||||
a = (unsigned char)(round(pixels[i].w*15.0f));
|
||||
|
||||
((unsigned short *)image->data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8 | (unsigned short)b << 4 | (unsigned short)a;
|
||||
}
|
||||
@@ -769,19 +914,21 @@ void ImageFormat(Image *image, int newFormat)
|
||||
|
||||
for (int i = 0, k = 0; i < image->width*image->height*4; i += 4, k++)
|
||||
{
|
||||
((unsigned char *)image->data)[i] = pixels[k].r;
|
||||
((unsigned char *)image->data)[i + 1] = pixels[k].g;
|
||||
((unsigned char *)image->data)[i + 2] = pixels[k].b;
|
||||
((unsigned char *)image->data)[i + 3] = pixels[k].a;
|
||||
((unsigned char *)image->data)[i] = (unsigned char)(pixels[k].x*255.0f);
|
||||
((unsigned char *)image->data)[i + 1] = (unsigned char)(pixels[k].y*255.0f);
|
||||
((unsigned char *)image->data)[i + 2] = (unsigned char)(pixels[k].z*255.0f);
|
||||
((unsigned char *)image->data)[i + 3] = (unsigned char)(pixels[k].w*255.0f);
|
||||
}
|
||||
} break;
|
||||
case UNCOMPRESSED_R32:
|
||||
{
|
||||
// WARNING: Image is converted to GRAYSCALE eqeuivalent 32bit
|
||||
|
||||
image->data = (float *)malloc(image->width*image->height*sizeof(float));
|
||||
|
||||
for (int i = 0; i < image->width*image->height; i++)
|
||||
{
|
||||
((float *)image->data)[i] = (float)((float)pixels[i].r*0.299f/255.0f + (float)pixels[i].g*0.587f/255.0f + (float)pixels[i].b*0.114f/255.0f);
|
||||
((float *)image->data)[i] = (float)(pixels[i].x*0.299f + pixels[i].y*0.587f + pixels[i].z*0.114f);
|
||||
}
|
||||
} break;
|
||||
case UNCOMPRESSED_R32G32B32:
|
||||
@@ -790,9 +937,9 @@ void ImageFormat(Image *image, int newFormat)
|
||||
|
||||
for (int i = 0, k = 0; i < image->width*image->height*3; i += 3, k++)
|
||||
{
|
||||
((float *)image->data)[i] = (float)pixels[k].r/255.0f;
|
||||
((float *)image->data)[i + 1] = (float)pixels[k].g/255.0f;
|
||||
((float *)image->data)[i + 2] = (float)pixels[k].b/255.0f;
|
||||
((float *)image->data)[i] = pixels[k].x;
|
||||
((float *)image->data)[i + 1] = pixels[k].y;
|
||||
((float *)image->data)[i + 2] = pixels[k].z;
|
||||
}
|
||||
} break;
|
||||
case UNCOMPRESSED_R32G32B32A32:
|
||||
@@ -801,10 +948,10 @@ void ImageFormat(Image *image, int newFormat)
|
||||
|
||||
for (int i = 0, k = 0; i < image->width*image->height*4; i += 4, k++)
|
||||
{
|
||||
((float *)image->data)[i] = (float)pixels[k].r/255.0f;
|
||||
((float *)image->data)[i + 1] = (float)pixels[k].g/255.0f;
|
||||
((float *)image->data)[i + 2] = (float)pixels[k].b/255.0f;
|
||||
((float *)image->data)[i + 3] = (float)pixels[k].a/255.0f;
|
||||
((float *)image->data)[i] = pixels[k].x;
|
||||
((float *)image->data)[i + 1] = pixels[k].y;
|
||||
((float *)image->data)[i + 2] = pixels[k].z;
|
||||
((float *)image->data)[i + 3] = pixels[k].w;
|
||||
}
|
||||
} break;
|
||||
default: break;
|
||||
@@ -812,13 +959,13 @@ void ImageFormat(Image *image, int newFormat)
|
||||
|
||||
free(pixels);
|
||||
pixels = NULL;
|
||||
|
||||
// In case original image had mipmaps, generate mipmaps for formated image
|
||||
// NOTE: Original mipmaps are replaced by new ones, if custom mipmaps were used, they are lost
|
||||
if (image->mipmaps > 1)
|
||||
{
|
||||
image->mipmaps = 1;
|
||||
assert(image->data != NULL);
|
||||
ImageMipmaps(image);
|
||||
if (image->data != NULL) ImageMipmaps(image);
|
||||
}
|
||||
}
|
||||
else TraceLog(LOG_WARNING, "Image data format is compressed, can not be converted");
|
||||
@@ -1064,6 +1211,29 @@ void ImageResizeNN(Image *image,int newWidth,int newHeight)
|
||||
free(pixels);
|
||||
}
|
||||
|
||||
// Resize canvas and fill with color
|
||||
// NOTE: Resize offset is relative to the top-left corner of the original image
|
||||
void ImageResizeCanvas(Image *image, int newWidth,int newHeight, int offsetX, int offsetY, Color color)
|
||||
{
|
||||
Image imTemp = GenImageColor(newWidth, newHeight, color);
|
||||
Rectangle srcRec = { 0, 0, image->width, image->height };
|
||||
Rectangle dstRec = { offsetX, offsetY, srcRec.width, srcRec.height };
|
||||
|
||||
// TODO: Review different scaling situations
|
||||
|
||||
if ((newWidth > image->width) && (newHeight > image->height))
|
||||
{
|
||||
ImageDraw(&imTemp, *image, srcRec, dstRec);
|
||||
ImageFormat(&imTemp, image->format);
|
||||
UnloadImage(*image);
|
||||
*image = imTemp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: ImageCrop(), define proper cropping rectangle
|
||||
}
|
||||
}
|
||||
|
||||
// Generate all mipmap levels for a provided image
|
||||
// NOTE 1: Supports POT and NPOT images
|
||||
// NOTE 2: image.data is scaled to include mipmap levels
|
||||
@@ -1269,7 +1439,6 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec)
|
||||
{
|
||||
srcRec.height = src.height - srcRec.y;
|
||||
TraceLog(LOG_WARNING, "Source rectangle height out of bounds, rescaled height: %i", srcRec.height);
|
||||
cropRequired = true;
|
||||
}
|
||||
|
||||
Image srcCopy = ImageCopy(src); // Make a copy of source image to work with it
|
||||
@@ -1281,10 +1450,7 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec)
|
||||
if (dstRec.y < 0) dstRec.y = 0;
|
||||
|
||||
// Scale source image in case destination rec size is different than source rec size
|
||||
if ((dstRec.width != srcRec.width) || (dstRec.height != srcRec.height))
|
||||
{
|
||||
ImageResize(&srcCopy, dstRec.width, dstRec.height);
|
||||
}
|
||||
if ((dstRec.width != srcRec.width) || (dstRec.height != srcRec.height)) ImageResize(&srcCopy, dstRec.width, dstRec.height);
|
||||
|
||||
if ((dstRec.x + dstRec.width) > dst->width)
|
||||
{
|
||||
@@ -1483,7 +1649,7 @@ void ImageDrawTextEx(Image *dst, Vector2 position, Font font, const char *text,
|
||||
void ImageFlipVertical(Image *image)
|
||||
{
|
||||
Color *srcPixels = GetImageData(*image);
|
||||
Color *dstPixels = (Color *)malloc(sizeof(Color)*image->width*image->height);
|
||||
Color *dstPixels = (Color *)malloc(image->width*image->height*sizeof(Color));
|
||||
|
||||
for (int y = 0; y < image->height; y++)
|
||||
{
|
||||
@@ -1507,7 +1673,7 @@ void ImageFlipVertical(Image *image)
|
||||
void ImageFlipHorizontal(Image *image)
|
||||
{
|
||||
Color *srcPixels = GetImageData(*image);
|
||||
Color *dstPixels = (Color *)malloc(sizeof(Color)*image->width*image->height);
|
||||
Color *dstPixels = (Color *)malloc(image->width*image->height*sizeof(Color));
|
||||
|
||||
for (int y = 0; y < image->height; y++)
|
||||
{
|
||||
@@ -1527,6 +1693,58 @@ void ImageFlipHorizontal(Image *image)
|
||||
image->data = processed.data;
|
||||
}
|
||||
|
||||
// Rotate image clockwise 90deg
|
||||
void ImageRotateCW(Image *image)
|
||||
{
|
||||
Color *srcPixels = GetImageData(*image);
|
||||
Color *rotPixels = (Color *)malloc(image->width*image->height*sizeof(Color));
|
||||
|
||||
for (int y = 0; y < image->height; y++)
|
||||
{
|
||||
for (int x = 0; x < image->width; x++)
|
||||
{
|
||||
rotPixels[x*image->height + (image->height - y - 1)] = srcPixels[y*image->width + x];
|
||||
}
|
||||
}
|
||||
|
||||
Image processed = LoadImageEx(rotPixels, image->height, image->width);
|
||||
ImageFormat(&processed, image->format);
|
||||
UnloadImage(*image);
|
||||
|
||||
free(srcPixels);
|
||||
free(rotPixels);
|
||||
|
||||
image->data = processed.data;
|
||||
image->width = processed.width;
|
||||
image->height = processed.height;
|
||||
}
|
||||
|
||||
// Rotate image counter-clockwise 90deg
|
||||
void ImageRotateCCW(Image *image)
|
||||
{
|
||||
Color *srcPixels = GetImageData(*image);
|
||||
Color *rotPixels = (Color *)malloc(image->width*image->height*sizeof(Color));
|
||||
|
||||
for (int y = 0; y < image->height; y++)
|
||||
{
|
||||
for (int x = 0; x < image->width; x++)
|
||||
{
|
||||
rotPixels[x*image->height + y] = srcPixels[y*image->width + (image->width - x - 1)];
|
||||
}
|
||||
}
|
||||
|
||||
Image processed = LoadImageEx(rotPixels, image->height, image->width);
|
||||
ImageFormat(&processed, image->format);
|
||||
UnloadImage(*image);
|
||||
|
||||
free(srcPixels);
|
||||
free(rotPixels);
|
||||
|
||||
image->data = processed.data;
|
||||
image->width = processed.width;
|
||||
image->height = processed.height;
|
||||
}
|
||||
|
||||
// Modify image color: tint
|
||||
void ImageColorTint(Image *image, Color color)
|
||||
{
|
||||
@@ -1683,6 +1901,36 @@ void ImageColorBrightness(Image *image, int brightness)
|
||||
|
||||
image->data = processed.data;
|
||||
}
|
||||
|
||||
// Modify image color: replace color
|
||||
void ImageColorReplace(Image *image, Color color, Color replace)
|
||||
{
|
||||
Color *pixels = GetImageData(*image);
|
||||
|
||||
for (int y = 0; y < image->height; y++)
|
||||
{
|
||||
for (int x = 0; x < image->width; x++)
|
||||
{
|
||||
if ((pixels[y*image->width + x].r == color.r) &&
|
||||
(pixels[y*image->width + x].g == color.g) &&
|
||||
(pixels[y*image->width + x].b == color.b) &&
|
||||
(pixels[y*image->width + x].a == color.a))
|
||||
{
|
||||
pixels[y*image->width + x].r = replace.r;
|
||||
pixels[y*image->width + x].g = replace.g;
|
||||
pixels[y*image->width + x].b = replace.b;
|
||||
pixels[y*image->width + x].a = replace.a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image processed = LoadImageEx(pixels, image->width, image->height);
|
||||
ImageFormat(&processed, image->format);
|
||||
UnloadImage(*image);
|
||||
free(pixels);
|
||||
|
||||
image->data = processed.data;
|
||||
}
|
||||
#endif // SUPPORT_IMAGE_MANIPULATION
|
||||
|
||||
#if defined(SUPPORT_IMAGE_GENERATION)
|
||||
@@ -2020,9 +2268,9 @@ void DrawTextureV(Texture2D texture, Vector2 position, Color tint)
|
||||
// Draw a Texture2D with extended parameters
|
||||
void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint)
|
||||
{
|
||||
Rectangle sourceRec = { 0, 0, texture.width, texture.height };
|
||||
Rectangle destRec = { position.x, position.y, texture.width*scale, texture.height*scale };
|
||||
Vector2 origin = { 0, 0 };
|
||||
Rectangle sourceRec = { 0.0f, 0.0f, (float)texture.width, (float)texture.height };
|
||||
Rectangle destRec = { position.x, position.y, (float)texture.width*scale, (float)texture.height*scale };
|
||||
Vector2 origin = { 0.0f, 0.0f };
|
||||
|
||||
DrawTexturePro(texture, sourceRec, destRec, origin, rotation, tint);
|
||||
}
|
||||
@@ -2030,8 +2278,8 @@ void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float sc
|
||||
// Draw a part of a texture (defined by a rectangle)
|
||||
void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint)
|
||||
{
|
||||
Rectangle destRec = { position.x, position.y, sourceRec.width, fabsf(sourceRec.height) };
|
||||
Vector2 origin = { 0, 0 };
|
||||
Rectangle destRec = { position.x, position.y, sourceRec.width, fabs(sourceRec.height) };
|
||||
Vector2 origin = { 0.0f, 0.0f };
|
||||
|
||||
DrawTexturePro(texture, sourceRec, destRec, origin, 0.0f, tint);
|
||||
}
|
||||
@@ -2043,6 +2291,9 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V
|
||||
// Check if texture is valid
|
||||
if (texture.id > 0)
|
||||
{
|
||||
float width = (float)texture.width;
|
||||
float height = (float)texture.height;
|
||||
|
||||
if (sourceRec.width < 0) sourceRec.x -= sourceRec.width;
|
||||
if (sourceRec.height < 0) sourceRec.y -= sourceRec.height;
|
||||
|
||||
@@ -2058,19 +2309,19 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V
|
||||
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
||||
|
||||
// Bottom-left corner for texture and quad
|
||||
rlTexCoord2f(sourceRec.x/texture.width, sourceRec.y/texture.height);
|
||||
rlTexCoord2f(sourceRec.x/width, sourceRec.y/height);
|
||||
rlVertex2f(0.0f, 0.0f);
|
||||
|
||||
// Bottom-right corner for texture and quad
|
||||
rlTexCoord2f(sourceRec.x/texture.width, (sourceRec.y + sourceRec.height)/texture.height);
|
||||
rlTexCoord2f(sourceRec.x/width, (sourceRec.y + sourceRec.height)/height);
|
||||
rlVertex2f(0.0f, destRec.height);
|
||||
|
||||
// Top-right corner for texture and quad
|
||||
rlTexCoord2f((sourceRec.x + sourceRec.width)/texture.width, (sourceRec.y + sourceRec.height)/texture.height);
|
||||
rlTexCoord2f((sourceRec.x + sourceRec.width)/width, (sourceRec.y + sourceRec.height)/height);
|
||||
rlVertex2f(destRec.width, destRec.height);
|
||||
|
||||
// Top-left corner for texture and quad
|
||||
rlTexCoord2f((sourceRec.x + sourceRec.width)/texture.width, sourceRec.y/texture.height);
|
||||
rlTexCoord2f((sourceRec.x + sourceRec.width)/width, sourceRec.y/height);
|
||||
rlVertex2f(destRec.width, 0.0f);
|
||||
rlEnd();
|
||||
rlPopMatrix();
|
||||
|
Reference in New Issue
Block a user