Redesigned stereo rendering mechanism

Now it's easier for the user! Just init Oculus device and get stereo
rendering!
This commit is contained in:
Ray 2016-07-04 01:29:23 +02:00
parent 164ead03c9
commit ee72654b55
6 changed files with 259 additions and 244 deletions

View file

@ -55,18 +55,11 @@ int main()
Begin3dMode(camera); Begin3dMode(camera);
for (int eye = 0; eye < 2; eye++)
{
SetOculusView(eye);
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
DrawGrid(10, 1.0f); DrawGrid(10, 1.0f);
DrawDefaultBuffers(); // Process internal dynamic buffers
}
End3dMode(); End3dMode();
DrawFPS(10, 10); DrawFPS(10, 10);

View file

@ -10,12 +10,13 @@ uniform sampler2D texture0;
out vec4 finalColor; out vec4 finalColor;
// NOTE: Add here your custom variables // NOTE: Add here your custom variables
const vec2 LeftLensCenter = vec2(0.2863248, 0.5); const vec2 LeftLensCenter = vec2(0.288, 0.5);
const vec2 RightLensCenter = vec2(0.7136753, 0.5); const vec2 RightLensCenter = vec2(0.712, 0.5);
const vec2 LeftScreenCenter = vec2(0.25, 0.5); const vec2 LeftScreenCenter = vec2(0.25, 0.5);
const vec2 RightScreenCenter = vec2(0.75, 0.5); const vec2 RightScreenCenter = vec2(0.75, 0.5);
const vec2 Scale = vec2(0.25, 0.45); //vec2(0.1469278, 0.2350845); uniform vec2 Scale = vec2(0.25, 0.45); //vec2(0.1469278, 0.2350845);
const vec2 ScaleIn = vec2(4, 2.2222); uniform vec2 ScaleIn = vec2(4, 2.2222);
const vec4 HmdWarpParam = vec4(1, 0.22, 0.24, 0); const vec4 HmdWarpParam = vec4(1, 0.22, 0.24, 0);
const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0); const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0);

View file

@ -521,6 +521,8 @@ void BeginDrawing(void)
updateTime = currentTime - previousTime; updateTime = currentTime - previousTime;
previousTime = currentTime; previousTime = currentTime;
if (IsOculusReady()) BeginOculusDrawing();
rlClearScreenBuffers(); // Clear current framebuffers rlClearScreenBuffers(); // Clear current framebuffers
rlLoadIdentity(); // Reset current matrix (MODELVIEW) rlLoadIdentity(); // Reset current matrix (MODELVIEW)
rlMultMatrixf(MatrixToFloat(downscaleView)); // If downscale required, apply it here rlMultMatrixf(MatrixToFloat(downscaleView)); // If downscale required, apply it here
@ -534,6 +536,8 @@ void EndDrawing(void)
{ {
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2) rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
if (IsOculusReady()) EndOculusDrawing();
SwapBuffers(); // Copy back buffer to front buffer SwapBuffers(); // Copy back buffer to front buffer
PollInputEvents(); // Poll user events PollInputEvents(); // Poll user events
@ -608,15 +612,11 @@ void Begin3dMode(Camera camera)
rlMultMatrixf(MatrixToFloat(cameraView)); // Multiply MODELVIEW matrix by view matrix (camera) rlMultMatrixf(MatrixToFloat(cameraView)); // Multiply MODELVIEW matrix by view matrix (camera)
rlEnableDepthTest(); // Enable DEPTH_TEST for 3D rlEnableDepthTest(); // Enable DEPTH_TEST for 3D
if (IsOculusReady()) BeginOculusDrawing();
} }
// Ends 3D mode and returns to default 2D orthographic mode // Ends 3D mode and returns to default 2D orthographic mode
void End3dMode(void) void End3dMode(void)
{ {
if (IsOculusReady()) EndOculusDrawing();
rlglDraw(); // Process internal buffers (update + draw) rlglDraw(); // Process internal buffers (update + draw)
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
@ -1021,14 +1021,6 @@ Matrix GetCameraMatrix(Camera camera)
return MatrixLookAt(camera.position, camera.target, camera.up); return MatrixLookAt(camera.position, camera.target, camera.up);
} }
// Update and draw default buffers vertex data
// NOTE: This data has been stored dynamically during frame on each Draw*() call
void DrawDefaultBuffers(void)
{
rlglUpdateDefaultBuffers(); // Upload frame vertex data to GPU
rlglDrawDefaultBuffers(); // Draw vertex data into framebuffer
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions // Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View file

@ -572,7 +572,6 @@ void EndTextureMode(void); // Ends drawing to r
Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position
Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position from a 3d world space position Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position from a 3d world space position
Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix) Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix)
void DrawDefaultBuffers(void); // Update and draw default buffers vertex data (stored dynamically in frame)
void SetTargetFPS(int fps); // Set target FPS (maximum) void SetTargetFPS(int fps); // Set target FPS (maximum)
float GetFPS(void); // Returns current FPS float GetFPS(void); // Returns current FPS
@ -853,7 +852,6 @@ void DestroyLight(Light light); // Destroy a
void InitOculusDevice(void); // Init Oculus Rift device void InitOculusDevice(void); // Init Oculus Rift device
void CloseOculusDevice(void); // Close Oculus Rift device void CloseOculusDevice(void); // Close Oculus Rift device
void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation) void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation)
void SetOculusView(int eye); // Set internal projection and modelview matrix depending on eyes tracking data
void BeginOculusDrawing(void); // Begin Oculus drawing configuration void BeginOculusDrawing(void); // Begin Oculus drawing configuration
void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror) void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror)
bool IsOculusReady(void); // Detect if oculus device (or simulator) is ready bool IsOculusReady(void); // Detect if oculus device (or simulator) is ready

