diff --git a/CHANGELOG b/CHANGELOG
index 5024dc6ef..d8370b61a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,20 +1,20 @@
changelog
---------
-Current Release: raylib 1.5.0 (23 June 2016)
+Current Release: raylib 1.5.0 (xx June 2016)
NOTE: Only versions marked as 'Release' are available in installer, updates are only available as source.
NOTE: Current Release includes all previous updates.
-----------------------------------------------
-Release: raylib 1.5.0 (23 June 2016)
+Release: raylib 1.5.0 (xx June 2016)
-----------------------------------------------
NOTE:
Probably this new version is the biggest boost of the library ever, lots of parts of the library have been redesigned,
lots of bugs have been solved and some **AMAZING** new features have been added.
HUGE changes:
-[core] OCULUS RIFT CV1: Added support for VR witha bunch of Oculus-specific functions to init/close device and Oculus rendering.
+[rlgl] OCULUS RIFT CV1: Added support for VR witha bunch of Oculus-specific functions to init/close device and Oculus rendering.
[rlgl] MATERIALS SYSTEM: Added support for Materials (.mtl) and multiple material properties: diffuse, specular, normal.
[rlgl] LIGHTING SYSTEM: Added support for up to 8 lights of 3 different types: Omni, Directional and Spot
[physac] REDESIGNED: Improved performance and simplified usage, physic objects are managed internally
@@ -27,6 +27,7 @@ other changes:
[core] Renamed WorldToScreen() to GetWorldToScreen()
[core] Removed function SetCustomCursor()
[core] Removed functions BeginDrawingEx(), BeginDrawingPro()
+[core] Replaced functions InitDisplay() + InitGraphics() with: InitGraphicsDevice()
[core] Added support for field-of-view Y (fovy) on 3d Camera
[core] Added 2D camera mode functions: Begin2dMode() - End2dMode()
[core] Translate mouse inputs to Android touch/gestures internally
@@ -36,6 +37,7 @@ other changes:
[rlgl] Improved 2D vs 3D drawing system (lines, triangles, quads)
[rlgl] Improved DXT-ETC1 support on HTML5
[rlgl] Review function: rlglUnproject()
+[rlgl] Removed function: rlglInitGraphics(), integrated into rlglInit()
[rlgl] Updated Mesh and Shader structs
[rlgl] Simplified internal (default) dynamic buffers
[rlgl] Added support for indexed and dynamic mesh data
@@ -65,6 +67,7 @@ other changes:
[models] Updated BoundingBox collision detections
[models] Added color parameter to DrawBoundigBox()
[models] Removed function: DrawQuad()
+[models] Removed function: SetModelTexture()
[models] Redesigned DrawPlane() to use RL_TRIANGLES
[models] Redesigned DrawRectangleV() to use RL_TRIANGLES
[models] Redesign to accomodate new materials system: LoadMaterial()
diff --git a/README.md b/README.md
index 6228a54a7..c5021ef2d 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-
+
about
-----
diff --git a/examples/Makefile b/examples/Makefile
index 2d2344afa..711f03a70 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -78,44 +78,38 @@ endif
#CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes
# define any directories containing required header files
+INCLUDES = -I. -I../src -I../src/external
+
ifeq ($(PLATFORM),PLATFORM_RPI)
- INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
+ INCLUDES += -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
endif
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
# add standard directories for GNU/Linux
ifeq ($(PLATFORM_OS),LINUX)
- INCLUDES = -I. -I../src -I/usr/local/include/raylib/
- else ifeq ($(PLATFORM_OS),OSX)
- INCLUDES = -I. -I../src
- else
- INCLUDES = -I. -I../../src -IC:/raylib/raylib/src
+ INCLUDES += -I/usr/local/include/raylib/
+ else ifeq ($(PLATFORM_OS),WINDOWS)
# external libraries headers
# GLFW3
- INCLUDES += -I../../external/glfw3/include
+ INCLUDES += -I../src/external/glfw3/include
# OpenAL Soft
- INCLUDES += -I../../external/openal_soft/include
+ INCLUDES += -I../src/external/openal_soft/include
endif
endif
# define library paths containing required libs
+LFLAGS = -L. -L../src
+
ifeq ($(PLATFORM),PLATFORM_RPI)
- LFLAGS = -L. -L../../src -L/opt/vc/lib
+ LFLAGS += -L/opt/vc/lib
endif
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
# add standard directories for GNU/Linux
- ifeq ($(PLATFORM_OS),LINUX)
- LFLAGS = -L. -L../../src
- else ifeq ($(PLATFORM_OS),OSX)
- LFLAGS = -L. -L../src
- else
- LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+ ifeq ($(PLATFORM_OS),WINDOWS)
# external libraries to link with
# GLFW3
- LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
- ifneq ($(PLATFORM_OS),OSX)
+ LFLAGS += -L../src/external/glfw3/lib/$(LIBPATH)
# OpenAL Soft
- LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
- endif
+ LFLAGS += -L../src/external/openal_soft/lib/$(LIBPATH)
endif
endif
@@ -148,7 +142,7 @@ ifeq ($(PLATFORM),PLATFORM_RPI)
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
# just adjust the correct path to libraylib.bc
- LIBS = ../src/libraylib.bc
+ LIBS = ../release/html5/libraylib.bc
endif
# define additional parameters and flags for windows
@@ -178,6 +172,9 @@ EXAMPLES = \
core_3d_picking \
core_3d_camera_free \
core_3d_camera_first_person \
+ core_2d_camera \
+ core_world_screen \
+ core_oculus_rift \
shapes_logo_raylib \
shapes_basic_shapes \
shapes_colors_palette \
@@ -208,6 +205,7 @@ EXAMPLES = \
shaders_shapes_textures \
shaders_custom_uniform \
shaders_postprocessing \
+ shaders_standard_lighting \
audio_sound_loading \
audio_music_stream \
fix_dylib \
@@ -287,7 +285,19 @@ core_3d_camera_free: core_3d_camera_free.c
# compile [core] example - 3d camera first person
core_3d_camera_first_person: core_3d_camera_first_person.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile [core] example - 2d camera
+core_2d_camera: core_2d_camera.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+# compile [core] example - world screen
+core_world_screen: core_world_screen.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile [core] example - oculus rift
+core_oculus_rift: core_oculus_rift.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
# compile [shapes] example - raylib logo (with basic shapes)
shapes_logo_raylib: shapes_logo_raylib.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
@@ -411,7 +421,11 @@ shaders_custom_uniform: shaders_custom_uniform.c
# compile [shaders] example - postprocessing shader
shaders_postprocessing: shaders_postprocessing.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
-
+
+# compile [shaders] example - standard lighting
+shaders_standard_lighting: shaders_standard_lighting.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
# compile [audio] example - sound loading and playing (WAV and OGG)
audio_sound_loading: audio_sound_loading.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
diff --git a/examples/audio_music_stream.c b/examples/audio_music_stream.c
index 8c668cce7..e135a6e44 100644
--- a/examples/audio_music_stream.c
+++ b/examples/audio_music_stream.c
@@ -24,7 +24,7 @@ int main()
InitAudioDevice(); // Initialize audio device
- PlayMusicStream("resources/audio/guitar_noodling.ogg"); // Play music stream
+ PlayMusicStream(0, "resources/audio/guitar_noodling.ogg"); // Play music stream
int framesCounter = 0;
float timePlayed = 0.0f;
@@ -52,18 +52,18 @@ int main()
{
volume = 1.0;
framesCounter = 0;
- PlayMusicStream("resources/audio/another_file.ogg");
+ PlayMusicStream(1, "resources/audio/another_file.ogg");
}
SetMusicVolume(volume);
}
*/
- if (IsWindowMinimized()) PauseMusicStream();
- else ResumeMusicStream();
+ if (IsWindowMinimized()) PauseMusicStream(0);
+ else ResumeMusicStream(0);
- timePlayed = GetMusicTimePlayed()/GetMusicTimeLength()*100*4; // We scale by 4 to fit 400 pixels
+ timePlayed = GetMusicTimePlayed(0)/GetMusicTimeLength(0)*100*4; // We scale by 4 to fit 400 pixels
- UpdateMusicStream(); // Update music buffer with new stream data
+ UpdateMusicStream(0); // Update music buffer with new stream data
//----------------------------------------------------------------------------------
// Draw
diff --git a/examples/core_2d_camera.c b/examples/core_2d_camera.c
index 73e1d65f3..f2f219ef4 100644
--- a/examples/core_2d_camera.c
+++ b/examples/core_2d_camera.c
@@ -23,8 +23,8 @@ int main()
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera");
Rectangle player = { 400, 280, 40, 40 };
- Rectangle buildings[MAX_BUILDINGS] = { 0, 0, 0, 0 };
- Color buildColors[MAX_BUILDINGS] = { 80, 80, 80, 255 };
+ Rectangle buildings[MAX_BUILDINGS];
+ Color buildColors[MAX_BUILDINGS];
int spacing = 0;
diff --git a/examples/core_color_select.c b/examples/core_color_select.c
index 118dc88a9..002a69312 100644
--- a/examples/core_color_select.c
+++ b/examples/core_color_select.c
@@ -16,7 +16,7 @@ int main()
// Initialization
//--------------------------------------------------------------------------------------
int screenWidth = 800;
- int screenHeight = 400;
+ int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - color selection (collision detection)");
@@ -30,7 +30,7 @@ int main()
for (int i = 0; i < 21; i++)
{
colorsRecs[i].x = 20 + 100*(i%7) + 10*(i%7);
- colorsRecs[i].y = 40 + 100*(i/7) + 10*(i/7);
+ colorsRecs[i].y = 60 + 100*(i/7) + 10*(i/7);
colorsRecs[i].width = 100;
colorsRecs[i].height = 100;
}
diff --git a/examples/core_oculus_rift.c b/examples/core_oculus_rift.c
index 865178295..734ba8fd9 100644
--- a/examples/core_oculus_rift.c
+++ b/examples/core_oculus_rift.c
@@ -30,11 +30,11 @@ int main()
camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
- camera.fovy = 45.0f; // Camera field-of-view Y
+ camera.fovy = 60.0f; // Camera field-of-view Y
Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
- //SetTargetFPS(90); // Set our game to run at 90 frames-per-second
+ SetTargetFPS(90); // Set our game to run at 90 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
@@ -43,31 +43,30 @@ int main()
// Update
//----------------------------------------------------------------------------------
UpdateOculusTracking();
+
+ if (IsKeyPressed(KEY_SPACE)) ToggleVR();
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
-
+
ClearBackground(RAYWHITE);
- BeginOculusDrawing();
-
- for (int eye = 0; eye < 2; eye++)
- {
- Begin3dMode(camera);
+ if (IsOculusReady()) BeginOculusDrawing();
+
+ Begin3dMode(camera);
+
+ DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
+ DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
- SetOculusMatrix(eye);
-
- DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
- DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
-
- DrawGrid(10, 1.0f);
-
- End3dMode();
- }
+ DrawGrid(10, 1.0f);
- EndOculusDrawing();
+ End3dMode();
+
+ if (IsOculusReady()) EndOculusDrawing();
+
+ DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
diff --git a/examples/core_world_screen.c b/examples/core_world_screen.c
index f3798830d..aa9505e8b 100644
--- a/examples/core_world_screen.c
+++ b/examples/core_world_screen.c
@@ -63,7 +63,6 @@ int main()
DrawText("Enemy: 100 / 100", cubeScreenPosition.x - MeasureText("Enemy: 100 / 100", 20) / 2, cubeScreenPosition.y, 20, BLACK);
DrawText("Text is always on top of the cube", (screenWidth - MeasureText("Text is always on top of the cube", 20)) / 2, 25, 20, GRAY);
-
EndDrawing();
//----------------------------------------------------------------------------------
diff --git a/examples/models_cubicmap.c b/examples/models_cubicmap.c
index 1ca27dfd2..89bc75cf5 100644
--- a/examples/models_cubicmap.c
+++ b/examples/models_cubicmap.c
@@ -29,7 +29,7 @@ int main()
// NOTE: By default each cube is mapped to one part of texture atlas
Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture
- SetModelTexture(&map, texture); // Bind texture to map model
+ map.material.texDiffuse = texture; // Set map diffuse texture
Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position
diff --git a/examples/models_heightmap.c b/examples/models_heightmap.c
index c8e5ff35f..90e5f5bb3 100644
--- a/examples/models_heightmap.c
+++ b/examples/models_heightmap.c
@@ -26,7 +26,7 @@ int main()
Image image = LoadImage("resources/heightmap.png"); // Load heightmap image (RAM)
Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM)
Model map = LoadHeightmap(image, (Vector3){ 16, 8, 16 }); // Load heightmap model with defined size
- SetModelTexture(&map, texture); // Bind texture to model
+ map.material.texDiffuse = texture; // Set map diffuse texture
Vector3 mapPosition = { -8.0f, 0.0f, -8.0f }; // Set model position (depends on model scaling!)
UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM
diff --git a/examples/models_obj_loading.c b/examples/models_obj_loading.c
index e8dd0adc1..a6969f705 100644
--- a/examples/models_obj_loading.c
+++ b/examples/models_obj_loading.c
@@ -25,7 +25,7 @@ int main()
Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model
Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture
- SetModelTexture(&dwarf, texture); // Bind texture to model
+ dwarf.material.texDiffuse = texture; // Set dwarf model diffuse texture
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
diff --git a/examples/oculus_glfw_sample/rlgl_standalone.c b/examples/oculus_glfw_sample/rlgl_standalone.c
index 4728160a0..33e916312 100644
--- a/examples/oculus_glfw_sample/rlgl_standalone.c
+++ b/examples/oculus_glfw_sample/rlgl_standalone.c
@@ -96,11 +96,19 @@ int main(void)
// Initialize rlgl internal buffers and OpenGL state
rlglInit();
- rlglInitGraphics(0, 0, screenWidth, screenHeight);
- rlClearColor(245, 245, 245, 255); // Define clear color
- rlEnableDepthTest(); // Enable DEPTH_TEST for 3D
- Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
+ // Initialize viewport and internal projection/modelview matrices
+ rlViewport(0, 0, screenWidth, screenHeight);
+ rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix
+ rlLoadIdentity(); // Reset current matrix (PROJECTION)
+ rlOrtho(0, screenWidth, screenHeight, 0, 0.0f, 1.0f); // Orthographic projection with top-left corner at (0,0)
+ rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix
+ rlLoadIdentity(); // Reset current matrix (MODELVIEW)
+
+ rlClearColor(245, 245, 245, 255); // Define clear color
+ rlEnableDepthTest(); // Enable DEPTH_TEST for 3D
+
+ Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; // Cube default position (center)
Camera camera;
camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position
diff --git a/examples/oculus_glfw_sample/rlgl_standalone_stereo.c b/examples/oculus_glfw_sample/rlgl_standalone_stereo.c
index 1955d11e7..fa7f3e4ae 100644
--- a/examples/oculus_glfw_sample/rlgl_standalone_stereo.c
+++ b/examples/oculus_glfw_sample/rlgl_standalone_stereo.c
@@ -184,7 +184,7 @@ int main(void)
rlMatrixMode(RL_PROJECTION); // Enable internal projection matrix
rlLoadIdentity(); // Reset internal projection matrix
- rlOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0); // Recalculate internal projection matrix
+ rlOrtho(0.0, screenWidth/2, screenHeight, 0.0, 0.0, 1.0); // Recalculate internal projection matrix
rlMatrixMode(RL_MODELVIEW); // Enable internal modelview matrix
rlLoadIdentity(); // Reset internal modelview matrix
#endif
diff --git a/examples/resources/shaders/glsl100/distortion.fs b/examples/resources/shaders/glsl100/distortion.fs
new file mode 100644
index 000000000..a0a6cc18e
--- /dev/null
+++ b/examples/resources/shaders/glsl100/distortion.fs
@@ -0,0 +1,66 @@
+#version 100
+
+precision mediump float;
+
+// Input vertex attributes (from vertex shader)
+varying vec2 fragTexCoord;
+
+// Input uniform values
+uniform sampler2D texture0;
+
+// NOTE: Add here your custom variables
+const vec2 LeftLensCenter = vec2(0.2863248, 0.5);
+const vec2 RightLensCenter = vec2(0.7136753, 0.5);
+const vec2 LeftScreenCenter = vec2(0.25, 0.5);
+const vec2 RightScreenCenter = vec2(0.75, 0.5);
+const vec2 Scale = vec2(0.25, 0.45); //vec2(0.1469278, 0.2350845);
+const vec2 ScaleIn = vec2(4, 2.2222);
+const vec4 HmdWarpParam = vec4(1, 0.22, 0.24, 0);
+const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0);
+
+/*
+// Another set of default values
+ChromaAbCorrection = {1.0, 0.0, 1.0, 0}
+DistortionK = {1.0, 0.22, 0.24, 0}
+Scale = {0.25, 0.5*AspectRatio, 0, 0}
+ScaleIn = {4.0, 2/AspectRatio, 0, 0}
+Left Screen Center = {0.25, 0.5, 0, 0}
+Left Lens Center = {0.287994117, 0.5, 0, 0}
+Right Screen Center = {0.75, 0.5, 0, 0}
+Right Lens Center = {0.712005913, 0.5, 0, 0}
+*/
+
+void main()
+{
+ // The following two variables need to be set per eye
+ vec2 LensCenter = fragTexCoord.x < 0.5 ? LeftLensCenter : RightLensCenter;
+ vec2 ScreenCenter = fragTexCoord.x < 0.5 ? LeftScreenCenter : RightScreenCenter;
+
+ // Scales input texture coordinates for distortion: vec2 HmdWarp(vec2 fragTexCoord, vec2 LensCenter)
+ vec2 theta = (fragTexCoord - LensCenter)*ScaleIn; // Scales to [-1, 1]
+ float rSq = theta.x*theta.x + theta.y*theta.y;
+ vec2 theta1 = theta*(HmdWarpParam.x + HmdWarpParam.y*rSq + HmdWarpParam.z*rSq*rSq + HmdWarpParam.w*rSq*rSq*rSq);
+ //vec2 tc = LensCenter + Scale*theta1;
+
+ // Detect whether blue texture coordinates are out of range since these will scaled out the furthest
+ vec2 thetaBlue = theta1*(ChromaAbParam.z + ChromaAbParam.w*rSq);
+ vec2 tcBlue = LensCenter + Scale*thetaBlue;
+
+ if (any(bvec2(clamp(tcBlue, ScreenCenter - vec2(0.25, 0.5), ScreenCenter + vec2(0.25, 0.5)) - tcBlue))) gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ else
+ {
+ // Do blue texture lookup
+ float blue = texture2D(texture0, tcBlue).b;
+
+ // Do green lookup (no scaling)
+ vec2 tcGreen = LensCenter + Scale*theta1;
+ float green = texture2D(texture0, tcGreen).g;
+
+ // Do red scale and lookup
+ vec2 thetaRed = theta1*(ChromaAbParam.x + ChromaAbParam.y*rSq);
+ vec2 tcRed = LensCenter + Scale*thetaRed;
+ float red = texture2D(texture0, tcRed).r;
+
+ gl_FragColor = vec4(red, green, blue, 1.0);
+ }
+}
diff --git a/examples/resources/shaders/glsl330/distortion.fs b/examples/resources/shaders/glsl330/distortion.fs
new file mode 100644
index 000000000..62856341b
--- /dev/null
+++ b/examples/resources/shaders/glsl330/distortion.fs
@@ -0,0 +1,69 @@
+#version 330
+
+// Input vertex attributes (from vertex shader)
+in vec2 fragTexCoord;
+
+// Input uniform values
+uniform sampler2D texture0;
+
+// Output fragment color
+out vec4 finalColor;
+
+// NOTE: Add here your custom variables
+const vec2 LeftLensCenter = vec2(0.288, 0.5);
+const vec2 RightLensCenter = vec2(0.712, 0.5);
+const vec2 LeftScreenCenter = vec2(0.25, 0.5);
+const vec2 RightScreenCenter = vec2(0.75, 0.5);
+uniform vec2 Scale = vec2(0.25, 0.45); //vec2(0.1469278, 0.2350845);
+uniform vec2 ScaleIn = vec2(4, 2.2222);
+
+const vec4 HmdWarpParam = vec4(1, 0.22, 0.24, 0);
+const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0);
+
+/*
+// Another set of default values
+ChromaAbCorrection = {1.0, 0.0, 1.0, 0}
+DistortionK = {1.0, 0.22, 0.24, 0}
+Scale = {0.25, 0.5*AspectRatio, 0, 0}
+ScaleIn = {4.0, 2/AspectRatio, 0, 0}
+Left Screen Center = {0.25, 0.5, 0, 0}
+Left Lens Center = {0.287994117, 0.5, 0, 0}
+Right Screen Center = {0.75, 0.5, 0, 0}
+Right Lens Center = {0.712005913, 0.5, 0, 0}
+*/
+
+void main()
+{
+ // The following two variables need to be set per eye
+ vec2 LensCenter = fragTexCoord.x < 0.5 ? LeftLensCenter : RightLensCenter;
+ vec2 ScreenCenter = fragTexCoord.x < 0.5 ? LeftScreenCenter : RightScreenCenter;
+
+ // Scales input texture coordinates for distortion: vec2 HmdWarp(vec2 fragTexCoord, vec2 LensCenter)
+ vec2 theta = (fragTexCoord - LensCenter)*ScaleIn; // Scales to [-1, 1]
+ float rSq = theta.x*theta.x + theta.y*theta.y;
+ vec2 theta1 = theta*(HmdWarpParam.x + HmdWarpParam.y*rSq + HmdWarpParam.z*rSq*rSq + HmdWarpParam.w*rSq*rSq*rSq);
+ //vec2 tc = LensCenter + Scale*theta1;
+
+ // Detect whether blue texture coordinates are out of range since these will scaled out the furthest
+ vec2 thetaBlue = theta1*(ChromaAbParam.z + ChromaAbParam.w*rSq);
+ vec2 tcBlue = LensCenter + Scale*thetaBlue;
+
+ if (any(bvec2(clamp(tcBlue, ScreenCenter - vec2(0.25, 0.5), ScreenCenter + vec2(0.25, 0.5)) - tcBlue))) finalColor = vec4(0.0, 0.0, 0.0, 1.0);
+ else
+ {
+ // Do blue texture lookup
+ float blue = texture(texture0, tcBlue).b;
+
+ // Do green lookup (no scaling)
+ vec2 tcGreen = LensCenter + Scale*theta1;
+ float green = texture(texture0, tcGreen).g;
+
+ // Do red scale and lookup
+ vec2 thetaRed = theta1*(ChromaAbParam.x + ChromaAbParam.y*rSq);
+ vec2 tcRed = LensCenter + Scale*thetaRed;
+ float red = texture(texture0, tcRed).r;
+
+ finalColor = vec4(red, green, blue, 1.0);
+ }
+}
+
diff --git a/examples/shaders_custom_uniform.c b/examples/shaders_custom_uniform.c
index 516d5087c..c4f87259c 100644
--- a/examples/shaders_custom_uniform.c
+++ b/examples/shaders_custom_uniform.c
@@ -34,7 +34,7 @@ int main()
Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model
Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture (diffuse map)
- SetModelTexture(&dwarf, texture); // Bind texture to model
+ dwarf.material.texDiffuse = texture; // Set dwarf model diffuse texture
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
diff --git a/examples/shaders_postprocessing.c b/examples/shaders_postprocessing.c
index 5e8b5a804..43d21e082 100644
--- a/examples/shaders_postprocessing.c
+++ b/examples/shaders_postprocessing.c
@@ -34,7 +34,7 @@ int main()
Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model
Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture (diffuse map)
- SetModelTexture(&dwarf, texture); // Bind texture to model
+ dwarf.material.texDiffuse = texture; // Set dwarf model diffuse texture
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
diff --git a/games/raylib_demo/raylib_demo.c b/games/raylib_demo/raylib_demo.c
index 7f6f291a3..22213b467 100644
--- a/games/raylib_demo/raylib_demo.c
+++ b/games/raylib_demo/raylib_demo.c
@@ -202,8 +202,8 @@ int main()
camera = (Camera){{ 0.0, 12.0, 15.0 }, { 0.0, 3.0, 0.0 }, { 0.0, 1.0, 0.0 }};
catTexture = LoadTexture("resources/catsham.png"); // Load model texture
- cat = LoadModel("resources/cat.obj"); // Load OBJ model
- SetModelTexture(&cat, catTexture);
+ cat = LoadModel("resources/cat.obj"); // Load OBJ model
+ cat.material.texDiffuse = texture; // Set cat model diffuse texture
fxWav = LoadSound("resources/audio/weird.wav"); // Load WAV audio file
fxOgg = LoadSound("resources/audio/tanatana.ogg"); // Load OGG audio file
diff --git a/shaders/glsl100/standard.fs b/shaders/glsl100/standard.fs
new file mode 100644
index 000000000..d5daa4452
--- /dev/null
+++ b/shaders/glsl100/standard.fs
@@ -0,0 +1,155 @@
+#version 100
+
+precision mediump float;
+
+varying vec3 fragPosition;
+varying vec2 fragTexCoord;
+varying vec4 fragColor;
+varying vec3 fragNormal;
+
+uniform sampler2D texture0;
+uniform sampler2D texture1;
+uniform sampler2D texture2;
+
+uniform vec4 colAmbient;
+uniform vec4 colDiffuse;
+uniform vec4 colSpecular;
+uniform float glossiness;
+
+uniform int useNormal;
+uniform int useSpecular;
+
+uniform mat4 modelMatrix;
+uniform vec3 viewDir;
+
+struct Light {
+ int enabled;
+ int type;
+ vec3 position;
+ vec3 direction;
+ vec4 diffuse;
+ float intensity;
+ float radius;
+ float coneAngle;
+};
+
+const int maxLights = 8;
+uniform int lightsCount;
+uniform Light lights[maxLights];
+
+vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s)
+{
+ vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));
+ vec3 surfaceToLight = l.position - surfacePos;
+
+ // Diffuse shading
+ float brightness = clamp(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n)), 0, 1);
+ float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*brightness*l.intensity;
+
+ // Specular shading
+ float spec = 0.0;
+ if (diff > 0.0)
+ {
+ vec3 h = normalize(-l.direction + v);
+ spec = pow(dot(n, h), 3 + glossiness)*s;
+ }
+
+ return (diff*l.diffuse.rgb + spec*colSpecular.rgb);
+}
+
+vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s)
+{
+ vec3 lightDir = normalize(-l.direction);
+
+ // Diffuse shading
+ float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;
+
+ // Specular shading
+ float spec = 0.0;
+ if (diff > 0.0)
+ {
+ vec3 h = normalize(lightDir + v);
+ spec = pow(dot(n, h), 3 + glossiness)*s;
+ }
+
+ // Combine results
+ return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);
+}
+
+vec3 CalcSpotLight(Light l, vec3 n, vec3 v, float s)
+{
+ vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));
+ vec3 lightToSurface = normalize(surfacePos - l.position);
+ vec3 lightDir = normalize(-l.direction);
+
+ // Diffuse shading
+ float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;
+
+ // Spot attenuation
+ float attenuation = clamp(dot(n, lightToSurface), 0.0, 1.0);
+ attenuation = dot(lightToSurface, -lightDir);
+
+ float lightToSurfaceAngle = degrees(acos(attenuation));
+ if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0;
+
+ float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle;
+
+ // Combine diffuse and attenuation
+ float diffAttenuation = diff*attenuation;
+
+ // Specular shading
+ float spec = 0.0;
+ if (diffAttenuation > 0.0)
+ {
+ vec3 h = normalize(lightDir + v);
+ spec = pow(dot(n, h), 3 + glossiness)*s;
+ }
+
+ return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));
+}
+
+void main()
+{
+ // Calculate fragment normal in screen space
+ // NOTE: important to multiply model matrix by fragment normal to apply model transformation (rotation and scale)
+ mat3 normalMatrix = transpose(inverse(mat3(modelMatrix)));
+ vec3 normal = normalize(normalMatrix*fragNormal);
+
+ // Normalize normal and view direction vectors
+ vec3 n = normalize(normal);
+ vec3 v = normalize(viewDir);
+
+ // Calculate diffuse texture color fetching
+ vec4 texelColor = texture2D(texture0, fragTexCoord);
+ vec3 lighting = colAmbient.rgb;
+
+ // Calculate normal texture color fetching or set to maximum normal value by default
+ if (useNormal == 1)
+ {
+ n *= texture2D(texture1, fragTexCoord).rgb;
+ n = normalize(n);
+ }
+
+ // Calculate specular texture color fetching or set to maximum specular value by default
+ float spec = 1.0;
+ if (useSpecular == 1) spec *= normalize(texture2D(texture2, fragTexCoord).r);
+
+ for (int i = 0; i < lightsCount; i++)
+ {
+ // Check if light is enabled
+ if (lights[i].enabled == 1)
+ {
+ // Calculate lighting based on light type
+ switch (lights[i].type)
+ {
+ case 0: lighting += CalcPointLight(lights[i], n, v, spec); break;
+ case 1: lighting += CalcDirectionalLight(lights[i], n, v, spec); break;
+ case 2: lighting += CalcSpotLight(lights[i], n, v, spec); break;
+ default: break;
+ }
+ }
+ }
+
+ // Calculate final fragment color
+ gl_FragColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a);
+}
diff --git a/shaders/glsl100/standard.vs b/shaders/glsl100/standard.vs
new file mode 100644
index 000000000..49c5a3ebf
--- /dev/null
+++ b/shaders/glsl100/standard.vs
@@ -0,0 +1,23 @@
+#version 100
+
+attribute vec3 vertexPosition;
+attribute vec3 vertexNormal;
+attribute vec2 vertexTexCoord;
+attribute vec4 vertexColor;
+
+varying vec3 fragPosition;
+varying vec2 fragTexCoord;
+varying vec4 fragColor;
+varying vec3 fragNormal;
+
+uniform mat4 mvpMatrix;
+
+void main()
+{
+ fragPosition = vertexPosition;
+ fragTexCoord = vertexTexCoord;
+ fragColor = vertexColor;
+ fragNormal = vertexNormal;
+
+ gl_Position = mvpMatrix*vec4(vertexPosition, 1.0);
+}
\ No newline at end of file
diff --git a/examples/resources/shaders/standard.fs b/shaders/glsl330/standard.fs
similarity index 100%
rename from examples/resources/shaders/standard.fs
rename to shaders/glsl330/standard.fs
diff --git a/examples/resources/shaders/standard.vs b/shaders/glsl330/standard.vs
similarity index 100%
rename from examples/resources/shaders/standard.vs
rename to shaders/glsl330/standard.vs
diff --git a/src/Makefile b/src/Makefile
index ce703c3a1..33b666b4f 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -51,6 +51,7 @@ ifeq ($(PLATFORM),PLATFORM_RPI)
else
# define raylib graphics api to use (OpenGL 1.1 by default)
GRAPHICS ?= GRAPHICS_API_OPENGL_11
+ #GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1
#GRAPHICS = GRAPHICS_API_OPENGL_33 # Uncomment to use OpenGL 3.3
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
diff --git a/src/core.c b/src/core.c
index fb71af211..f8a83e250 100644
--- a/src/core.c
+++ b/src/core.c
@@ -238,8 +238,7 @@ extern void UnloadDefaultFont(void); // [Module: text] Unloads default fo
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
-static void InitDisplay(int width, int height); // Initialize display device and framebuffer
-static void InitGraphics(void); // Initialize OpenGL graphics
+static void InitGraphicsDevice(int width, int height); // Initialize graphics device
static void SetupFramebufferSize(int displayWidth, int displayHeight);
static void InitTimer(void); // Initialize timer
static double GetTime(void); // Returns time since InitTimer() was run
@@ -300,11 +299,8 @@ void InitWindow(int width, int height, const char *title)
// Store window title (could be useful...)
windowTitle = title;
- // Init device display (monitor, LCD, ...)
- InitDisplay(width, height);
-
- // Init OpenGL graphics
- InitGraphics();
+ // Init graphics device (display device and OpenGL context)
+ InitGraphicsDevice(width, height);
// Load default font for convenience
// NOTE: External function (defined in module: text)
@@ -444,7 +440,15 @@ void CloseWindow(void)
eglTerminate(display);
display = EGL_NO_DISPLAY;
- }
+ }
+#endif
+
+#if defined(PLATFORM_RPI)
+ // Wait for mouse and gamepad threads to finish before closing
+ // NOTE: Those threads should already have finished at this point
+ // because they are controlled by windowShouldClose variable
+ pthread_join(mouseThreadId, NULL);
+ pthread_join(gamepadThreadId, NULL);
#endif
TraceLog(INFO, "Window closed successfully");
@@ -476,16 +480,14 @@ bool IsWindowMinimized(void)
}
// Fullscreen toggle
-// TODO: When destroying window context is lost and resources too, take care!
void ToggleFullscreen(void)
{
#if defined(PLATFORM_DESKTOP)
fullscreen = !fullscreen; // Toggle fullscreen flag
- rlglClose(); // De-init rlgl
- glfwDestroyWindow(window); // Destroy the current window (we will recreate it!)
-
- InitWindow(screenWidth, screenHeight, windowTitle);
+ // NOTE: glfwSetWindowMonitor() doesn't work properly (bugs)
+ if (fullscreen) glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE);
+ else glfwSetWindowMonitor(window, NULL, 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE);
#endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
@@ -518,6 +520,8 @@ void BeginDrawing(void)
currentTime = GetTime(); // Number of elapsed seconds since InitTimer() was called
updateTime = currentTime - previousTime;
previousTime = currentTime;
+
+ //if (IsOculusReady()) BeginOculusDrawing();
rlClearScreenBuffers(); // Clear current framebuffers
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
@@ -531,6 +535,8 @@ void BeginDrawing(void)
void EndDrawing(void)
{
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
+
+ //if (IsOculusReady()) EndOculusDrawing();
SwapBuffers(); // Copy back buffer to front buffer
PollInputEvents(); // Poll user events
@@ -610,8 +616,8 @@ void Begin3dMode(Camera camera)
// Ends 3D mode and returns to default 2D orthographic mode
void End3dMode(void)
-{
- rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
+{
+ rlglDraw(); // Process internal buffers (update + draw)
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
rlPopMatrix(); // Restore previous matrix (PROJECTION) from matrix stack
@@ -1433,7 +1439,7 @@ bool IsButtonReleased(int button)
// Initialize display device and framebuffer
// NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
// If width or height are 0, default display size will be used for framebuffer size
-static void InitDisplay(int width, int height)
+static void InitGraphicsDevice(int width, int height)
{
screenWidth = width; // User desired width
screenHeight = height; // User desired height
@@ -1480,16 +1486,21 @@ static void InitDisplay(int width, int height)
// 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 3.3 context fordward compatible.
-
- // Check selection OpenGL version (not initialized yet!)
- if (rlGetVersion() == OPENGL_33)
+
+ if (configFlags & FLAG_MSAA_4X_HINT)
{
- if (configFlags & FLAG_MSAA_4X_HINT)
- {
- glfwWindowHint(GLFW_SAMPLES, 4); // Enables multisampling x4 (MSAA), default is 0
- TraceLog(INFO, "Trying to enable MSAA x4");
- }
+ glfwWindowHint(GLFW_SAMPLES, 4); // Enables multisampling x4 (MSAA), default is 0
+ TraceLog(INFO, "Trying to enable MSAA x4");
+ }
+ // Check selection OpenGL version
+ if (rlGetVersion() == OPENGL_21)
+ {
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); // Choose OpenGL major version (just hint)
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); // Choose OpenGL minor version (just hint)
+ }
+ else if (rlGetVersion() == OPENGL_33)
+ {
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Choose OpenGL major version (just hint)
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint)
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above!
@@ -1504,25 +1515,40 @@ static void InitDisplay(int width, int height)
if (fullscreen)
{
+ // Obtain recommended displayWidth/displayHeight from a valid videomode for the monitor
+ int count;
+ const GLFWvidmode *modes = glfwGetVideoModes(glfwGetPrimaryMonitor(), &count);
+
+ // Get closest videomode to desired screenWidth/screenHeight
+ for (int i = 0; i < count; i++)
+ {
+ if (modes[i].width >= screenWidth)
+ {
+ if (modes[i].height >= screenHeight)
+ {
+ displayWidth = modes[i].width;
+ displayHeight = modes[i].height;
+ break;
+ }
+ }
+ }
+
+ TraceLog(WARNING, "Closest fullscreen videomode: %i x %i", displayWidth, displayHeight);
+
+ // NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example,
+ // for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3),
+ // framebuffer is rendered correctly but once displayed on a 16:9 monitor, it gets stretched
+ // by the sides to fit all monitor space...
+
// At this point we need to manage render size vs screen size
// NOTE: This function uses and modifies global module variables:
// screenWidth/screenHeight - renderWidth/renderHeight - downscaleView
SetupFramebufferSize(displayWidth, displayHeight);
+
+ window = glfwCreateWindow(displayWidth, displayHeight, windowTitle, glfwGetPrimaryMonitor(), NULL);
- // TODO: SetupFramebufferSize() does not consider properly display video modes.
- // It setups a renderWidth/renderHeight with black bars that could not match a valid video mode,
- // and so, framebuffer is not scaled properly to some monitors.
-
- int count;
- const GLFWvidmode *modes = glfwGetVideoModes(glfwGetPrimaryMonitor(), &count);
-
- for (int i = 0; i < count; i++)
- {
- // TODO: Check modes[i]->width;
- // TODO: Check modes[i]->height;
- }
-
- window = glfwCreateWindow(screenWidth, screenHeight, windowTitle, glfwGetPrimaryMonitor(), NULL);
+ // NOTE: Full-screen change, not working properly...
+ //glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE);
}
else
{
@@ -1738,29 +1764,33 @@ static void InitDisplay(int width, int height)
TraceLog(INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY);
}
#endif // defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
-}
-// Initialize OpenGL graphics
-static void InitGraphics(void)
-{
- rlglInit(); // Init rlgl
- rlglInitGraphics(renderOffsetX, renderOffsetY, renderWidth, renderHeight); // Init graphics (OpenGL stuff)
+ // Initialize OpenGL context (states and resources)
+ rlglInit(screenWidth, screenHeight);
+
+ // Initialize screen viewport (area of the screen that you will actually draw to)
+ // NOTE: Viewport must be recalculated if screen is resized
+ rlViewport(renderOffsetX/2, renderOffsetY/2, renderWidth - renderOffsetX, renderHeight - renderOffsetY);
+
+ // Initialize internal projection and modelview matrices
+ // NOTE: Default to orthographic projection mode with top-left corner at (0,0)
+ rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix
+ rlLoadIdentity(); // Reset current matrix (PROJECTION)
+ rlOrtho(0, renderWidth - renderOffsetX, renderHeight - renderOffsetY, 0, 0.0f, 1.0f);
+ rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix
+ rlLoadIdentity(); // Reset current matrix (MODELVIEW)
ClearBackground(RAYWHITE); // Default background color for raylib games :P
#if defined(PLATFORM_ANDROID)
- windowReady = true; // IMPORTANT!
+ windowReady = true; // IMPORTANT!
#endif
}
// Compute framebuffer size relative to screen size and display size
-// NOTE: Global variables renderWidth/renderHeight can be modified
+// NOTE: Global variables renderWidth/renderHeight and renderOffsetX/renderOffsetY can be modified
static void SetupFramebufferSize(int displayWidth, int displayHeight)
-{
- // TODO: SetupFramebufferSize() does not consider properly display video modes.
- // It setups a renderWidth/renderHeight with black bars that could not match a valid video mode,
- // and so, framebuffer is not scaled properly to some monitors.
-
+{
// Calculate renderWidth and renderHeight, we have the display size (input params) and the desired screen size (global var)
if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
{
@@ -2109,8 +2139,14 @@ static void CursorEnterCallback(GLFWwindow *window, int enter)
// NOTE: Window resizing not allowed by default
static void WindowSizeCallback(GLFWwindow *window, int width, int height)
{
- // If window is resized, graphics device is re-initialized (but only ortho mode)
- rlglInitGraphics(0, 0, width, height);
+ // If window is resized, viewport and projection matrix needs to be re-calculated
+ rlViewport(0, 0, width, height); // Set viewport width and height
+ rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix
+ rlLoadIdentity(); // Reset current matrix (PROJECTION)
+ rlOrtho(0, width, height, 0, 0.0f, 1.0f); // Orthographic projection mode with top-left corner at (0,0)
+ rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix
+ rlLoadIdentity(); // Reset current matrix (MODELVIEW)
+ rlClearScreenBuffers(); // Clear screen buffers (color and depth)
// Window size must be updated to be used on 3D mode to get new aspect ratio (Begin3dMode())
screenWidth = width;
@@ -2119,9 +2155,6 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
renderHeight = height;
// NOTE: Postprocessing texture is not scaled to new size
-
- // Background must be also re-cleared
- ClearBackground(RAYWHITE);
}
// GLFW3 WindowIconify Callback, runs when window is minimized/restored
@@ -2188,11 +2221,8 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
}
else
{
- // Init device display (monitor, LCD, ...)
- InitDisplay(screenWidth, screenHeight);
-
- // Init OpenGL graphics
- InitGraphics();
+ // Init graphics device (display device and OpenGL context)
+ InitGraphicsDevice(screenWidth, screenHeight);
// Load default font for convenience
// NOTE: External function (defined in module: text)
@@ -2645,7 +2675,7 @@ static void *MouseThread(void *arg)
int mouseRelX = 0;
int mouseRelY = 0;
- while(1)
+ while (!windowShouldClose)
{
if (read(mouseStream, &mouse, sizeof(MouseEvent)) == (int)sizeof(MouseEvent))
{
@@ -2735,7 +2765,7 @@ static void *GamepadThread(void *arg)
// Read gamepad event
struct js_event gamepadEvent;
- while (1)
+ while (!windowShouldClose)
{
for (int i = 0; i < MAX_GAMEPADS; i++)
{
@@ -2770,7 +2800,7 @@ static void *GamepadThread(void *arg)
return NULL;
}
-#endif
+#endif // PLATFORM_RPI
// Plays raylib logo appearing animation
static void LogoAnimation(void)
diff --git a/src/external/OculusSDK/LibOVR/Include/Extras/OVR_Math.h b/src/external/OculusSDK/LibOVR/Include/Extras/OVR_Math.h
index c182ed5b4..718c21cb8 100644
--- a/src/external/OculusSDK/LibOVR/Include/Extras/OVR_Math.h
+++ b/src/external/OculusSDK/LibOVR/Include/Extras/OVR_Math.h
@@ -1487,6 +1487,25 @@ public:
}
}
+ // Decompose a quat into quat = swing * twist, where twist is a rotation about axis,
+ // and swing is a rotation perpendicular to axis.
+ Quat GetSwingTwist(const Vector3& axis, Quat* twist) const
+ {
+ OVR_MATH_ASSERT(twist);
+ OVR_MATH_ASSERT(axis.IsNormalized());
+
+ // Create a normalized quaternion from projection of (x,y,z) onto axis
+ T d = axis.Dot(Vector3(x, y, z));
+ *twist = Quat(axis.x*d, axis.y*d, axis.z*d, w);
+ T len = twist->Length();
+ if (len == 0)
+ twist->w = T(1); // identity
+ else
+ twist /= len; // normalize
+
+ return *this * twist.Inverted();
+ }
+
// Normalized linear interpolation of quaternions
// NOTE: This function is a bad approximation of Slerp()
// when the angle between the *this and b is large.
@@ -1500,7 +1519,7 @@ public:
Quat Slerp(const Quat& b, T s) const
{
Vector3 delta = (b * this->Inverted()).ToRotationVector();
- return FromRotationVector(delta * s) * *this;
+ return (FromRotationVector(delta * s) * *this).Normalized(); // normalize so errors don't accumulate
}
// Spherical linear interpolation: much faster for small rotations, accurate for large rotations. See FastTo/FromRotationVector
diff --git a/src/external/OculusSDK/LibOVR/Include/OVR_CAPI.h b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI.h
index b1ec3cc0e..cf7aab622 100644
--- a/src/external/OculusSDK/LibOVR/Include/OVR_CAPI.h
+++ b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI.h
@@ -493,7 +493,7 @@ typedef enum ovrStatusBits_
/// Specifies the description of a single sensor.
///
-/// \see ovrGetTrackerDesc
+/// \see ovr_GetTrackerDesc
///
typedef struct OVR_ALIGNAS(OVR_PTR_SIZE) ovrTrackerDesc_
{
@@ -665,6 +665,18 @@ typedef enum ovrTextureFormat_
OVR_FORMAT_D32_FLOAT,
OVR_FORMAT_D32_FLOAT_S8X24_UINT,
+ // Added in 1.5 compressed formats can be used for static layers
+ OVR_FORMAT_BC1_UNORM,
+ OVR_FORMAT_BC1_UNORM_SRGB,
+ OVR_FORMAT_BC2_UNORM,
+ OVR_FORMAT_BC2_UNORM_SRGB,
+ OVR_FORMAT_BC3_UNORM,
+ OVR_FORMAT_BC3_UNORM_SRGB,
+ OVR_FORMAT_BC6H_UF16,
+ OVR_FORMAT_BC6H_SF16,
+ OVR_FORMAT_BC7_UNORM,
+ OVR_FORMAT_BC7_UNORM_SRGB,
+
OVR_FORMAT_ENUMSIZE = 0x7fffffff ///< \internal Force type int32_t.
} ovrTextureFormat;
@@ -779,18 +791,20 @@ typedef enum ovrTouch_
ovrTouch_A = ovrButton_A,
ovrTouch_B = ovrButton_B,
ovrTouch_RThumb = ovrButton_RThumb,
+ ovrTouch_RThumbRest = 0x00000008,
ovrTouch_RIndexTrigger = 0x00000010,
// Bit mask of all the button touches on the right controller
- ovrTouch_RButtonMask = ovrTouch_A | ovrTouch_B | ovrTouch_RThumb | ovrTouch_RIndexTrigger,
+ ovrTouch_RButtonMask = ovrTouch_A | ovrTouch_B | ovrTouch_RThumb | ovrTouch_RThumbRest | ovrTouch_RIndexTrigger,
ovrTouch_X = ovrButton_X,
ovrTouch_Y = ovrButton_Y,
ovrTouch_LThumb = ovrButton_LThumb,
+ ovrTouch_LThumbRest = 0x00000800,
ovrTouch_LIndexTrigger = 0x00001000,
// Bit mask of all the button touches on the left controller
- ovrTouch_LButtonMask = ovrTouch_X | ovrTouch_Y | ovrTouch_LThumb | ovrTouch_LIndexTrigger,
+ ovrTouch_LButtonMask = ovrTouch_X | ovrTouch_Y | ovrTouch_LThumb | ovrTouch_LThumbRest | ovrTouch_LIndexTrigger,
// Finger pose state
// Derived internally based on distance, proximity to sensors and filtering.
@@ -959,36 +973,6 @@ extern "C" {
// -----------------------------------------------------------------------------------
// ***** API Interfaces
-// Overview of the API
-//
-// Setup:
-// - ovr_Initialize().
-// - ovr_Create(&hmd, &graphicsId).
-// - Use hmd members and ovr_GetFovTextureSize() to determine graphics configuration
-// and ovr_GetRenderDesc() to get per-eye rendering parameters.
-// - Allocate texture swap chains with ovr_CreateTextureSwapChainDX() or
-// ovr_CreateTextureSwapChainGL(). Create any associated render target views or
-// frame buffer objects.
-//
-// Application Loop:
-// - Call ovr_GetPredictedDisplayTime() to get the current frame timing information.
-// - Call ovr_GetTrackingState() and ovr_CalcEyePoses() to obtain the predicted
-// rendering pose for each eye based on timing.
-// - Render the scene content into the current buffer of the texture swapchains
-// for each eye and layer you plan to update this frame. If you render into a
-// texture swap chain, you must call ovr_CommitTextureSwapChain() on it to commit
-// the changes before you reference the chain this frame (otherwise, your latest
-// changes won't be picked up).
-// - Call ovr_SubmitFrame() to render the distorted layers to and present them on the HMD.
-// If ovr_SubmitFrame returns ovrSuccess_NotVisible, there is no need to render the scene
-// for the next loop iteration. Instead, just call ovr_SubmitFrame again until it returns
-// ovrSuccess.
-//
-// Shutdown:
-// - ovr_Destroy().
-// - ovr_Shutdown().
-
-
/// Initializes LibOVR
///
/// Initialize LibOVR for application usage. This includes finding and loading the LibOVRRT
@@ -1097,6 +1081,35 @@ OVR_PUBLIC_FUNCTION(const char*) ovr_GetVersionString();
OVR_PUBLIC_FUNCTION(int) ovr_TraceMessage(int level, const char* message);
+/// Identify client application info.
+///
+/// The string is one or more newline-delimited lines of optional info
+/// indicating engine name, engine version, engine plugin name, engine plugin
+/// version, engine editor. The order of the lines is not relevant. Individual
+/// lines are optional. A newline is not necessary at the end of the last line.
+/// Call after ovr_Initialize and before the first call to ovr_Create.
+/// Each value is limited to 20 characters. Key names such as 'EngineName:'
+/// 'EngineVersion:' do not count towards this limit.
+///
+/// \param[in] identity Specifies one or more newline-delimited lines of optional info:
+/// EngineName: %s\n
+/// EngineVersion: %s\n
+/// EnginePluginName: %s\n
+/// EnginePluginVersion: %s\n
+/// EngineEditor: ('true' or 'false')\n
+///
+/// Example code
+/// \code{.cpp}
+/// ovr_IdentifyClient("EngineName: Unity\n"
+/// "EngineVersion: 5.3.3\n"
+/// "EnginePluginName: OVRPlugin\n"
+/// "EnginePluginVersion: 1.2.0\n"
+/// "EngineEditor: true");
+/// \endcode
+///
+OVR_PUBLIC_FUNCTION(ovrResult) ovr_IdentifyClient(const char* identity);
+
+
//-------------------------------------------------------------------------------------
/// @name HMD Management
///
@@ -1153,7 +1166,7 @@ OVR_PUBLIC_FUNCTION(ovrTrackerDesc) ovr_GetTrackerDesc(ovrSession session, unsig
/// Creates a handle to a VR session.
///
/// Upon success the returned ovrSession must be eventually freed with ovr_Destroy when it is no longer needed.
-/// A second call to ovr_Create will result in an error return value if the previous Hmd has not been destroyed.
+/// A second call to ovr_Create will result in an error return value if the previous session has not been destroyed.
///
/// \param[out] pSession Provides a pointer to an ovrSession which will be written to upon success.
/// \param[out] luid Provides a system specific graphics adapter identifier that locates which
@@ -1161,7 +1174,7 @@ OVR_PUBLIC_FUNCTION(ovrTrackerDesc) ovr_GetTrackerDesc(ovrSession session, unsig
/// or no rendering output will be possible. This is important for stability on multi-adapter systems. An
/// application that simply chooses the default adapter will not run reliably on multi-adapter systems.
/// \return Returns an ovrResult indicating success or failure. Upon failure
-/// the returned pHmd will be NULL.
+/// the returned ovrSession will be NULL.
///
/// Example code
/// \code{.cpp}
@@ -1177,7 +1190,7 @@ OVR_PUBLIC_FUNCTION(ovrTrackerDesc) ovr_GetTrackerDesc(ovrSession session, unsig
OVR_PUBLIC_FUNCTION(ovrResult) ovr_Create(ovrSession* pSession, ovrGraphicsLuid* pLuid);
-/// Destroys the HMD.
+/// Destroys the session.
///
/// \param[in] session Specifies an ovrSession previously returned by ovr_Create.
/// \see ovr_Create
@@ -1304,7 +1317,7 @@ OVR_PUBLIC_FUNCTION(void) ovr_ClearShouldRecenterFlag(ovrSession session);
/// ovrTrackingState value. Use 0 to request the most recent tracking state.
/// \param[in] latencyMarker Specifies that this call is the point in time where
/// the "App-to-Mid-Photon" latency timer starts from. If a given ovrLayer
-/// provides "SensorSampleTimestamp", that will override the value stored here.
+/// provides "SensorSampleTime", that will override the value stored here.
/// \return Returns the ovrTrackingState that is predicted for the given absTime.
///
/// \see ovrTrackingState, ovr_GetEyePoses, ovr_GetTimeInSeconds
@@ -1363,12 +1376,11 @@ OVR_PUBLIC_FUNCTION(unsigned int) ovr_GetConnectedControllerTypes(ovrSession ses
///
/// \see ovrControllerType
///
-OVR_PUBLIC_FUNCTION(ovrResult) ovr_SetControllerVibration(ovrSession session, ovrControllerType controllerType,
- float frequency, float amplitude);
+OVR_PUBLIC_FUNCTION(ovrResult) ovr_SetControllerVibration(ovrSession session, ovrControllerType controllerType, float frequency, float amplitude);
+
///@}
-
//-------------------------------------------------------------------------------------
// @name Layers
//
@@ -1768,7 +1780,7 @@ OVR_PUBLIC_FUNCTION(ovrEyeRenderDesc) ovr_GetRenderDesc(ovrSession session,
/// ovrLayerQuad layer1;
/// ...
/// ovrLayerHeader* layers[2] = { &layer0.Header, &layer1.Header };
-/// ovrResult result = ovr_SubmitFrame(hmd, frameIndex, nullptr, layers, 2);
+/// ovrResult result = ovr_SubmitFrame(session, frameIndex, nullptr, layers, 2);
/// \endcode
///
/// \return Returns an ovrResult for which OVR_SUCCESS(result) is false upon error and true
@@ -1844,7 +1856,7 @@ OVR_PUBLIC_FUNCTION(double) ovr_GetTimeInSeconds();
/// App can toggle performance HUD modes as such:
/// \code{.cpp}
/// ovrPerfHudMode PerfHudMode = ovrPerfHud_LatencyTiming;
-/// ovr_SetInt(Hmd, OVR_PERF_HUD_MODE, (int)PerfHudMode);
+/// ovr_SetInt(session, OVR_PERF_HUD_MODE, (int)PerfHudMode);
/// \endcode
///
typedef enum ovrPerfHudMode_
@@ -1864,7 +1876,7 @@ typedef enum ovrPerfHudMode_
/// App can toggle layer HUD modes as such:
/// \code{.cpp}
/// ovrLayerHudMode LayerHudMode = ovrLayerHud_Info;
-/// ovr_SetInt(Hmd, OVR_LAYER_HUD_MODE, (int)LayerHudMode);
+/// ovr_SetInt(session, OVR_LAYER_HUD_MODE, (int)LayerHudMode);
/// \endcode
///
typedef enum ovrLayerHudMode_
@@ -1885,7 +1897,7 @@ typedef enum ovrLayerHudMode_
/// App can toggle the debug HUD modes as such:
/// \code{.cpp}
/// ovrDebugHudStereoMode DebugHudMode = ovrDebugHudStereo_QuadWithCrosshair;
-/// ovr_SetInt(Hmd, OVR_DEBUG_HUD_STEREO_MODE, (int)DebugHudMode);
+/// ovr_SetInt(session, OVR_DEBUG_HUD_STEREO_MODE, (int)DebugHudMode);
/// \endcode
///
/// The app can modify the visual properties of the stereo guide (i.e. quad, crosshair)
@@ -2004,7 +2016,7 @@ OVR_PUBLIC_FUNCTION(ovrBool) ovr_SetFloatArray(ovrSession session, const char* p
/// \param[in] defaultVal Specifes the value to return if the property couldn't be read.
/// \return Returns the string property if it exists. Otherwise returns defaultVal, which can be specified as NULL.
/// The return memory is guaranteed to be valid until next call to ovr_GetString or
-/// until the HMD is destroyed, whichever occurs first.
+/// until the session is destroyed, whichever occurs first.
OVR_PUBLIC_FUNCTION(const char*) ovr_GetString(ovrSession session, const char* propertyName,
const char* defaultVal);
diff --git a/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Audio.h b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Audio.h
index c53448133..930dfcbe7 100644
--- a/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Audio.h
+++ b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Audio.h
@@ -9,6 +9,10 @@
#define OVR_CAPI_Audio_h
#ifdef _WIN32
+// Prevents from defining min() and max() macro symbols.
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
#include
#include "OVR_CAPI.h"
#define OVR_AUDIO_MAX_DEVICE_STR_SIZE 128
diff --git a/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_D3D.h b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_D3D.h
index 50806bca1..982af8f0a 100644
--- a/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_D3D.h
+++ b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_D3D.h
@@ -25,7 +25,7 @@
/// \param[in] desc Specifies requested texture properties. See notes for more info about texture format.
/// \param[in] bindFlags Specifies what ovrTextureBindFlags the application requires for this texture chain.
/// \param[out] out_TextureSwapChain Returns the created ovrTextureSwapChain, which will be valid upon a successful return value, else it will be NULL.
-/// This texture chain must be eventually destroyed via ovr_DestroyTextureSwapChain before destroying the HMD with ovr_Destroy.
+/// This texture chain must be eventually destroyed via ovr_DestroyTextureSwapChain before destroying the session with ovr_Destroy.
///
/// \return Returns an ovrResult indicating success or failure. In the case of failure, use
/// ovr_GetLastErrorInfo to get more information.
@@ -88,7 +88,7 @@ OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetTextureSwapChainBufferDX(ovrSession sessio
/// which must be the same one the application renders to the textures with.
/// \param[in] desc Specifies requested texture properties. See notes for more info about texture format.
/// \param[out] out_MirrorTexture Returns the created ovrMirrorTexture, which will be valid upon a successful return value, else it will be NULL.
-/// This texture must be eventually destroyed via ovr_DestroyMirrorTexture before destroying the HMD with ovr_Destroy.
+/// This texture must be eventually destroyed via ovr_DestroyMirrorTexture before destroying the session with ovr_Destroy.
///
/// \return Returns an ovrResult indicating success or failure. In the case of failure, use
/// ovr_GetLastErrorInfo to get more information.
diff --git a/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h
index 1658ca578..814879474 100644
--- a/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h
+++ b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h
@@ -15,7 +15,7 @@
/// \param[in] desc Specifies the requested texture properties. See notes for more info about texture format.
/// \param[out] out_TextureSwapChain Returns the created ovrTextureSwapChain, which will be valid upon
/// a successful return value, else it will be NULL. This texture swap chain must be eventually
-/// destroyed via ovr_DestroyTextureSwapChain before destroying the HMD with ovr_Destroy.
+/// destroyed via ovr_DestroyTextureSwapChain before destroying the session with ovr_Destroy.
///
/// \return Returns an ovrResult indicating success or failure. In the case of failure, use
/// ovr_GetLastErrorInfo to get more information.
@@ -64,7 +64,7 @@ OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetTextureSwapChainBufferGL(ovrSession sessio
/// \param[in] session Specifies an ovrSession previously returned by ovr_Create.
/// \param[in] desc Specifies the requested mirror texture description.
/// \param[out] out_MirrorTexture Specifies the created ovrMirrorTexture, which will be valid upon a successful return value, else it will be NULL.
-/// This texture must be eventually destroyed via ovr_DestroyMirrorTexture before destroying the HMD with ovr_Destroy.
+/// This texture must be eventually destroyed via ovr_DestroyMirrorTexture before destroying the session with ovr_Destroy.
///
/// \return Returns an ovrResult indicating success or failure. In the case of failure, use
/// ovr_GetLastErrorInfo to get more information.
diff --git a/src/external/OculusSDK/LibOVR/Include/OVR_ErrorCode.h b/src/external/OculusSDK/LibOVR/Include/OVR_ErrorCode.h
index ed0be0e70..9fc527c71 100644
--- a/src/external/OculusSDK/LibOVR/Include/OVR_ErrorCode.h
+++ b/src/external/OculusSDK/LibOVR/Include/OVR_ErrorCode.h
@@ -14,9 +14,6 @@
-
-
-
#ifndef OVR_RESULT_DEFINED
#define OVR_RESULT_DEFINED ///< Allows ovrResult to be independently defined.
/// API call results are represented at the highest level by a single ovrResult.
@@ -59,27 +56,26 @@ typedef enum ovrSuccessType_
{
/// This is a general success result. Use OVR_SUCCESS to test for success.
ovrSuccess = 0,
+} ovrSuccessType;
+#endif
+// Public success types
+// Success is a value greater or equal to 0, while all error types are negative values.
+typedef enum ovrSuccessTypes_
+{
/// Returned from a call to SubmitFrame. The call succeeded, but what the app
/// rendered will not be visible on the HMD. Ideally the app should continue
/// calling SubmitFrame, but not do any rendering. When the result becomes
/// ovrSuccess, rendering should continue as usual.
ovrSuccess_NotVisible = 1000,
- ovrSuccess_HMDFirmwareMismatch = 4100, ///< The HMD Firmware is out of date but is acceptable.
- ovrSuccess_TrackerFirmwareMismatch = 4101, ///< The Tracker Firmware is out of date but is acceptable.
- ovrSuccess_ControllerFirmwareMismatch = 4104, ///< The controller firmware is out of date but is acceptable.
- ovrSuccess_TrackerDriverNotFound = 4105, ///< The tracker driver interface was not found. Can be a temporary error
-
-} ovrSuccessType;
-#endif
-
+} ovrSuccessTypes;
+// Public error types
typedef enum ovrErrorType_
{
/* General errors */
ovrError_MemoryAllocationFailure = -1000, ///< Failure to allocate memory.
- ovrError_SocketCreationFailure = -1001, ///< Failure to create a socket.
ovrError_InvalidSession = -1002, ///< Invalid ovrSession parameter provided.
ovrError_Timeout = -1003, ///< The operation timed out.
ovrError_NotInitialized = -1004, ///< The system or component has not been initialized.
@@ -94,10 +90,8 @@ typedef enum ovrErrorType_
ovrError_ServiceDeadlockDetected = -1014, ///< The service watchdog discovered a deadlock.
/* Audio error range, reserved for Audio errors. */
- ovrError_AudioReservedBegin = -2000, ///< First Audio error.
ovrError_AudioDeviceNotFound = -2001, ///< Failure to find the specified audio device.
ovrError_AudioComError = -2002, ///< Generic COM error.
- ovrError_AudioReservedEnd = -2999, ///< Last Audio error.
/* Initialization errors. */
ovrError_Initialize = -3000, ///< Generic initialization error.
@@ -122,51 +116,6 @@ typedef enum ovrErrorType_
ovrError_DisplayManagerInit = -3019, ///< Initialization of the DisplayManager failed.
ovrError_TrackerDriverInit = -3020, ///< Failed to get the interface for an attached tracker
- /* Hardware errors */
- ovrError_InvalidBundleAdjustment = -4000, ///< Headset has no bundle adjustment data.
- ovrError_USBBandwidth = -4001, ///< The USB hub cannot handle the camera frame bandwidth.
- ovrError_USBEnumeratedSpeed = -4002, ///< The USB camera is not enumerating at the correct device speed.
- ovrError_ImageSensorCommError = -4003, ///< Unable to communicate with the image sensor.
- ovrError_GeneralTrackerFailure = -4004, ///< We use this to report various sensor issues that don't fit in an easily classifiable bucket.
- ovrError_ExcessiveFrameTruncation = -4005, ///< A more than acceptable number of frames are coming back truncated.
- ovrError_ExcessiveFrameSkipping = -4006, ///< A more than acceptable number of frames have been skipped.
- ovrError_SyncDisconnected = -4007, ///< The sensor is not receiving the sync signal (cable disconnected?).
- ovrError_TrackerMemoryReadFailure = -4008, ///< Failed to read memory from the sensor.
- ovrError_TrackerMemoryWriteFailure = -4009, ///< Failed to write memory from the sensor.
- ovrError_TrackerFrameTimeout = -4010, ///< Timed out waiting for a camera frame.
- ovrError_TrackerTruncatedFrame = -4011, ///< Truncated frame returned from sensor.
- ovrError_TrackerDriverFailure = -4012, ///< The sensor driver has encountered a problem.
- ovrError_TrackerNRFFailure = -4013, ///< The sensor wireless subsystem has encountered a problem.
- ovrError_HardwareGone = -4014, ///< The hardware has been unplugged
- ovrError_NordicEnabledNoSync = -4015, ///< The nordic indicates that sync is enabled but it is not sending sync pulses
- ovrError_NordicSyncNoFrames = -4016, ///< It looks like we're getting a sync signal, but no camera frames have been received
- ovrError_CatastrophicFailure = -4017, ///< A catastrophic failure has occurred. We will attempt to recover by resetting the device
- ovrError_CatastrophicTimeout = -4018, ///< The catastrophic recovery has timed out.
- ovrError_RepeatCatastrophicFail = -4019, ///< Catastrophic failure has repeated too many times.
- ovrError_USBOpenDeviceFailure = -4020, ///< Could not open handle for Rift device (likely already in use by another process).
- ovrError_HMDGeneralFailure = -4021, ///< Unexpected HMD issues that don't fit a specific bucket.
-
- ovrError_HMDFirmwareMismatch = -4100, ///< The HMD Firmware is out of date and is unacceptable.
- ovrError_TrackerFirmwareMismatch = -4101, ///< The sensor Firmware is out of date and is unacceptable.
- ovrError_BootloaderDeviceDetected = -4102, ///< A bootloader HMD is detected by the service.
- ovrError_TrackerCalibrationError = -4103, ///< The sensor calibration is missing or incorrect.
- ovrError_ControllerFirmwareMismatch = -4104, ///< The controller firmware is out of date and is unacceptable.
- ovrError_DevManDeviceDetected = -4105, ///< A DeviceManagement mode HMD is detected by the service.
- ovrError_RebootedBootloaderDevice = -4106, ///< Had to reboot bootloader device, which succeeded.
- ovrError_FailedRebootBootloaderDev = -4107, ///< Had to reboot bootloader device, which failed. Device is stuck in bootloader mode.
-
- ovrError_IMUTooManyLostSamples = -4200, ///< Too many lost IMU samples.
- ovrError_IMURateError = -4201, ///< IMU rate is outside of the expected range.
- ovrError_FeatureReportFailure = -4202, ///< A feature report has failed.
- ovrError_HMDWirelessTimeout = -4203, ///< HMD wireless interface never returned from busy state.
-
- ovrError_BootloaderAssertLog = -4300, ///< HMD Bootloader Assert Log was not empty.
- ovrError_AppAssertLog = -4301, ///< HMD App Assert Log was not empty.
-
- /* Synchronization errors */
- ovrError_Incomplete = -5000, ///< Requested async work not yet complete.
- ovrError_Abandoned = -5001, ///< Requested async work was abandoned and result is incomplete.
-
/* Rendering errors */
ovrError_DisplayLost = -6000, ///< In the event of a system-wide graphics reset or cable unplug this is returned to the app.
ovrError_TextureSwapChainFull = -6001, ///< ovr_CommitTextureSwapChain was called too many times on a texture swapchain without calling submit to use the chain.
@@ -182,18 +131,6 @@ typedef enum ovrErrorType_
ovrError_RuntimeException = -7000, ///< A runtime exception occurred. The application is required to shutdown LibOVR and re-initialize it before this error state will be cleared.
- ovrError_MetricsUnknownApp = -90000,
- ovrError_MetricsDuplicateApp = -90001,
- ovrError_MetricsNoEvents = -90002,
- ovrError_MetricsRuntime = -90003,
- ovrError_MetricsFile = -90004,
- ovrError_MetricsNoClientInfo = -90005,
- ovrError_MetricsNoAppMetaData = -90006,
- ovrError_MetricsNoApp = -90007,
- ovrError_MetricsOafFailure = -90008,
- ovrError_MetricsSessionAlreadyActive = -90009,
- ovrError_MetricsSessionNotActive = -90010,
-
} ovrErrorType;
@@ -206,4 +143,5 @@ typedef struct ovrErrorInfo_
char ErrorString[512]; ///< A UTF8-encoded null-terminated English string describing the problem. The format of this string is subject to change in future versions.
} ovrErrorInfo;
+
#endif /* OVR_ErrorCode_h */
diff --git a/src/external/OculusSDK/LibOVR/Include/OVR_Version.h b/src/external/OculusSDK/LibOVR/Include/OVR_Version.h
index dbfe4deba..376fa7d59 100644
--- a/src/external/OculusSDK/LibOVR/Include/OVR_Version.h
+++ b/src/external/OculusSDK/LibOVR/Include/OVR_Version.h
@@ -19,7 +19,7 @@
// Master version numbers
#define OVR_PRODUCT_VERSION 1 // Product version doesn't participate in semantic versioning.
#define OVR_MAJOR_VERSION 1 // If you change these values then you need to also make sure to change LibOVR/Projects/Windows/LibOVR.props in parallel.
-#define OVR_MINOR_VERSION 4 //
+#define OVR_MINOR_VERSION 5 //
#define OVR_PATCH_VERSION 0
#define OVR_BUILD_NUMBER 0
diff --git a/src/external/OculusSDK/LibOVR/LibOVRRT32_1.dll b/src/external/OculusSDK/LibOVR/LibOVRRT32_1.dll
index 70f63f701..8553ce110 100644
Binary files a/src/external/OculusSDK/LibOVR/LibOVRRT32_1.dll and b/src/external/OculusSDK/LibOVR/LibOVRRT32_1.dll differ
diff --git a/src/models.c b/src/models.c
index 8deabcb0e..b194a0db1 100644
--- a/src/models.c
+++ b/src/models.c
@@ -40,7 +40,7 @@
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
-#define CUBIC_MAP_HALF_BLOCK_SIZE 0.5
+// ...
//----------------------------------------------------------------------------------
// Types and Structures Definition
@@ -808,13 +808,6 @@ void UnloadMaterial(Material material)
rlDeleteTextures(material.texSpecular.id);
}
-// Link a texture to a model
-void SetModelTexture(Model *model, Texture2D texture)
-{
- if (texture.id <= 0) model->material.texDiffuse = GetDefaultTexture(); // Use default white texture
- else model->material.texDiffuse = texture;
-}
-
// Generate a mesh from heightmap
static Mesh GenMeshHeightmap(Image heightmap, Vector3 size)
{
@@ -1549,8 +1542,11 @@ BoundingBox CalculateBoundingBox(Mesh mesh)
// Detect and resolve cubicmap collisions
// NOTE: player position (or camera) is modified inside this function
+// TODO: This functions needs to be completely reviewed!
Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius)
{
+ #define CUBIC_MAP_HALF_BLOCK_SIZE 0.5
+
Color *cubicmapPixels = GetImageData(cubicmap);
// Detect the cell where the player is located
@@ -1562,15 +1558,15 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
locationCellX = floor(playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE);
locationCellY = floor(playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE);
- if (locationCellX >= 0 && locationCellY >= 0 && locationCellX < cubicmap.width && locationCellY < cubicmap.height)
+ if ((locationCellX >= 0) && (locationCellY >= 0) && (locationCellX < cubicmap.width) && (locationCellY < cubicmap.height))
{
// Multiple Axis --------------------------------------------------------------------------------------------
// Axis x-, y-
- if (locationCellX > 0 && locationCellY > 0)
+ if ((locationCellX > 0) && (locationCellY > 0))
{
- if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) &&
- (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0))
+ if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r != 0) &&
+ (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r != 0))
{
if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) &&
((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius))
@@ -1583,10 +1579,10 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
}
// Axis x-, y+
- if (locationCellX > 0 && locationCellY < cubicmap.height - 1)
+ if ((locationCellX > 0) && (locationCellY < cubicmap.height - 1))
{
- if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) &&
- (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0))
+ if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r != 0) &&
+ (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r != 0))
{
if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) &&
((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius))
@@ -1599,10 +1595,10 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
}
// Axis x+, y-
- if (locationCellX < cubicmap.width - 1 && locationCellY > 0)
+ if ((locationCellX < cubicmap.width - 1) && (locationCellY > 0))
{
- if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0) &&
- (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0))
+ if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r != 0) &&
+ (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r != 0))
{
if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) &&
((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius))
@@ -1615,10 +1611,10 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
}
// Axis x+, y+
- if (locationCellX < cubicmap.width - 1 && locationCellY < cubicmap.height - 1)
+ if ((locationCellX < cubicmap.width - 1) && (locationCellY < cubicmap.height - 1))
{
- if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0) &&
- (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0))
+ if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r != 0) &&
+ (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r != 0))
{
if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) &&
((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius))
@@ -1635,7 +1631,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
// Axis x-
if (locationCellX > 0)
{
- if (cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0)
+ if (cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r != 0)
{
if ((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius)
{
@@ -1647,7 +1643,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
// Axis x+
if (locationCellX < cubicmap.width - 1)
{
- if (cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0)
+ if (cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r != 0)
{
if ((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius)
{
@@ -1659,7 +1655,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
// Axis y-
if (locationCellY > 0)
{
- if (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0)
+ if (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r != 0)
{
if ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)
{
@@ -1671,7 +1667,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
// Axis y+
if (locationCellY < cubicmap.height - 1)
{
- if (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0)
+ if (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r != 0)
{
if ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)
{
@@ -1684,11 +1680,11 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
// Diagonals -------------------------------------------------------------------------------------------------------
// Axis x-, y-
- if (locationCellX > 0 && locationCellY > 0)
+ if ((locationCellX > 0) && (locationCellY > 0))
{
- if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r == 0) &&
- (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r == 0) &&
- (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX - 1)].r != 0))
+ if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r == 0) &&
+ (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r == 0) &&
+ (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX - 1)].r != 0))
{
if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) &&
((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius))
@@ -1707,11 +1703,11 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
}
// Axis x-, y+
- if (locationCellX > 0 && locationCellY < cubicmap.height - 1)
+ if ((locationCellX > 0) && (locationCellY < cubicmap.height - 1))
{
- if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r == 0) &&
- (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r == 0) &&
- (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX - 1)].r != 0))
+ if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r == 0) &&
+ (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r == 0) &&
+ (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX - 1)].r != 0))
{
if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) &&
((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius))
@@ -1730,11 +1726,11 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
}
// Axis x+, y-
- if (locationCellX < cubicmap.width - 1 && locationCellY > 0)
+ if ((locationCellX < cubicmap.width - 1) && (locationCellY > 0))
{
- if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r == 0) &&
- (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r == 0) &&
- (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX + 1)].r != 0))
+ if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r == 0) &&
+ (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r == 0) &&
+ (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX + 1)].r != 0))
{
if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) &&
((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius))
@@ -1753,11 +1749,11 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
}
// Axis x+, y+
- if (locationCellX < cubicmap.width - 1 && locationCellY < cubicmap.height - 1)
+ if ((locationCellX < cubicmap.width - 1) && (locationCellY < cubicmap.height - 1))
{
- if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r == 0) &&
- (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r == 0) &&
- (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX + 1)].r != 0))
+ if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r == 0) &&
+ (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r == 0) &&
+ (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX + 1)].r != 0))
{
if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) &&
((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius))
diff --git a/src/raylib.h b/src/raylib.h
index 0c9f0280f..89fc457fd 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -794,7 +794,6 @@ Model LoadModelFromRES(const char *rresName, int resId); // Load a 3d mod
Model LoadHeightmap(Image heightmap, Vector3 size); // Load a heightmap image as a 3d model
Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based)
void UnloadModel(Model model); // Unload 3d model from memory
-void SetModelTexture(Model *model, Texture2D texture); // Link a texture to a model
Material LoadMaterial(const char *fileName); // Load material data (from file)
Material LoadDefaultMaterial(void); // Load default material (uses default models shader)
@@ -853,9 +852,10 @@ void DestroyLight(Light light); // Destroy a
void InitOculusDevice(void); // Init Oculus Rift device
void CloseOculusDevice(void); // Close Oculus Rift device
void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation)
-void SetOculusMatrix(int eye); // Set internal projection and modelview matrix depending on eyes tracking data
void BeginOculusDrawing(void); // Begin Oculus drawing configuration
void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror)
+bool IsOculusReady(void); // Detect if oculus device (or simulator) is ready
+void ToggleVR(void); // Enable/Disable VR experience (Oculus device or simulator)
//------------------------------------------------------------------------------------
// Audio Loading and Playing Functions (Module: audio)
diff --git a/src/rlgl.c b/src/rlgl.c
index 5d6fd9d7e..af2d57cbd 100644
--- a/src/rlgl.c
+++ b/src/rlgl.c
@@ -31,6 +31,7 @@
#include // Required for: fopen(), fclose(), fread()... [Used only on ReadTextFile()]
#include // Required for: malloc(), free(), rand()
#include // Required for: strcmp(), strlen(), strtok()
+#include // Required for: atan()
#ifndef RLGL_STANDALONE
#include "raymath.h" // Required for Vector3 and Matrix functions
@@ -44,6 +45,10 @@
#endif
#endif
+#if defined(GRAPHICS_API_OPENGL_21)
+ #define GRAPHICS_API_OPENGL_33
+#endif
+
#if defined(GRAPHICS_API_OPENGL_33)
#ifdef __APPLE__
#include // OpenGL 3 library for OSX
@@ -68,10 +73,11 @@
#include // Required for: va_list, va_start(), vfprintf(), va_end() [Used only on TraceLog()]
#endif
-#if !defined(GRAPHICS_API_OPENGL_11)
+#if !defined(GRAPHICS_API_OPENGL_11) && !defined(RLGL_NO_STANDARD_SHADER)
#include "standard_shader.h" // Standard shader to embed
#endif
+//#define RLGL_OCULUS_SUPPORT // Enable Oculus Rift code
#if defined(RLGL_OCULUS_SUPPORT)
#include "external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h" // Oculus SDK for OpenGL
#endif
@@ -130,6 +136,12 @@
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
#endif
+#if defined(GRAPHICS_API_OPENGL_ES2)
+ #define glClearDepth glClearDepthf
+ #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER
+ #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER
+#endif
+
// Default vertex attribute names on shader to set location points
#define DEFAULT_ATTRIB_POSITION_NAME "vertexPosition" // shader-location = 0
#define DEFAULT_ATTRIB_TEXCOORD_NAME "vertexTexCoord" // shader-location = 1
@@ -235,7 +247,7 @@ static bool useTempBuffer = false;
static Shader defaultShader;
static Shader standardShader; // Lazy initialization when GetStandardShader()
static Shader currentShader; // By default, defaultShader
-static bool standardShaderLoaded = false;
+static bool standardShaderLoaded = false; // Flag to track if standard shader has been loaded
// Flags for supported extensions
static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support VAO extension)
@@ -262,6 +274,14 @@ static OculusMirror mirror; // Oculus mirror texture and fbo
static unsigned int frameIndex = 0; // Oculus frames counter, used to discard frames from chain
#endif
+static bool oculusReady = false; // Oculus device ready flag
+static bool oculusSimulator = false; // Oculus device simulator
+static bool vrEnabled = false; // VR experience enabled (Oculus device or simulator)
+static bool vrControl = true; // VR controlled by user code, instead of internally
+
+static RenderTexture2D stereoFbo;
+static Shader distortionShader;
+
// Compressed textures support flags
static bool texCompDXTSupported = false; // DDS texture compression support
static bool npotSupported = false; // NPOT textures full support
@@ -274,11 +294,15 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays;
//static PFNGLISVERTEXARRAYOESPROC glIsVertexArray; // NOTE: Fails in WebGL, omitted
#endif
-static int blendMode = 0;
+static int blendMode = 0; // Track current blending mode
// White texture useful for plain color polys (required by shader)
static unsigned int whiteTexture;
+// Default framebuffer size (required by Oculus device)
+static int screenWidth; // Default framebuffer width
+static int screenHeight; // Default framebuffer height
+
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
@@ -294,15 +318,18 @@ static void UnloadStandardShader(void); // Unload standard shader
static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads)
static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data
-static void DrawDefaultBuffers(void); // Draw default internal buffers vertex data
+static void DrawDefaultBuffers(int eyesCount); // Draw default internal buffers vertex data
static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU
+// Set internal projection and modelview matrix depending on eyes tracking data
+static void SetOculusView(int eye, Matrix matProjection, Matrix matModelView);
+
static void SetShaderLights(Shader shader); // Sets shader uniform values for lights array
static char *ReadTextFile(const char *fileName);
#endif
-#if defined(RLGL_OCULUS_SUPPORT) // Oculus Rift functions
+#if defined(RLGL_OCULUS_SUPPORT)
static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height); // Load Oculus required buffers
static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer); // Unload texture required buffers
static OculusMirror LoadOculusMirror(ovrSession session, int width, int height); // Load Oculus mirror buffers
@@ -465,7 +492,8 @@ void rlOrtho(double left, double right, double bottom, double top, double near,
#endif
-// Set the viewport area (trasnformation from normalized device coordinates to window coordinates)
+// Set the viewport area (transformation from normalized device coordinates to window coordinates)
+// NOTE: Updates global variables: screenWidth, screenHeight
void rlViewport(int x, int y, int width, int height)
{
glViewport(x, y, width, height);
@@ -857,6 +885,8 @@ void rlDeleteRenderTextures(RenderTexture2D target)
if (target.id != 0) glDeleteFramebuffers(1, &target.id);
if (target.texture.id != 0) glDeleteTextures(1, &target.texture.id);
if (target.depth.id != 0) glDeleteTextures(1, &target.depth.id);
+
+ TraceLog(INFO, "[FBO ID %i] Unloaded render texture data from VRAM (GPU)", target.id);
#endif
}
@@ -916,6 +946,8 @@ int rlGetVersion(void)
{
#if defined(GRAPHICS_API_OPENGL_11)
return OPENGL_11;
+#elif defined(GRAPHICS_API_OPENGL_21)
+ return OPENGL_21;
#elif defined(GRAPHICS_API_OPENGL_33)
return OPENGL_33;
#elif defined(GRAPHICS_API_OPENGL_ES2)
@@ -927,8 +959,8 @@ int rlGetVersion(void)
// Module Functions Definition - rlgl Functions
//----------------------------------------------------------------------------------
-// Init OpenGL 3.3+ required data
-void rlglInit(void)
+// Initialize rlgl: OpenGL extensions, default buffers/shaders/textures, OpenGL states
+void rlglInit(int width, int height)
{
// Check OpenGL information and capabilities
//------------------------------------------------------------------------------
@@ -1074,18 +1106,7 @@ void rlglInit(void)
// Initialize buffers, default shaders and default textures
//----------------------------------------------------------
- // Set default draw mode
- currentDrawMode = RL_TRIANGLES;
-
- // Reset projection and modelview matrices
- projection = MatrixIdentity();
- modelview = MatrixIdentity();
- currentMatrix = &modelview;
-
- // Initialize matrix stack
- for (int i = 0; i < MATRIX_STACK_SIZE; i++) stack[i] = MatrixIdentity();
-
- // Create default white texture for plain colors (required by shader)
+ // Init default white texture
unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes)
whiteTexture = rlglLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1);
@@ -1097,7 +1118,8 @@ void rlglInit(void)
defaultShader = LoadDefaultShader();
currentShader = defaultShader;
- LoadDefaultBuffers(); // Initialize default vertex arrays buffers (lines, triangles, quads)
+ // Init default vertex arrays buffers (lines, triangles, quads)
+ LoadDefaultBuffers();
// Init temp vertex buffer, used when transformation required (translate, rotate, scale)
tempBuffer = (Vector3 *)malloc(sizeof(Vector3)*TEMP_VERTEX_BUFFER_SIZE);
@@ -1115,7 +1137,50 @@ void rlglInit(void)
drawsCounter = 1;
draws[drawsCounter - 1].textureId = whiteTexture;
+ currentDrawMode = RL_TRIANGLES; // Set default draw mode
+
+ // Init internal matrix stack (emulating OpenGL 1.1)
+ for (int i = 0; i < MATRIX_STACK_SIZE; i++) stack[i] = MatrixIdentity();
+
+ // Init internal projection and modelview matrices
+ projection = MatrixIdentity();
+ modelview = MatrixIdentity();
+ currentMatrix = &modelview;
+#endif // defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+
+ // Initialize OpenGL default states
+ //----------------------------------------------------------
+
+ // Init state: Depth test
+ glDepthFunc(GL_LEQUAL); // Type of depth testing to apply
+ glDisable(GL_DEPTH_TEST); // Disable depth testing for 2D (only used for 3D)
+
+ // Init state: Blending mode
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Color blending function (how colors are mixed)
+ glEnable(GL_BLEND); // Enable color blending (required to work with transparencies)
+
+ // Init state: Culling
+ // NOTE: All shapes/models triangles are drawn CCW
+ glCullFace(GL_BACK); // Cull the back face (default)
+ glFrontFace(GL_CCW); // Front face are defined counter clockwise (default)
+ glEnable(GL_CULL_FACE); // Enable backface culling
+
+#if defined(GRAPHICS_API_OPENGL_11)
+ // Init state: Color hints (deprecated in OpenGL 3.0+)
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Improve quality of color and texture coordinate interpolation
+ glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation)
#endif
+
+ // Init state: Color/Depth buffers clear
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set clear color (black)
+ glClearDepth(1.0f); // Set clear depth value (default)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers (depth buffer required for 3D)
+
+ // Store screen size into global variables
+ screenWidth = width;
+ screenHeight = height;
+
+ TraceLog(INFO, "OpenGL default states initialized successfully");
}
// Vertex Buffer Object deinitialization (memory free)
@@ -1145,76 +1210,32 @@ void rlglClose(void)
void rlglDraw(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-/*
- for (int i = 0; i < modelsCount; i++)
- {
- rlglDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform);
- }
-*/
- // NOTE: Default buffers always drawn at the end
+ // NOTE: In a future version, models could be stored in a stack...
+ //for (int i = 0; i < modelsCount; i++) rlglDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform);
+
+ // NOTE: Default buffers upload and draw
UpdateDefaultBuffers();
- DrawDefaultBuffers();
+
+ if (vrEnabled && vrControl) DrawDefaultBuffers(2);
+ else DrawDefaultBuffers(1);
#endif
}
-// Initialize Graphics Device (OpenGL stuff)
-// NOTE: Stores global variables screenWidth and screenHeight
-void rlglInitGraphics(int offsetX, int offsetY, int width, int height)
-{
- // NOTE: Required! viewport must be recalculated if screen resized!
- glViewport(offsetX/2, offsetY/2, width - offsetX, height - offsetY); // Set viewport width and height
-
- // NOTE: Don't confuse glViewport with the transformation matrix
- // NOTE: glViewport just defines the area of the context that you will actually draw to.
-
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set clear color (black)
- //glClearDepth(1.0f); // Clear depth buffer (default)
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, depth buffer is used for 3D
-
- glDisable(GL_DEPTH_TEST); // Disable depth testing for 2D (only used for 3D)
- glDepthFunc(GL_LEQUAL); // Type of depth testing to apply
-
- glEnable(GL_BLEND); // Enable color blending (required to work with transparencies)
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Color blending function (how colors are mixed)
-
-#if defined(GRAPHICS_API_OPENGL_11)
- glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Improve quality of color and texture coordinate interpolation (Deprecated in OGL 3.0)
- // Other options: GL_FASTEST, GL_DONT_CARE (default)
-#endif
-
- rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix
- rlLoadIdentity(); // Reset current matrix (PROJECTION)
-
- rlOrtho(0, width - offsetX, height - offsetY, 0, 0.0f, 1.0f); // Config orthographic mode: top-left corner --> (0,0)
-
- rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix
- rlLoadIdentity(); // Reset current matrix (MODELVIEW)
-
- // NOTE: All shapes/models triangles are drawn CCW
-
- glEnable(GL_CULL_FACE); // Enable backface culling (Disabled by default)
- //glCullFace(GL_BACK); // Cull the Back face (default)
- //glFrontFace(GL_CCW); // Front face are defined counter clockwise (default)
-
-#if defined(GRAPHICS_API_OPENGL_11)
- glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation) (Deprecated on OpenGL 3.3+)
- // Possible options: GL_SMOOTH (Color interpolation) or GL_FLAT (no interpolation)
-#endif
-
- TraceLog(INFO, "OpenGL graphic device initialized successfully");
-}
-
// Load OpenGL extensions
// NOTE: External loader function could be passed as a pointer
void rlglLoadExtensions(void *loader)
{
-#if defined(GRAPHICS_API_OPENGL_33)
- // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions
+#if defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_33)
+ // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions)
if (!gladLoadGLLoader((GLADloadproc)loader)) TraceLog(WARNING, "GLAD: Cannot load OpenGL extensions");
else TraceLog(INFO, "GLAD: OpenGL extensions loaded successfully");
-
- if (GLAD_GL_VERSION_3_3) TraceLog(INFO, "OpenGL 3.3 Core profile supported");
+
+#if defined(GRAPHICS_API_OPENGL_21)
+ if (GLAD_GL_VERSION_2_1) TraceLog(INFO, "OpenGL 2.1 profile supported");
+#elif defined(GRAPHICS_API_OPENGL_33)
+ if(GLAD_GL_VERSION_3_3) TraceLog(INFO, "OpenGL 3.3 Core profile supported");
else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported");
+#endif
// With GLAD, we can check if an extension is supported using the GLAD_GL_xxx booleans
//if (GLAD_GL_ARB_vertex_array_object) // Use GL_ARB_vertex_array_object
@@ -1628,8 +1649,8 @@ void rlglLoadMesh(Mesh *mesh, bool dynamic)
int drawHint = GL_STATIC_DRAW;
if (dynamic) drawHint = GL_DYNAMIC_DRAW;
- GLuint vaoId = 0; // Vertex Array Objects (VAO)
- GLuint vboId[7]; // Vertex Buffer Objects (VBOs)
+ GLuint vaoId = 0; // Vertex Array Objects (VAO)
+ GLuint vboId[7] = { 0 }; // Vertex Buffer Objects (VBOs)
if (vaoSupported)
{
@@ -1725,7 +1746,6 @@ void rlglLoadMesh(Mesh *mesh, bool dynamic)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*mesh->triangleCount*3, mesh->indices, GL_STATIC_DRAW);
}
-
mesh->vboId[0] = vboId[0]; // Vertex position VBO
mesh->vboId[1] = vboId[1]; // Texcoords VBO
mesh->vboId[2] = vboId[2]; // Normals VBO
@@ -1848,26 +1868,23 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
#endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ int eyesCount = 1;
+ if (vrEnabled) eyesCount = 2;
+
glUseProgram(material.shader.id);
+ // Upload to shader material.colDiffuse
+ float vColorDiffuse[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 };
+ glUniform4fv(material.shader.tintColorLoc, 1, vColorDiffuse);
+
// At this point the modelview matrix just contains the view matrix (camera)
// That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix()
Matrix matView = modelview; // View matrix (camera)
Matrix matProjection = projection; // Projection matrix (perspective)
-
+
// Calculate model-view matrix combining matModel and matView
Matrix matModelView = MatrixMultiply(transform, matView); // Transform to camera-space coordinates
- // Calculate model-view-projection matrix (MVP)
- Matrix matMVP = MatrixMultiply(matModelView, matProjection); // Transform to screen-space coordinates
-
- // Send combined model-view-projection matrix to shader
- glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP));
-
- // Upload to shader material.colDiffuse
- float vColorDiffuse[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 };
- glUniform4fv(material.shader.tintColorLoc, 1, vColorDiffuse);
-
// Check if using standard shader to get location points
// NOTE: standard shader specific locations are got at render time to keep Shader struct as simple as possible (with just default shader locations)
if (material.shader.id == standardShader.id)
@@ -1895,12 +1912,12 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
// Upload to shader glossiness
glUniform1f(glGetUniformLocation(material.shader.id, "glossiness"), material.glossiness);
}
-
+
// Set shader textures (diffuse, normal, specular)
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id);
glUniform1i(material.shader.mapTexture0Loc, 0); // Diffuse texture fits in active texture unit 0
-
+
if ((material.texNormal.id != 0) && (material.shader.mapTexture1Loc != -1))
{
// Upload to shader specular map flag
@@ -1920,7 +1937,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
glBindTexture(GL_TEXTURE_2D, material.texSpecular.id);
glUniform1i(material.shader.mapTexture2Loc, 2); // Specular texture fits in active texture unit 2
}
-
+
if (vaoSupported)
{
glBindVertexArray(mesh.vaoId);
@@ -1945,12 +1962,22 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
glEnableVertexAttribArray(material.shader.normalLoc);
}
- // Bind mesh VBO data: vertex colors (shader-location = 3, if available) , tangents, texcoords2 (if available)
+ // Bind mesh VBO data: vertex colors (shader-location = 3, if available)
if (material.shader.colorLoc != -1)
{
- glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[3]);
- glVertexAttribPointer(material.shader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
- glEnableVertexAttribArray(material.shader.colorLoc);
+ if (mesh.vboId[3] != 0)
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[3]);
+ glVertexAttribPointer(material.shader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
+ glEnableVertexAttribArray(material.shader.colorLoc);
+ }
+ else
+ {
+ // Set default value for unused attribute
+ // NOTE: Required when using default shader and no VAO support
+ glVertexAttrib4f(material.shader.colorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
+ glDisableVertexAttribArray(material.shader.colorLoc);
+ }
}
// Bind mesh VBO data: vertex tangents (shader-location = 4, if available)
@@ -1972,9 +1999,21 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]);
}
- // Draw call!
- if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw
- else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount);
+ for (int eye = 0; eye < eyesCount; eye++)
+ {
+ if (eyesCount == 2) SetOculusView(eye, matProjection, matModelView);
+ else modelview = matModelView;
+
+ // Calculate model-view-projection matrix (MVP)
+ Matrix matMVP = MatrixMultiply(modelview, projection); // Transform to screen-space coordinates
+
+ // Send combined model-view-projection matrix to shader
+ glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP));
+
+ // Draw call!
+ if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw
+ else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount);
+ }
if (material.texNormal.id != 0)
{
@@ -1999,6 +2038,10 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
}
glUseProgram(0); // Unbind shader program
+
+ // Restore projection/modelview matrices
+ projection = matProjection;
+ modelview = matView;
#endif
}
@@ -2293,7 +2336,7 @@ Shader GetDefaultShader(void)
Shader GetStandardShader(void)
{
Shader shader = { 0 };
-
+
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if (standardShaderLoaded) shader = standardShader;
else
@@ -2314,7 +2357,7 @@ int GetShaderLocation(Shader shader, const char *uniformName)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
location = glGetUniformLocation(shader.id, uniformName);
- if (location == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName);
+ if (location == -1) TraceLog(DEBUG, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName);
#endif
return location;
}
@@ -2461,131 +2504,348 @@ void DestroyLight(Light light)
#endif
}
-#if defined(RLGL_OCULUS_SUPPORT)
-// Init Oculus Rift device
-// NOTE: Device initialization should be done before window creation?
+// Init Oculus Rift device (or Oculus device simulator)
void InitOculusDevice(void)
{
+#if defined(RLGL_OCULUS_SUPPORT)
// Initialize Oculus device
ovrResult result = ovr_Initialize(NULL);
- if (OVR_FAILURE(result)) TraceLog(WARNING, "OVR: Could not initialize Oculus device");
-
- result = ovr_Create(&session, &luid);
if (OVR_FAILURE(result))
{
- TraceLog(WARNING, "OVR: Could not create Oculus session");
- ovr_Shutdown();
+ TraceLog(WARNING, "OVR: Could not initialize Oculus device");
+ oculusReady = false;
}
+ else
+ {
+ result = ovr_Create(&session, &luid);
+ if (OVR_FAILURE(result))
+ {
+ TraceLog(WARNING, "OVR: Could not create Oculus session");
+ ovr_Shutdown();
+ oculusReady = false;
+ }
+ else
+ {
+ hmdDesc = ovr_GetHmdDesc(session);
+
+ TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName);
+ TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer);
+ TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId);
+ TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type);
+ //TraceLog(INFO, "OVR: Serial Number: %s", hmdDesc.SerialNumber);
+ TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h);
+
+ // NOTE: Oculus mirror is set to defined screenWidth and screenHeight...
+ // ...ideally, it should be (hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2)
+
+ // Initialize Oculus Buffers
+ layer = InitOculusLayer(session);
+ buffer = LoadOculusBuffer(session, layer.width, layer.height);
+ mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2); // NOTE: hardcoded...
+ layer.eyeLayer.ColorTexture[0] = buffer.textureChain; //SetOculusLayerTexture(eyeLayer, buffer.textureChain);
+
+ // Recenter OVR tracking origin
+ ovr_RecenterTrackingOrigin(session);
+
+ oculusReady = true;
+ vrEnabled = true;
+ }
+ }
+#else
+ oculusReady = false;
+#endif
- hmdDesc = ovr_GetHmdDesc(session);
-
- TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName);
- TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer);
- TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId);
- TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type);
- //TraceLog(INFO, "OVR: Serial Number: %s", hmdDesc.SerialNumber);
- TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h);
-
- // NOTE: Oculus mirror is set to defined screenWidth and screenHeight...
- // ...ideally, it should be (hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2)
-
- // Initialize Oculus Buffers
- layer = InitOculusLayer(session);
- buffer = LoadOculusBuffer(session, layer.width, layer.height);
- mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2); // NOTE: hardcoded...
- layer.eyeLayer.ColorTexture[0] = buffer.textureChain; //SetOculusLayerTexture(eyeLayer, buffer.textureChain);
-
- // Recenter OVR tracking origin
- ovr_RecenterTrackingOrigin(session);
+ if (!oculusReady)
+ {
+ TraceLog(WARNING, "VR: Initializing Oculus simulator");
+
+ // Initialize framebuffer and textures for stereo rendering
+ stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight);
+
+ // Load oculus-distortion shader (oculus parameters setup internally)
+ // TODO: Embed coulus distortion shader (in this function like default shader?)
+ distortionShader = LoadShader("resources/shaders/glsl330/base.vs", "resources/shaders/glsl330/distortion.fs");
+
+ oculusSimulator = true;
+ vrEnabled = true;
+ }
}
-// Close Oculus Rift device
+// Close Oculus Rift device (or Oculus device simulator)
void CloseOculusDevice(void)
{
- UnloadOculusMirror(session, mirror); // Unload Oculus mirror buffer
- UnloadOculusBuffer(session, buffer); // Unload Oculus texture buffers
+#if defined(RLGL_OCULUS_SUPPORT)
+ if (oculusReady)
+ {
+ UnloadOculusMirror(session, mirror); // Unload Oculus mirror buffer
+ UnloadOculusBuffer(session, buffer); // Unload Oculus texture buffers
- ovr_Destroy(session); // Free Oculus session data
- ovr_Shutdown(); // Close Oculus device connection
+ ovr_Destroy(session); // Free Oculus session data
+ ovr_Shutdown(); // Close Oculus device connection
+ }
+ else
+#endif
+ {
+ // Unload stereo framebuffer and texture
+ rlDeleteRenderTextures(stereoFbo);
+
+ // Unload oculus-distortion shader
+ UnloadShader(distortionShader);
+ }
+
+ oculusReady = false;
+}
+
+// Detect if oculus device is available
+bool IsOculusReady(void)
+{
+ return (oculusReady || oculusSimulator) && vrEnabled;
+}
+
+// Enable/Disable VR experience (Oculus device or simulator)
+void ToggleVR(void)
+{
+ vrEnabled = !vrEnabled;
}
// Update Oculus Rift tracking (position and orientation)
void UpdateOculusTracking(void)
{
- frameIndex++;
+#if defined(RLGL_OCULUS_SUPPORT)
+ if (oculusReady)
+ {
+ frameIndex++;
- ovrPosef eyePoses[2];
- ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime);
-
- layer.eyeLayer.RenderPose[0] = eyePoses[0];
- layer.eyeLayer.RenderPose[1] = eyePoses[1];
+ ovrPosef eyePoses[2];
+ ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime);
+
+ layer.eyeLayer.RenderPose[0] = eyePoses[0];
+ layer.eyeLayer.RenderPose[1] = eyePoses[1];
+
+ // Get session status information
+ ovrSessionStatus sessionStatus;
+ ovr_GetSessionStatus(session, &sessionStatus);
+
+ if (sessionStatus.ShouldQuit) TraceLog(WARNING, "OVR: Session should quit...");
+ if (sessionStatus.ShouldRecenter) ovr_RecenterTrackingOrigin(session);
+ //if (sessionStatus.HmdPresent) // HMD is present.
+ //if (sessionStatus.DisplayLost) // HMD was unplugged or the display driver was manually disabled or encountered a TDR.
+ //if (sessionStatus.HmdMounted) // HMD is on the user's head.
+ //if (sessionStatus.IsVisible) // the game or experience has VR focus and is visible in the HMD.
+ }
+ else
+#endif
+ {
+ // TODO: Use alternative inputs (mouse, keyboard) to simulate tracking data (eyes position/orientation)
+ }
}
-void SetOculusMatrix(int eye)
-{
- rlViewport(layer.eyeLayer.Viewport[eye].Pos.x, layer.eyeLayer.Viewport[eye].Pos.y, layer.eyeLayer.Viewport[eye].Size.w, layer.eyeLayer.Viewport[eye].Size.h);
+// Set internal projection and modelview matrix depending on eyes tracking data
+static void SetOculusView(int eye, Matrix matProjection, Matrix matModelView)
+{
+ if (vrEnabled)
+ {
+ Matrix eyeProjection = matProjection;
+ Matrix eyeModelView = matModelView;
+
+#if defined(RLGL_OCULUS_SUPPORT)
+ if (oculusReady)
+ {
+ rlViewport(layer.eyeLayer.Viewport[eye].Pos.x, layer.eyeLayer.Viewport[eye].Pos.y,
+ layer.eyeLayer.Viewport[eye].Size.w, layer.eyeLayer.Viewport[eye].Size.h);
- Quaternion eyeRPose = (Quaternion){ layer.eyeLayer.RenderPose[eye].Orientation.x,
- layer.eyeLayer.RenderPose[eye].Orientation.y,
- layer.eyeLayer.RenderPose[eye].Orientation.z,
- layer.eyeLayer.RenderPose[eye].Orientation.w };
- QuaternionInvert(&eyeRPose);
- Matrix eyeOrientation = QuaternionToMatrix(eyeRPose);
- Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x,
- -layer.eyeLayer.RenderPose[eye].Position.y,
- -layer.eyeLayer.RenderPose[eye].Position.z);
+ Quaternion eyeRenderPose = (Quaternion){ layer.eyeLayer.RenderPose[eye].Orientation.x,
+ layer.eyeLayer.RenderPose[eye].Orientation.y,
+ layer.eyeLayer.RenderPose[eye].Orientation.z,
+ layer.eyeLayer.RenderPose[eye].Orientation.w };
+ QuaternionInvert(&eyeRenderPose);
+ Matrix eyeOrientation = QuaternionToMatrix(eyeRenderPose);
+ Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x,
+ -layer.eyeLayer.RenderPose[eye].Position.y,
+ -layer.eyeLayer.RenderPose[eye].Position.z);
- Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation);
- Matrix modelEyeView = MatrixMultiply(modelview, eyeView); // Using internal camera modelview matrix
+ Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); // Matrix containing eye-head movement
+ eyeModelView = MatrixMultiply(matModelView, eyeView); // Combine internal camera matrix (modelview) wih eye-head movement
- SetMatrixModelview(modelEyeView);
- SetMatrixProjection(layer.eyeProjections[eye]);
+ eyeProjection = layer.eyeProjections[eye];
+ }
+ else
+#endif
+ {
+ // Setup viewport and projection/modelview matrices using tracking data
+ rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight);
+
+ static float IPD = 0.064f; // InterpupillaryDistance
+ float HScreenSize = 0.14976f;
+ float VScreenSize = 0.0936f; // HScreenSize/(1280.0f/800.0f)
+ float VScreenCenter = 0.04675f;
+ float EyeToScreenDistance = 0.041f;
+ float LensSeparationDistance = 0.064f; //0.0635f (DK1)
+
+ // NOTE: fovy value obtained from device parameters (Oculus Rift CV1)
+ float halfScreenDistance = VScreenSize/2.0f;
+ float fovy = 2.0f*atan(halfScreenDistance/EyeToScreenDistance)*RAD2DEG;
+
+ float viewCenter = (float)HScreenSize*0.25f;
+ float eyeProjectionShift = viewCenter - LensSeparationDistance*0.5f;
+ float projectionCenterOffset = eyeProjectionShift/(float)HScreenSize; //4.0f*eyeProjectionShift/(float)HScreenSize;
+/*
+ static float scale[2] = { 0.25, 0.45 };
+
+ if (IsKeyDown(KEY_RIGHT)) scale[0] += 0.01;
+ else if (IsKeyDown(KEY_LEFT)) scale[0] -= 0.01;
+ else if (IsKeyDown(KEY_UP)) scale[1] += 0.01;
+ else if (IsKeyDown(KEY_DOWN)) scale[1] -= 0.01;
+
+ SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "Scale"), scale, 2);
+
+ if (IsKeyDown(KEY_N)) IPD += 0.02;
+ else if (IsKeyDown(KEY_M)) IPD -= 0.02;
+*/
+ // The matrixes for offsetting the projection and view for each eye, to achieve stereo effect
+ Vector3 projectionOffset = { -projectionCenterOffset, 0.0f, 0.0f };
+
+ // Camera movement might seem more natural if we model the head.
+ // Our axis of rotation is the base of our head, so we might want to add
+ // some y (base of head to eye level) and -z (center of head to eye protrusion) to the camera positions.
+ Vector3 viewOffset = { -IPD/2.0f, 0.075f, 0.045f };
+
+ // Negate the left eye versions
+ if (eye == 0)
+ {
+ projectionOffset.x *= -1.0f;
+ viewOffset.x *= -1.0f;
+ }
+
+ // Adjust the view and projection matrixes
+ // View matrix is translated based on the eye offset
+ Matrix projCenter = MatrixPerspective(fovy, (double)((float)screenWidth*0.5f)/(double)screenHeight, 0.01, 1000.0);
+
+ Matrix projTranslation = MatrixTranslate(projectionOffset.x, projectionOffset.y, projectionOffset.z);
+ Matrix viewTranslation = MatrixTranslate(viewOffset.x, viewOffset.y, viewOffset.z);
+
+ eyeProjection = MatrixMultiply(projCenter, projTranslation); // projection
+ eyeModelView = MatrixMultiply(matModelView, viewTranslation); // modelview
+
+ MatrixTranspose(&eyeProjection);
+ }
+
+ SetMatrixModelview(eyeModelView); // ERROR! We are modifying modelview for next eye!!!
+ SetMatrixProjection(eyeProjection);
+ }
}
+// Begin Oculus drawing configuration
void BeginOculusDrawing(void)
{
- GLuint currentTexId;
- int currentIndex;
-
- ovr_GetTextureSwapChainCurrentIndex(session, buffer.textureChain, ¤tIndex);
- ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, currentIndex, ¤tTexId);
+#if defined(RLGL_OCULUS_SUPPORT)
+ if (oculusReady)
+ {
+ GLuint currentTexId;
+ int currentIndex;
+
+ ovr_GetTextureSwapChainCurrentIndex(session, buffer.textureChain, ¤tIndex);
+ ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, currentIndex, ¤tTexId);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer.fboId);
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, currentTexId, 0);
- //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, buffer.depthId, 0); // Already binded
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer.fboId);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, currentTexId, 0);
+ //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, buffer.depthId, 0); // Already binded
+ }
+ else
+#endif
+ {
+ // Setup framebuffer for stereo rendering
+ rlEnableRenderTexture(stereoFbo.id);
+ }
- //glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye)
- //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Same as rlClearScreenBuffers()
-
// NOTE: If your application is configured to treat the texture as a linear format (e.g. GL_RGBA)
// and performs linear-to-gamma conversion in GLSL or does not care about gamma-correction, then:
// - Require OculusBuffer format to be OVR_FORMAT_R8G8B8A8_UNORM_SRGB
// - Do NOT enable GL_FRAMEBUFFER_SRGB
//glEnable(GL_FRAMEBUFFER_SRGB);
+ //glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye)
rlClearScreenBuffers(); // Clear current framebuffer(s)
+
+ vrControl = true;
}
+// End Oculus drawing process (and desktop mirror)
void EndOculusDrawing(void)
{
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
-
- ovr_CommitTextureSwapChain(session, buffer.textureChain);
-
- ovrLayerHeader *layers = &layer.eyeLayer.Header;
- ovr_SubmitFrame(session, frameIndex, &layer.viewScaleDesc, &layers, 1);
+#if defined(RLGL_OCULUS_SUPPORT)
+ if (oculusReady)
+ {
+ // Unbind current framebuffer (Oculus buffer)
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+
+ ovr_CommitTextureSwapChain(session, buffer.textureChain);
+
+ ovrLayerHeader *layers = &layer.eyeLayer.Header;
+ ovr_SubmitFrame(session, frameIndex, &layer.viewScaleDesc, &layers, 1);
- // Blit mirror texture to back buffer
- BlitOculusMirror(session, mirror);
-
- // Get session status information
- ovrSessionStatus sessionStatus;
- ovr_GetSessionStatus(session, &sessionStatus);
- if (sessionStatus.ShouldQuit) TraceLog(WARNING, "OVR: Session should quit...");
- if (sessionStatus.ShouldRecenter) ovr_RecenterTrackingOrigin(session);
-}
+ // Blit mirror texture to back buffer
+ BlitOculusMirror(session, mirror);
+ }
+ else
#endif
+ {
+ // Unbind current framebuffer
+ rlDisableRenderTexture();
+
+ rlClearScreenBuffers(); // Clear current framebuffer
+
+ // Set viewport to default framebuffer size (screen size)
+ rlViewport(0, 0, screenWidth, screenHeight);
+
+ // Let rlgl reconfigure internal matrices
+ rlMatrixMode(RL_PROJECTION); // Enable internal projection matrix
+ rlLoadIdentity(); // Reset internal projection matrix
+ rlOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0); // Recalculate internal projection matrix
+ rlMatrixMode(RL_MODELVIEW); // Enable internal modelview matrix
+ rlLoadIdentity(); // Reset internal modelview matrix
+
+ // Draw RenderTexture (stereoFbo) using distortion shader
+ currentShader = distortionShader;
+
+ rlEnableTexture(stereoFbo.texture.id);
+
+ rlPushMatrix();
+ rlBegin(RL_QUADS);
+ rlColor4ub(255, 255, 255, 255);
+ rlNormal3f(0.0f, 0.0f, 1.0f);
+
+ // Bottom-left corner for texture and quad
+ rlTexCoord2f(0.0f, 1.0f);
+ rlVertex2f(0.0f, 0.0f);
+
+ // Bottom-right corner for texture and quad
+ rlTexCoord2f(0.0f, 0.0f);
+ rlVertex2f(0.0f, stereoFbo.texture.height);
+
+ // Top-right corner for texture and quad
+ rlTexCoord2f(1.0f, 0.0f);
+ rlVertex2f(stereoFbo.texture.width, stereoFbo.texture.height);
+
+ // Top-left corner for texture and quad
+ rlTexCoord2f(1.0f, 1.0f);
+ rlVertex2f(stereoFbo.texture.width, 0.0f);
+ rlEnd();
+ rlPopMatrix();
+
+ rlDisableTexture();
+
+ UpdateDefaultBuffers();
+ DrawDefaultBuffers(1);
+
+ currentShader = defaultShader;
+ }
+
+ rlDisableDepthTest();
+
+ vrControl = false;
+}
//----------------------------------------------------------------------------------
// Module specific Functions Definition
@@ -2746,55 +3006,65 @@ static Shader LoadDefaultShader(void)
Shader shader;
// Vertex shader directly defined, no external file required
-#if defined(GRAPHICS_API_OPENGL_33)
- char vShaderStr[] = "#version 330 \n"
- "in vec3 vertexPosition; \n"
- "in vec2 vertexTexCoord; \n"
- "in vec4 vertexColor; \n"
- "out vec2 fragTexCoord; \n"
- "out vec4 fragColor; \n"
+ char vDefaultShaderStr[] =
+#if defined(GRAPHICS_API_OPENGL_21)
+ "#version 120 \n"
#elif defined(GRAPHICS_API_OPENGL_ES2)
- char vShaderStr[] = "#version 100 \n"
- "attribute vec3 vertexPosition; \n"
- "attribute vec2 vertexTexCoord; \n"
- "attribute vec4 vertexColor; \n"
- "varying vec2 fragTexCoord; \n"
- "varying vec4 fragColor; \n"
+ "#version 100 \n"
#endif
- "uniform mat4 mvpMatrix; \n"
- "void main() \n"
- "{ \n"
- " fragTexCoord = vertexTexCoord; \n"
- " fragColor = vertexColor; \n"
- " gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n"
- "} \n";
+#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
+ "attribute vec3 vertexPosition; \n"
+ "attribute vec2 vertexTexCoord; \n"
+ "attribute vec4 vertexColor; \n"
+ "varying vec2 fragTexCoord; \n"
+ "varying vec4 fragColor; \n"
+#elif defined(GRAPHICS_API_OPENGL_33)
+ "#version 330 \n"
+ "in vec3 vertexPosition; \n"
+ "in vec2 vertexTexCoord; \n"
+ "in vec4 vertexColor; \n"
+ "out vec2 fragTexCoord; \n"
+ "out vec4 fragColor; \n"
+#endif
+ "uniform mat4 mvpMatrix; \n"
+ "void main() \n"
+ "{ \n"
+ " fragTexCoord = vertexTexCoord; \n"
+ " fragColor = vertexColor; \n"
+ " gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n"
+ "} \n";
// Fragment shader directly defined, no external file required
-#if defined(GRAPHICS_API_OPENGL_33)
- char fShaderStr[] = "#version 330 \n"
- "in vec2 fragTexCoord; \n"
- "in vec4 fragColor; \n"
- "out vec4 finalColor; \n"
+ char fDefaultShaderStr[] =
+#if defined(GRAPHICS_API_OPENGL_21)
+ "#version 120 \n"
#elif defined(GRAPHICS_API_OPENGL_ES2)
- char fShaderStr[] = "#version 100 \n"
- "precision mediump float; \n" // precision required for OpenGL ES2 (WebGL)
- "varying vec2 fragTexCoord; \n"
- "varying vec4 fragColor; \n"
+ "#version 100 \n"
+ "precision mediump float; \n" // precision required for OpenGL ES2 (WebGL)
#endif
- "uniform sampler2D texture0; \n"
- "uniform vec4 colDiffuse; \n"
- "void main() \n"
- "{ \n"
-#if defined(GRAPHICS_API_OPENGL_33)
- " vec4 texelColor = texture(texture0, fragTexCoord); \n"
- " finalColor = texelColor*colDiffuse*fragColor; \n"
-#elif defined(GRAPHICS_API_OPENGL_ES2)
- " vec4 texelColor = texture2D(texture0, fragTexCoord); \n" // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0
- " gl_FragColor = texelColor*colDiffuse*fragColor; \n"
+#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
+ "varying vec2 fragTexCoord; \n"
+ "varying vec4 fragColor; \n"
+#elif defined(GRAPHICS_API_OPENGL_33)
+ "#version 330 \n"
+ "in vec2 fragTexCoord; \n"
+ "in vec4 fragColor; \n"
+ "out vec4 finalColor; \n"
#endif
- "} \n";
+ "uniform sampler2D texture0; \n"
+ "uniform vec4 colDiffuse; \n"
+ "void main() \n"
+ "{ \n"
+#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
+ " vec4 texelColor = texture2D(texture0, fragTexCoord); \n" // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0
+ " gl_FragColor = texelColor*colDiffuse*fragColor; \n"
+#elif defined(GRAPHICS_API_OPENGL_33)
+ " vec4 texelColor = texture(texture0, fragTexCoord); \n"
+ " finalColor = texelColor*colDiffuse*fragColor; \n"
+#endif
+ "} \n";
- shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
+ shader.id = LoadShaderProgram(vDefaultShaderStr, fDefaultShaderStr);
if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id);
else TraceLog(WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id);
@@ -2813,6 +3083,7 @@ static Shader LoadStandardShader(void)
{
Shader shader;
+#if !defined(RLGL_NO_STANDARD_SHADER)
// Load standard shader (embeded in standard_shader.h)
shader.id = LoadShaderProgram(vStandardShaderStr, fStandardShaderStr);
@@ -2828,6 +3099,10 @@ static Shader LoadStandardShader(void)
TraceLog(WARNING, "[SHDR ID %i] Standard shader could not be loaded, using default shader", shader.id);
shader = GetDefaultShader();
}
+#else
+ shader = defaultShader;
+ TraceLog(WARNING, "[SHDR ID %i] Standard shader not available, using default shader", shader.id);
+#endif
return shader;
}
@@ -2878,12 +3153,13 @@ static void UnloadDefaultShader(void)
static void UnloadStandardShader(void)
{
glUseProgram(0);
-
+#if !defined(RLGL_NO_STANDARD_SHADER)
//glDetachShader(defaultShader, vertexShader);
//glDetachShader(defaultShader, fragmentShader);
//glDeleteShader(vertexShader); // Already deleted on shader compilation
//glDeleteShader(fragmentShader); // Already deleted on shader compilation
glDeleteProgram(standardShader.id);
+#endif
}
@@ -3009,7 +3285,7 @@ static void LoadDefaultBuffers(void)
glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers VAO initialized successfully (triangles)", triangles.vaoId);
- else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully(triangles)", triangles.vboId[0], triangles.vboId[1]);
+ else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (triangles)", triangles.vboId[0], triangles.vboId[1]);
// Upload and link quads vertex buffers
if (vaoSupported)
@@ -3131,146 +3407,154 @@ static void UpdateDefaultBuffers(void)
// Draw default internal buffers vertex data
// NOTE: We draw in this order: lines, triangles, quads
-static void DrawDefaultBuffers(void)
+static void DrawDefaultBuffers(int eyesCount)
{
- // Set current shader and upload current MVP matrix
- if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0))
+ Matrix matProjection = projection;
+ Matrix matModelView = modelview;
+
+ for (int eye = 0; eye < eyesCount; eye++)
{
- glUseProgram(currentShader.id);
-
- // Create modelview-projection matrix
- Matrix matMVP = MatrixMultiply(modelview, projection);
+ if (eyesCount == 2) SetOculusView(eye, matProjection, matModelView);
- glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP));
- glUniform4f(currentShader.tintColorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
- glUniform1i(currentShader.mapTexture0Loc, 0);
-
- // NOTE: Additional map textures not considered for default buffers drawing
- }
-
- // Draw lines buffers
- if (lines.vCounter > 0)
- {
- glBindTexture(GL_TEXTURE_2D, whiteTexture);
-
- if (vaoSupported)
+ // Set current shader and upload current MVP matrix
+ if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0))
{
- glBindVertexArray(lines.vaoId);
- }
- else
- {
- // Bind vertex attrib: position (shader-location = 0)
- glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]);
- glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
- glEnableVertexAttribArray(currentShader.vertexLoc);
-
- // Bind vertex attrib: color (shader-location = 3)
- glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[1]);
- glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
- glEnableVertexAttribArray(currentShader.colorLoc);
- }
-
- glDrawArrays(GL_LINES, 0, lines.vCounter);
-
- if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindTexture(GL_TEXTURE_2D, 0);
- }
-
- // Draw triangles buffers
- if (triangles.vCounter > 0)
- {
- glBindTexture(GL_TEXTURE_2D, whiteTexture);
-
- if (vaoSupported)
- {
- glBindVertexArray(triangles.vaoId);
- }
- else
- {
- // Bind vertex attrib: position (shader-location = 0)
- glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]);
- glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
- glEnableVertexAttribArray(currentShader.vertexLoc);
-
- // Bind vertex attrib: color (shader-location = 3)
- glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[1]);
- glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
- glEnableVertexAttribArray(currentShader.colorLoc);
- }
-
- glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter);
-
- if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindTexture(GL_TEXTURE_2D, 0);
- }
-
- // Draw quads buffers
- if (quads.vCounter > 0)
- {
- int quadsCount = 0;
- int numIndicesToProcess = 0;
- int indicesOffset = 0;
-
- if (vaoSupported)
- {
- glBindVertexArray(quads.vaoId);
- }
- else
- {
- // Bind vertex attrib: position (shader-location = 0)
- glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]);
- glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
- glEnableVertexAttribArray(currentShader.vertexLoc);
-
- // Bind vertex attrib: texcoord (shader-location = 1)
- glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[1]);
- glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
- glEnableVertexAttribArray(currentShader.texcoordLoc);
-
- // Bind vertex attrib: color (shader-location = 3)
- glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]);
- glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
- glEnableVertexAttribArray(currentShader.colorLoc);
+ glUseProgram(currentShader.id);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]);
+ // Create modelview-projection matrix
+ Matrix matMVP = MatrixMultiply(modelview, projection);
+
+ glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP));
+ glUniform4f(currentShader.tintColorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
+ glUniform1i(currentShader.mapTexture0Loc, 0);
+
+ // NOTE: Additional map textures not considered for default buffers drawing
}
-
- //TraceLog(DEBUG, "Draws required per frame: %i", drawsCounter);
-
- for (int i = 0; i < drawsCounter; i++)
+
+ // Draw lines buffers
+ if (lines.vCounter > 0)
{
- quadsCount = draws[i].vertexCount/4;
- numIndicesToProcess = quadsCount*6; // Get number of Quads * 6 index by Quad
+ glBindTexture(GL_TEXTURE_2D, whiteTexture);
- //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount);
+ if (vaoSupported)
+ {
+ glBindVertexArray(lines.vaoId);
+ }
+ else
+ {
+ // Bind vertex attrib: position (shader-location = 0)
+ glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]);
+ glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(currentShader.vertexLoc);
- glBindTexture(GL_TEXTURE_2D, draws[i].textureId);
+ // Bind vertex attrib: color (shader-location = 3)
+ glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[1]);
+ glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
+ glEnableVertexAttribArray(currentShader.colorLoc);
+ }
- // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process
-#if defined(GRAPHICS_API_OPENGL_33)
- glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*indicesOffset));
-#elif defined(GRAPHICS_API_OPENGL_ES2)
- glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*indicesOffset));
-#endif
- //GLenum err;
- //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(INFO, "OpenGL error: %i", (int)err); //GL_INVALID_ENUM!
+ glDrawArrays(GL_LINES, 0, lines.vCounter);
- indicesOffset += draws[i].vertexCount/4*6;
+ if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
}
- if (!vaoSupported)
+ // Draw triangles buffers
+ if (triangles.vCounter > 0)
{
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindTexture(GL_TEXTURE_2D, whiteTexture);
+
+ if (vaoSupported)
+ {
+ glBindVertexArray(triangles.vaoId);
+ }
+ else
+ {
+ // Bind vertex attrib: position (shader-location = 0)
+ glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]);
+ glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(currentShader.vertexLoc);
+
+ // Bind vertex attrib: color (shader-location = 3)
+ glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[1]);
+ glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
+ glEnableVertexAttribArray(currentShader.colorLoc);
+ }
+
+ glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter);
+
+ if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
}
- glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures
+ // Draw quads buffers
+ if (quads.vCounter > 0)
+ {
+ int quadsCount = 0;
+ int numIndicesToProcess = 0;
+ int indicesOffset = 0;
+
+ if (vaoSupported)
+ {
+ glBindVertexArray(quads.vaoId);
+ }
+ else
+ {
+ // Bind vertex attrib: position (shader-location = 0)
+ glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]);
+ glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(currentShader.vertexLoc);
+
+ // Bind vertex attrib: texcoord (shader-location = 1)
+ glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[1]);
+ glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(currentShader.texcoordLoc);
+
+ // Bind vertex attrib: color (shader-location = 3)
+ glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]);
+ glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
+ glEnableVertexAttribArray(currentShader.colorLoc);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]);
+ }
+
+ //TraceLog(DEBUG, "Draws required per frame: %i", drawsCounter);
+
+ for (int i = 0; i < drawsCounter; i++)
+ {
+ quadsCount = draws[i].vertexCount/4;
+ numIndicesToProcess = quadsCount*6; // Get number of Quads * 6 index by Quad
+
+ //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount);
+
+ glBindTexture(GL_TEXTURE_2D, draws[i].textureId);
+
+ // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process
+ #if defined(GRAPHICS_API_OPENGL_33)
+ glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*indicesOffset));
+ #elif defined(GRAPHICS_API_OPENGL_ES2)
+ glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*indicesOffset));
+ #endif
+ //GLenum err;
+ //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(INFO, "OpenGL error: %i", (int)err); //GL_INVALID_ENUM!
+
+ indicesOffset += draws[i].vertexCount/4*6;
+ }
+
+ if (!vaoSupported)
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures
+ }
+
+ if (vaoSupported) glBindVertexArray(0); // Unbind VAO
+
+ glUseProgram(0); // Unbind shader program
}
-
- if (vaoSupported) glBindVertexArray(0); // Unbind VAO
-
- glUseProgram(0); // Unbind shader program
-
+
// Reset draws counter
drawsCounter = 1;
draws[0].textureId = whiteTexture;
@@ -3287,6 +3571,10 @@ static void DrawDefaultBuffers(void)
// Reset depth for next draw
currentDepth = -1.0f;
+
+ // Restore projection/modelview matrices
+ projection = matProjection;
+ modelview = matModelView;
}
// Unload default internal buffers vertex data from CPU and GPU
@@ -3682,7 +3970,10 @@ static void BlitOculusMirror(ovrSession session, OculusMirror mirror)
glBindFramebuffer(GL_READ_FRAMEBUFFER, mirror.fboId);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mirrorTextureId, 0);
+#if defined(GRAPHICS_API_OPENGL_33)
+ // NOTE: glBlitFramebuffer() requires extension: GL_EXT_framebuffer_blit (not available in OpenGL ES 2.0)
glBlitFramebuffer(0, 0, mirror.width, mirror.height, 0, mirror.height, mirror.width, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+#endif
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
diff --git a/src/rlgl.h b/src/rlgl.h
index 1e77b771e..f52af6f9d 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -48,25 +48,31 @@
// Choose opengl version here or just define it at compile time: -DGRAPHICS_API_OPENGL_33
//#define GRAPHICS_API_OPENGL_11 // Only available on PLATFORM_DESKTOP
-//#define GRAPHICS_API_OPENGL_33 // Only available on PLATFORM_DESKTOP or PLATFORM_OCULUS
+//#define GRAPHICS_API_OPENGL_33 // Only available on PLATFORM_DESKTOP and RLGL_OCULUS_SUPPORT
//#define GRAPHICS_API_OPENGL_ES2 // Only available on PLATFORM_ANDROID or PLATFORM_RPI or PLATFORM_WEB
// Security check in case no GRAPHICS_API_OPENGL_* defined
-#if !defined(GRAPHICS_API_OPENGL_11) && !defined(GRAPHICS_API_OPENGL_33) && !defined(GRAPHICS_API_OPENGL_ES2)
+#if !defined(GRAPHICS_API_OPENGL_11) && !defined(GRAPHICS_API_OPENGL_21) && !defined(GRAPHICS_API_OPENGL_33) && !defined(GRAPHICS_API_OPENGL_ES2)
#define GRAPHICS_API_OPENGL_11
#endif
// Security check in case multiple GRAPHICS_API_OPENGL_* defined
#if defined(GRAPHICS_API_OPENGL_11)
+ #if defined(GRAPHICS_API_OPENGL_21)
+ #undef GRAPHICS_API_OPENGL_21
+ #endif
#if defined(GRAPHICS_API_OPENGL_33)
#undef GRAPHICS_API_OPENGL_33
#endif
-
#if defined(GRAPHICS_API_OPENGL_ES2)
#undef GRAPHICS_API_OPENGL_ES2
#endif
#endif
+#if defined(GRAPHICS_API_OPENGL_21)
+ #define GRAPHICS_API_OPENGL_33
+#endif
+
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
@@ -90,7 +96,7 @@ typedef enum { RL_PROJECTION, RL_MODELVIEW, RL_TEXTURE } MatrixMode;
typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode;
-typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
+typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion;
#if defined(RLGL_STANDALONE)
#ifndef __cplusplus
@@ -292,10 +298,9 @@ int rlGetVersion(void); // Returns current OpenGL versio
//------------------------------------------------------------------------------------
// Functions Declaration - rlgl functionality
//------------------------------------------------------------------------------------
-void rlglInit(void); // Initialize rlgl (shaders, VAO, VBO...)
+void rlglInit(int width, int height); // Initialize rlgl (buffers, shaders, textures, states)
void rlglClose(void); // De-init rlgl
void rlglDraw(void); // Draw VAO/VBO
-void rlglInitGraphics(int offsetX, int offsetY, int width, int height); // Initialize Graphics (OpenGL stuff)
void rlglLoadExtensions(void *loader); // Load OpenGL extensions
unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount); // Load texture in GPU
@@ -347,14 +352,13 @@ void DestroyLight(Light light); // Destroy a
void TraceLog(int msgType, const char *text, ...);
#endif
-#if defined(RLGL_OCULUS_SUPPORT)
void InitOculusDevice(void); // Init Oculus Rift device
void CloseOculusDevice(void); // Close Oculus Rift device
void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation)
-void SetOculusMatrix(int eye); // Set internal projection and modelview matrix depending on eyes tracking data
void BeginOculusDrawing(void); // Begin Oculus drawing configuration
void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror)
-#endif
+bool IsOculusReady(void); // Detect if oculus device (or simulator) is ready
+void ToggleVR(void); // Enable/Disable VR experience (Oculus device or simulator)
#ifdef __cplusplus
}
diff --git a/src/shapes.c b/src/shapes.c
index 3ccfd660a..2a4e19c26 100644
--- a/src/shapes.c
+++ b/src/shapes.c
@@ -135,7 +135,7 @@ void DrawCircleV(Vector2 center, float radius, Color color)
}
rlEnd();
}
- else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
+ else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
{
rlEnableTexture(GetDefaultTexture().id); // Default white texture
@@ -218,7 +218,7 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color)
rlVertex2i(position.x + size.x, position.y);
rlEnd();
}
- else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
+ else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
{
rlEnableTexture(GetDefaultTexture().id); // Default white texture
@@ -264,7 +264,7 @@ void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
rlVertex2i(posX + 1, posY + 1);
rlEnd();
}
- else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
+ else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
{
DrawRectangle(posX, posY, width, 1, color);
DrawRectangle(posX + width - 1, posY + 1, 1, height - 2, color);
diff --git a/src/standard_shader.h b/src/standard_shader.h
index a4bc96941..e1668ae79 100644
--- a/src/standard_shader.h
+++ b/src/standard_shader.h
@@ -166,9 +166,9 @@ static const char fStandardShaderStr[] =
" else if(lights[i].type == 2) lighting += CalcSpotLight(lights[i], n, v, spec);\n"
" }\n"
" }\n"
-#if defined(GRAPHICS_API_OPENGL_33)
-" finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n"
-#elif defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
+#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
" gl_FragColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n"
+#elif defined(GRAPHICS_API_OPENGL_33)
+" finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n"
#endif
"}\n";
diff --git a/src/textures.c b/src/textures.c
index 518348f40..f5523a3e9 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -422,12 +422,7 @@ void UnloadTexture(Texture2D texture)
// Unload render texture from GPU memory
void UnloadRenderTexture(RenderTexture2D target)
{
- if (target.id != 0)
- {
- rlDeleteRenderTextures(target);
-
- TraceLog(INFO, "[FBO ID %i] Unloaded render texture data from VRAM (GPU)", target.id);
- }
+ if (target.id != 0) rlDeleteRenderTextures(target);
}
// Get pixel data from image in the form of Color struct array