View file

@ -276,9 +276,10 @@ static unsigned int frameIndex = 0; // Oculus frames counter, used to discar
static bool oculusReady = false; // Oculus device ready flag static bool oculusReady = false; // Oculus device ready flag
static bool oculusSimulator = false; // Oculus device simulator static bool oculusSimulator = false; // Oculus device simulator
static bool vrEnabled = false; // VR experience enabled (Oculus device or 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 RenderTexture2D stereoFbo;
static Shader distortion; static Shader distortionShader;
// Compressed textures support flags // Compressed textures support flags
static bool texCompDXTSupported = false; // DDS texture compression support static bool texCompDXTSupported = false; // DDS texture compression support
@ -315,10 +316,13 @@ static void UnloadDefaultShader(void); // Unload default shader
static void UnloadStandardShader(void); // Unload standard shader static void UnloadStandardShader(void); // Unload standard shader
static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads) static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads)
void rlglUpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data
void rlglDrawDefaultBuffers(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 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 void SetShaderLights(Shader shader); // Sets shader uniform values for lights array
static char *ReadTextFile(const char *fileName); static char *ReadTextFile(const char *fileName);
@ -1205,15 +1209,14 @@ void rlglClose(void)
void rlglDraw(void) void rlglDraw(void)
{ {
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
/* // NOTE: In a future version, models could be stored in a stack...
for (int i = 0; i < modelsCount; i++) //for (int i = 0; i < modelsCount; i++) rlglDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform);
{
rlglDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform); // NOTE: Default buffers upload and draw
} UpdateDefaultBuffers();
*/
// NOTE: Default buffers always drawn at the end if (vrEnabled && vrControl) DrawDefaultBuffers(2);
rlglUpdateDefaultBuffers(); else DrawDefaultBuffers(1);
rlglDrawDefaultBuffers();
#endif #endif
} }
@ -1865,8 +1868,15 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
#endif #endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
int eyesCount = 1;
if (vrEnabled) eyesCount = 2;
glUseProgram(material.shader.id); 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) // 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() // 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 matView = modelview; // View matrix (camera)
@ -1875,16 +1885,6 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
// Calculate model-view matrix combining matModel and matView // Calculate model-view matrix combining matModel and matView
Matrix matModelView = MatrixMultiply(transform, matView); // Transform to camera-space coordinates 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 // 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) // 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) if (material.shader.id == standardShader.id)
@ -1989,9 +1989,20 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]);
} }
// Draw call! for (int eye = 0; eye < eyesCount; eye++)
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 (eyesCount == 2) SetOculusView(eye, matProjection, 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) if (material.texNormal.id != 0)
{ {
@ -2016,6 +2027,10 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
} }
glUseProgram(0); // Unbind shader program glUseProgram(0); // Unbind shader program
// Restore projection/modelview matrices
projection = matProjection;
modelview = matView;
#endif #endif
} }
@ -2538,7 +2553,7 @@ void InitOculusDevice(void)
// Load oculus-distortion shader (oculus parameters setup internally) // Load oculus-distortion shader (oculus parameters setup internally)
// TODO: Embed coulus distortion shader (in this function like default shader?) // TODO: Embed coulus distortion shader (in this function like default shader?)
distortion = LoadShader("resources/shaders/glsl330/base.vs", "resources/shaders/glsl330/distortion.fs"); distortionShader = LoadShader("resources/shaders/glsl330/base.vs", "resources/shaders/glsl330/distortion.fs");
oculusSimulator = true; oculusSimulator = true;
vrEnabled = true; vrEnabled = true;
@ -2564,7 +2579,7 @@ void CloseOculusDevice(void)
rlDeleteRenderTextures(stereoFbo); rlDeleteRenderTextures(stereoFbo);
// Unload oculus-distortion shader // Unload oculus-distortion shader
UnloadShader(distortion); UnloadShader(distortionShader);
} }
oculusReady = false; oculusReady = false;
@ -2615,13 +2630,13 @@ void UpdateOculusTracking(void)
} }
// Set internal projection and modelview matrix depending on eyes tracking data // Set internal projection and modelview matrix depending on eyes tracking data
void SetOculusView(int eye) static void SetOculusView(int eye, Matrix matProjection, Matrix matModelView)
{ {
Matrix eyeProjection;
Matrix eyeModelView;
if (vrEnabled) if (vrEnabled)
{ {
Matrix eyeProjection = matProjection;
Matrix eyeModelView = matModelView;
#if defined(RLGL_OCULUS_SUPPORT) #if defined(RLGL_OCULUS_SUPPORT)
if (oculusReady) if (oculusReady)
{ {
@ -2639,9 +2654,7 @@ void SetOculusView(int eye)
-layer.eyeLayer.RenderPose[eye].Position.z); -layer.eyeLayer.RenderPose[eye].Position.z);
Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); // Matrix containing eye-head movement Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); // Matrix containing eye-head movement
eyeModelView = MatrixMultiply(modelview, eyeView); // Combine internal camera matrix (modelview) wih eye-head movement eyeModelView = MatrixMultiply(matModelView, eyeView); // Combine internal camera matrix (modelview) wih eye-head movement
// TODO: Find a better way to get camera view matrix (instead of using internal modelview)
eyeProjection = layer.eyeProjections[eye]; eyeProjection = layer.eyeProjections[eye];
} }
@ -2651,28 +2664,43 @@ void SetOculusView(int eye)
// Setup viewport and projection/modelview matrices using tracking data // Setup viewport and projection/modelview matrices using tracking data
rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight); rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight);
float hmdIPD = 0.064f; static float IPD = 0.064f; // InterpupillaryDistance
float hmdHScreenSize = 0.14976f; float HScreenSize = 0.14976f;
float hmdVScreenSize = 0.0936f; float VScreenSize = 0.0936f; // HScreenSize/(1280.0f/800.0f)
//float hmdVScreenCenter = 0.04675f; float VScreenCenter = 0.04675f;
float hmdEyeToScreenDistance = 0.041f; float EyeToScreenDistance = 0.041f;
float hmdLensSeparationDistance = 0.064f; float LensSeparationDistance = 0.064f; //0.0635f (DK1)
//NOTE: fovy value hardcoded to 60 degrees (Oculus Rift CV1 vertical FOV is 100 degrees) // NOTE: fovy value obtained from device parameters (Oculus Rift CV1)
//float halfScreenDistance = hmdVScreenSize/2.0f; float halfScreenDistance = VScreenSize/2.0f;
//float yfov = 2.0f*atan(halfScreenDistance/hmdEyeToScreenDistance); float fovy = 2.0f*atan(halfScreenDistance/EyeToScreenDistance)*RAD2DEG;
float viewCenter = (float)hmdHScreenSize*0.25f; float viewCenter = (float)HScreenSize*0.25f;
float eyeProjectionShift = viewCenter - hmdLensSeparationDistance*0.5f; float eyeProjectionShift = viewCenter - LensSeparationDistance*0.5f;
float projectionCenterOffset = 4.0f*eyeProjectionShift/(float)hmdHScreenSize; float projectionCenterOffset = 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 // The matrixes for offsetting the projection and view for each eye, to achieve stereo effect
Vector3 projectionOffset = { -projectionCenterOffset, 0.0f, 0.0f }; Vector3 projectionOffset = { -projectionCenterOffset, 0.0f, 0.0f };
Vector3 viewOffset = { -hmdIPD/2.0f, 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 // Negate the left eye versions
if (eye == 1) if (eye == 0)
{ {
projectionOffset.x *= -1.0f; projectionOffset.x *= -1.0f;
viewOffset.x *= -1.0f; viewOffset.x *= -1.0f;
@ -2680,29 +2708,18 @@ void SetOculusView(int eye)
// Adjust the view and projection matrixes // Adjust the view and projection matrixes
// View matrix is translated based on the eye offset // View matrix is translated based on the eye offset
Matrix projCenter = MatrixPerspective(60.0, (double)((float)screenWidth*0.5f)/(double)screenHeight, 0.01, 1000.0); 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 projTranslation = MatrixTranslate(projectionOffset.x, projectionOffset.y, projectionOffset.z);
Matrix viewTranslation = MatrixTranslate(viewOffset.x, viewOffset.y, viewOffset.z); Matrix viewTranslation = MatrixTranslate(viewOffset.x, viewOffset.y, viewOffset.z);
eyeProjection = MatrixMultiply(projCenter, projTranslation); // projection eyeProjection = MatrixMultiply(projCenter, projTranslation); // projection
eyeModelView = MatrixMultiply(modelview, viewTranslation); // modelview eyeModelView = MatrixMultiply(matModelView, viewTranslation); // modelview
MatrixTranspose(&eyeProjection); MatrixTranspose(&eyeProjection);
/*
// NOTE: fovy value hardcoded to 60 degrees (Oculus Rift CV1 vertical FOV is 100 degrees)
eyeProjection = MatrixPerspective(60.0, (double)(screenWidth/2)/(double)screenHeight, 0.01, 1000.0);
MatrixTranspose(&eyeProjection);
// TODO: Compute eyes IPD and apply to current modelview matrix (camera)
Matrix eyeView = MatrixIdentity();
eyeModelView = MatrixMultiply(modelview, eyeView);
*/
} }
SetMatrixModelview(eyeModelView); SetMatrixModelview(eyeModelView); // ERROR! We are modifying modelview for next eye!!!
SetMatrixProjection(eyeProjection); SetMatrixProjection(eyeProjection);
} }
} }
@ -2738,6 +2755,8 @@ void BeginOculusDrawing(void)
//glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye) //glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye)
rlClearScreenBuffers(); // Clear current framebuffer(s) rlClearScreenBuffers(); // Clear current framebuffer(s)
vrControl = true;
} }
// End Oculus drawing process (and desktop mirror) // End Oculus drawing process (and desktop mirror)
@ -2777,40 +2796,44 @@ void EndOculusDrawing(void)
rlLoadIdentity(); // Reset internal modelview matrix rlLoadIdentity(); // Reset internal modelview matrix
// Draw RenderTexture (stereoFbo) using distortion shader // Draw RenderTexture (stereoFbo) using distortion shader
BeginShaderMode(distortion); currentShader = distortionShader;
rlEnableTexture(stereoFbo.texture.id); rlEnableTexture(stereoFbo.texture.id);
rlPushMatrix(); rlPushMatrix();
rlBegin(RL_QUADS); rlBegin(RL_QUADS);
rlColor4ub(255, 255, 255, 255); rlColor4ub(255, 255, 255, 255);
rlNormal3f(0.0f, 0.0f, 1.0f); rlNormal3f(0.0f, 0.0f, 1.0f);
// Bottom-left corner for texture and quad // Bottom-left corner for texture and quad
rlTexCoord2f(0.0f, 1.0f); rlTexCoord2f(0.0f, 1.0f);
rlVertex2f(0.0f, 0.0f); rlVertex2f(0.0f, 0.0f);
// Bottom-right corner for texture and quad // Bottom-right corner for texture and quad
rlTexCoord2f(0.0f, 0.0f); rlTexCoord2f(0.0f, 0.0f);
rlVertex2f(0.0f, stereoFbo.texture.height); rlVertex2f(0.0f, stereoFbo.texture.height);
// Top-right corner for texture and quad // Top-right corner for texture and quad
rlTexCoord2f(1.0f, 0.0f); rlTexCoord2f(1.0f, 0.0f);
rlVertex2f(stereoFbo.texture.width, stereoFbo.texture.height); rlVertex2f(stereoFbo.texture.width, stereoFbo.texture.height);
// Top-left corner for texture and quad // Top-left corner for texture and quad
rlTexCoord2f(1.0f, 1.0f); rlTexCoord2f(1.0f, 1.0f);
rlVertex2f(stereoFbo.texture.width, 0.0f); rlVertex2f(stereoFbo.texture.width, 0.0f);
rlEnd(); rlEnd();
rlPopMatrix(); rlPopMatrix();
rlDisableTexture(); rlDisableTexture();
//rlglDraw(); UpdateDefaultBuffers();
EndShaderMode(); DrawDefaultBuffers(1);
currentShader = defaultShader;
} }
rlDisableDepthTest(); rlDisableDepthTest();
vrControl = false;
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -3303,7 +3326,7 @@ static void LoadDefaultBuffers(void)
// Update default internal buffers (VAOs/VBOs) with vertex array data // Update default internal buffers (VAOs/VBOs) with vertex array data
// NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0) // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0)
// TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required) // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required)
void rlglUpdateDefaultBuffers(void) static void UpdateDefaultBuffers(void)
{ {
// Update lines vertex buffers // Update lines vertex buffers
if (lines.vCounter > 0) if (lines.vCounter > 0)
@ -3373,146 +3396,154 @@ void rlglUpdateDefaultBuffers(void)
// Draw default internal buffers vertex data // Draw default internal buffers vertex data
// NOTE: We draw in this order: lines, triangles, quads // NOTE: We draw in this order: lines, triangles, quads
void rlglDrawDefaultBuffers(void) static void DrawDefaultBuffers(int eyesCount)
{ {
// Set current shader and upload current MVP matrix Matrix matProjection = projection;
if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0)) Matrix matModelView = modelview;
for (int eye = 0; eye < eyesCount; eye++)
{ {
glUseProgram(currentShader.id); if (eyesCount == 2) SetOculusView(eye, matProjection, matModelView);
// Create modelview-projection matrix // Set current shader and upload current MVP matrix
Matrix matMVP = MatrixMultiply(modelview, projection); if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0))
{
glUseProgram(currentShader.id);
glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP)); // Create modelview-projection matrix
glUniform4f(currentShader.tintColorLoc, 1.0f, 1.0f, 1.0f, 1.0f); Matrix matMVP = MatrixMultiply(modelview, projection);
glUniform1i(currentShader.mapTexture0Loc, 0);
// NOTE: Additional map textures not considered for default buffers drawing 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)
{
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);
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
} }
// Draw lines buffers
if (lines.vCounter > 0)
{
glBindTexture(GL_TEXTURE_2D, whiteTexture);
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);
// 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);
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
// Reset draws counter // Reset draws counter
drawsCounter = 1; drawsCounter = 1;
draws[0].textureId = whiteTexture; draws[0].textureId = whiteTexture;
@ -3529,6 +3560,10 @@ void rlglDrawDefaultBuffers(void)
// Reset depth for next draw // Reset depth for next draw
currentDepth = -1.0f; currentDepth = -1.0f;
// Restore projection/modelview matrices
projection = matProjection;
modelview = matModelView;
} }
// Unload default internal buffers vertex data from CPU and GPU // Unload default internal buffers vertex data from CPU and GPU

View file

@ -303,9 +303,6 @@ void rlglClose(void); // De-init rlgl
void rlglDraw(void); // Draw VAO/VBO void rlglDraw(void); // Draw VAO/VBO
void rlglLoadExtensions(void *loader); // Load OpenGL extensions void rlglLoadExtensions(void *loader); // Load OpenGL extensions
void rlglUpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data
void rlglDrawDefaultBuffers(void); // Draw default internal buffers vertex data
unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount); // Load texture in GPU unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount); // Load texture in GPU
RenderTexture2D rlglLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments) RenderTexture2D rlglLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments)
void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data); // Update GPU texture with new data void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data); // Update GPU texture with new data
@ -358,7 +355,6 @@ void TraceLog(int msgType, const char *text, ...);
void InitOculusDevice(void); // Init Oculus Rift device void InitOculusDevice(void); // Init Oculus Rift device
void CloseOculusDevice(void); // Close Oculus Rift device void CloseOculusDevice(void); // Close Oculus Rift device
void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation) void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation)
void SetOculusView(int eye); // Set internal projection and modelview matrix depending on eyes tracking data
void BeginOculusDrawing(void); // Begin Oculus drawing configuration void BeginOculusDrawing(void); // Begin Oculus drawing configuration
void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror) void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror)
bool IsOculusReady(void); // Detect if oculus device (or simulator) is ready bool IsOculusReady(void); // Detect if oculus device (or simulator) is ready