浏览代码

merge fix

Joshua Reisenauer 9 年之前
父节点
当前提交
289a53221d
共有 5 个文件被更改,包括 341 次插入51 次删除
  1. 18 12
      examples/oculus_glfw_sample/oculus_glfw_sample.c
  2. 280 0
      examples/oculus_glfw_sample/oculus_glfw_sample_new.c
  3. 27 17
      src/core.c
  4. 11 13
      src/raylib.h
  5. 5 9
      src/rlgl.c

+ 18 - 12
examples/oculus_glfw_sample/oculus_glfw_sample.c

@@ -91,12 +91,13 @@ int main()
 {
     // Initialization
     //--------------------------------------------------------------------------------------
-    ovrResult result = ovr_Initialize(NULL);
-    if (OVR_FAILURE(result)) TraceLog(LOG_ERROR, "OVR: Could not initialize Oculus device");
-
     ovrSession session;
     ovrGraphicsLuid luid;   // Useless for OpenGL since SDK 0.7
+    ovrHmdDesc hmdDesc;
     
+    ovrResult result = ovr_Initialize(NULL);
+    if (OVR_FAILURE(result)) TraceLog(LOG_ERROR, "OVR: Could not initialize Oculus device");
+
     result = ovr_Create(&session, &luid);
     if (OVR_FAILURE(result))
     {
@@ -104,7 +105,7 @@ int main()
         ovr_Shutdown();
     }
 
-    ovrHmdDesc hmdDesc = ovr_GetHmdDesc(session);
+    hmdDesc = ovr_GetHmdDesc(session);
     
     TraceLog(LOG_INFO, "OVR: Product Name: %s", hmdDesc.ProductName);
     TraceLog(LOG_INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer);
@@ -129,10 +130,12 @@ int main()
     }
     else TraceLog(LOG_INFO, "GLFW3: GLFW initialized successfully");
     
+    glfwWindowHint(GLFW_DEPTH_BITS, 16);
     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
-    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
+    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
     glfwWindowHint(GLFW_DECORATED, GL_FALSE);   // Mandatory on Oculus Rift to avoid program crash!
    
     window = glfwCreateWindow(screenWidth, screenHeight, "rlgl standalone", NULL, NULL);
@@ -209,6 +212,10 @@ int main()
         TraceLog(LOG_WARNING, "OVR: Could not initialize mirror framebuffers");
     }
     
+    glClearColor(1.0f, 0.1f, 0.1f, 0.0f);
+    glEnable(GL_DEPTH_TEST);
+    ovr_RecenterTrackingOrigin(session);
+    
     // FloorLevel will give tracking poses where the floor height is 0
     ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
     //--------------------------------------------------------------------------------------
@@ -218,7 +225,8 @@ int main()
     {
         // Update
         //----------------------------------------------------------------------------------
-
+        frameIndex++;
+        
         // TODO: Update game here!
         
 	    // Call ovr_GetRenderDesc each frame to get the ovrEyeRenderDesc, as the returned values (e.g. HmdToEyeOffset) may change at runtime.
@@ -238,15 +246,15 @@ int main()
         //----------------------------------------------------------------------------------
         
         // Clear screen to red color
-        glClearColor(1.0f, 0.1f, 0.1f, 0.0f);   
-        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+        //glClearColor(1.0f, 0.1f, 0.1f, 0.0f);   
+        //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
         
         if (isVisible)
         {
             for (int eye = 0; eye < 2; ++eye)
             {
                 SetOculusBuffer(session, eyeRenderBuffer[eye]);
-                
+
                 // TODO: Get view and projection matrices for the eye
                 // Sample using Oculus OVR_Math.h (C++)
                 /*
@@ -322,8 +330,6 @@ int main()
         
         glfwSwapBuffers(window);
         glfwPollEvents();
-    
-        //frameIndex++;     //?
         //----------------------------------------------------------------------------------
     }
 
@@ -398,7 +404,7 @@ static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height)
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, buffer.width, buffer.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, buffer.width, buffer.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
 
     return buffer;
 }

+ 280 - 0
examples/oculus_glfw_sample/oculus_glfw_sample_new.c

@@ -0,0 +1,280 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "glad.h"      // Extensions loading library
+#include <GLFW/glfw3.h>
+
+#include "OculusSDK/LibOVR/Include/OVR_CAPI_GL.h"    // Oculus SDK for OpenGL
+
+#define FAIL(X) printf(X);
+
+typedef struct Vector2 {
+    float x;
+    float y;
+} Vector2;
+
+typedef struct Matrix {
+    float m0, m4, m8, m12;
+    float m1, m5, m9, m13;
+    float m2, m6, m10, m14;
+    float m3, m7, m11, m15;
+} Matrix;
+
+// RiftManagerApp class
+ovrSession session;
+ovrHmdDesc hmdDesc;
+ovrGraphicsLuid luid;
+
+// RiftApp class
+GLuint fbo = 0;
+GLuint depthBuffer = 0;
+ovrTextureSwapChain eyeTexture;
+
+GLuint mirrorFbo = 0;
+ovrMirrorTexture mirrorTexture;
+ovrEyeRenderDesc eyeRenderDescs[2];
+Matrix eyeProjections[2];
+
+ovrLayerEyeFov eyeLayer;
+ovrViewScaleDesc viewScaleDesc;
+
+Vector2 renderTargetSize;
+Vector2 mirrorSize;
+
+// GlfwApp class
+GLFWwindow *window = NULL;
+unsigned int frame = 0;
+
+static void ErrorCallback(int error, const char* description)
+{
+    fputs(description, stderr);
+}
+
+static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
+{
+    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
+    {
+        glfwSetWindowShouldClose(window, GL_TRUE);
+    }
+}
+
+// Execute our example class
+int main() 
+{
+    if (!OVR_SUCCESS(ovr_Initialize(NULL))) FAIL("Failed to initialize the Oculus SDK\n");
+    
+    //result = ExampleApp().run();      // class ExampleApp : public RiftApp : public GlfwApp, public RiftManagerApp
+    
+    if (!OVR_SUCCESS(ovr_Create(&session, &luid))) FAIL("Unable to create HMD session\n");
+    hmdDesc = ovr_GetHmdDesc(session);
+    
+    // RiftApp() constructor
+    viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
+    memset(&eyeLayer, 0, sizeof(ovrLayerEyeFov));
+    eyeLayer.Header.Type = ovrLayerType_EyeFov;
+    eyeLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
+
+    //ovr::for_each_eye([&](ovrEyeType eye) 
+    for (int eye = 0; eye < 2; eye++)
+    {
+        eyeRenderDescs[eye] = ovr_GetRenderDesc(session, eye, hmdDesc.DefaultEyeFov[eye]);
+        ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(eyeRenderDescs[eye].Fov, 0.01f, 1000.0f, ovrProjection_ClipRangeOpenGL);
+        //eyeProjections[eye] = ovr::toGlm(ovrPerspectiveProjection);
+        viewScaleDesc.HmdToEyeOffset[eye] = eyeRenderDescs[eye].HmdToEyeOffset;
+
+        eyeLayer.Fov[eye] = eyeRenderDescs[eye].Fov;
+        ovrSizei eyeSize = ovr_GetFovTextureSize(session, eye, eyeLayer.Fov[eye], 1.0f);
+        eyeLayer.Viewport[eye].Size = eyeSize;
+        eyeLayer.Viewport[eye].Pos.x = renderTargetSize.x;
+        eyeLayer.Viewport[eye].Pos.y = 0;
+
+        renderTargetSize.y = renderTargetSize.y; // std::max(renderTargetSize.y, (uint32_t)eyeSize.h);
+        renderTargetSize.x += eyeSize.w;
+    }
+    
+    // Make the on screen window 1/4 the resolution of the render target
+    mirrorSize = renderTargetSize;
+    mirrorSize.x /= 2;
+    mirrorSize.y /= 2;
+
+    // GLFWApp() constructor
+    if (!glfwInit()) FAIL("Failed to initialize GLFW\n"); // Initialize the GLFW system for creating and positioning windows
+    glfwSetErrorCallback(ErrorCallback);
+    
+    ////preCreate();
+    glfwWindowHint(GLFW_DEPTH_BITS, 16);
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
+    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
+
+    //***************window = createRenderingTarget(windowSize, windowPosition);    //GLFWwindow *createRenderingTarget(uvec2 & size, ivec2 & pos) = 0; //glfw::createWindow(_mirrorSize);
+    /*
+    GLFWwindow *createWindow(const uvec2 &size, const ivec2 &position = ivec2(INT_MIN))
+    {
+        GLFWwindow *window = glfwCreateWindow(size.x, size.y, "glfw", NULL, NULL);  // size = mirrorSize
+        
+        if (!window) FAIL("Unable to create rendering window\n");
+
+        if ((position.x > INT_MIN) && (position.y > INT_MIN)) // INT_MIN = -32767   // #define INT_MIN (-2147483647 - 1)
+        {
+            glfwSetWindowPos(window, position.x, position.y);
+        }
+        
+        return window;
+    }
+    */
+    
+    window = glfwCreateWindow(mirrorSize.x, mirrorSize.y, "glfw", NULL, NULL);
+
+    if (!window) FAIL("Unable to create OpenGL window\n");
+
+    ////postCreate();
+    //glfwSetWindowUserPointer(window, this);  //// Useful to hack input callbacks
+    glfwSetKeyCallback(window, KeyCallback);
+    glfwMakeContextCurrent(window);
+
+    // Initialize the OpenGL extensions
+    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) FAIL("GLAD failed\n");
+    /*
+    glewExperimental = GL_TRUE;
+    if (0 != glewInit()) FAIL("Failed to initialize GLEW\n");
+    glGetError();
+
+    if (GLEW_KHR_debug) 
+    {
+        GLint v;
+        glGetIntegerv(GL_CONTEXT_FLAGS, &v);
+        if (v & GL_CONTEXT_FLAG_DEBUG_BIT) glDebugMessageCallback(glDebugCallbackHandler, this);
+    }
+    */
+
+    ////initGl();
+    {
+        // RiftApp::InitGL() ----->
+            //GlfwApp::initGl();    // virtual
+
+        // Disable the v-sync for buffer swap
+        glfwSwapInterval(0);
+
+        ovrTextureSwapChainDesc desc = {};
+        desc.Type = ovrTexture_2D;
+        desc.ArraySize = 1;
+        desc.Width = renderTargetSize.x;
+        desc.Height = renderTargetSize.y;
+        desc.MipLevels = 1;
+        desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
+        desc.SampleCount = 1;
+        desc.StaticImage = ovrFalse;
+        
+        ovrResult result = ovr_CreateTextureSwapChainGL(session, &desc, &eyeTexture);
+        eyeLayer.ColorTexture[0] = eyeTexture;
+        
+        if (!OVR_SUCCESS(result)) FAIL("Failed to create swap textures");
+        
+        int length = 0;
+        result = ovr_GetTextureSwapChainLength(session, eyeTexture, &length);
+        
+        if (!OVR_SUCCESS(result) || !length) FAIL("Unable to count swap chain textures");
+
+        for (int i = 0; i < length; ++i) 
+        {
+            GLuint chainTexId;
+            ovr_GetTextureSwapChainBufferGL(session, eyeTexture, i, &chainTexId);
+            glBindTexture(GL_TEXTURE_2D, chainTexId);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        }
+        
+        glBindTexture(GL_TEXTURE_2D, 0);
+
+        // Set up the framebuffer object
+        glGenFramebuffers(1, &fbo);
+        glGenRenderbuffers(1, &depthBuffer);
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
+        glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
+        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, renderTargetSize.x, renderTargetSize.y);
+        glBindRenderbuffer(GL_RENDERBUFFER, 0);
+        glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+
+        ovrMirrorTextureDesc mirrorDesc;
+        memset(&mirrorDesc, 0, sizeof(mirrorDesc));
+        mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
+        mirrorDesc.Width = mirrorSize.x;
+        mirrorDesc.Height = mirrorSize.y;
+        
+        if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirrorTexture))) FAIL("Could not create mirror texture");
+
+        glGenFramebuffers(1, &mirrorFbo);
+
+        // RiftApp::InitGL() <------
+        
+        glClearColor(0.2f, 0.2f, 0.2f, 0.0f);
+        glEnable(GL_DEPTH_TEST);
+        ovr_RecenterTrackingOrigin(session);
+        
+        // TODO: Init cube scene --> cubeScene = std::shared_ptr<ColorCubeScene>(new ColorCubeScene());
+    }
+
+    while (!glfwWindowShouldClose(window)) 
+    {
+        frame++;
+        glfwPollEvents();
+        
+        //update();
+        
+        //draw(); ------>
+        ovrPosef eyePoses[2];
+        ovr_GetEyePoses(session, frame, ovrTrue, viewScaleDesc.HmdToEyeOffset, eyePoses, &eyeLayer.SensorSampleTime);
+
+        int curIndex;
+        ovr_GetTextureSwapChainCurrentIndex(session, eyeTexture, &curIndex);
+        GLuint curTexId;
+        ovr_GetTextureSwapChainBufferGL(session, eyeTexture, curIndex, &curTexId);
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
+        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, curTexId, 0);
+        
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+        
+        for (int eye = 0; eye < 2; eye++)
+        {
+            glViewport(eyeLayer.Viewport[eye].Pos.x, eyeLayer.Viewport[eye].Pos.y, 
+                       eyeLayer.Viewport[eye].Size.w, eyeLayer.Viewport[eye].Size.h);
+            eyeLayer.RenderPose[eye] = eyePoses[eye];
+            
+            //renderScene(_eyeProjections[eye], ovr::toGlm(eyePoses[eye])); -->  cubeScene->render(projection, glm::inverse(headPose));
+        }
+        
+        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+        ovr_CommitTextureSwapChain(session, eyeTexture);
+        ovrLayerHeader *headerList = &eyeLayer.Header;
+        
+        ovr_SubmitFrame(session, frame, &viewScaleDesc, &headerList, 1);
+
+        GLuint mirrorTextureId;
+        ovr_GetMirrorTextureBufferGL(session, mirrorTexture, &mirrorTextureId);
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFbo);
+        glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mirrorTextureId, 0);
+        glBlitFramebuffer(0, 0, mirrorSize.x, mirrorSize.y, 0, mirrorSize.y, mirrorSize.x, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+        //draw() <-------------
+        
+        glfwSwapBuffers(window); //finishFrame();
+    }
+
+    //shutdownGl();        // Delete scene:  cubeScene.reset();
+    
+    glfwDestroyWindow(window);
+    glfwTerminate();
+
+    ovr_Destroy(session);
+    ovr_Shutdown();
+    
+    return 0;
+}

+ 27 - 17
src/core.c

@@ -524,23 +524,6 @@ void BeginDrawing(void)
                                         // NOTE: Not required with OpenGL 3.3+
 }
 
-// Setup drawing canvas with 2d camera
-void BeginDrawingEx(Camera2D camera)
-{
-    BeginDrawing();
-    
-    // Camera rotation and scaling is always relative to target
-    Matrix matOrigin = MatrixTranslate(-camera.target.x, -camera.target.y, 0.0f);
-    Matrix matRotation = MatrixRotate((Vector3){ 0.0f, 0.0f, 1.0f }, camera.rotation*DEG2RAD);
-    Matrix matScale = MatrixScale(camera.zoom, camera.zoom, 1.0f);
-    
-    Matrix matTranslation = MatrixTranslate(camera.offset.x + camera.target.x, camera.offset.y + camera.target.y, 0.0f);
-
-    Matrix matTransform = MatrixMultiply(MatrixMultiply(matOrigin, MatrixMultiply(matScale, matRotation)), matTranslation);
-    
-    rlMultMatrixf(MatrixToFloat(matTransform));
-}
-
 // End canvas drawing and Swap Buffers (Double Buffering)
 void EndDrawing(void)
 {
@@ -569,6 +552,33 @@ void EndDrawing(void)
     }
 }
 
+// Initialize 2D mode with custom camera
+void Begin2dMode(Camera2D camera)
+{
+    rlglDraw();                         // Draw Buffers (Only OpenGL 3+ and ES2)
+
+    rlLoadIdentity();                   // Reset current matrix (MODELVIEW)
+
+    // Camera rotation and scaling is always relative to target
+    Matrix matOrigin = MatrixTranslate(-camera.target.x, -camera.target.y, 0.0f);
+    Matrix matRotation = MatrixRotate((Vector3){ 0.0f, 0.0f, 1.0f }, camera.rotation*DEG2RAD);
+    Matrix matScale = MatrixScale(camera.zoom, camera.zoom, 1.0f);
+    
+    Matrix matTranslation = MatrixTranslate(camera.offset.x + camera.target.x, camera.offset.y + camera.target.y, 0.0f);
+
+    Matrix matTransform = MatrixMultiply(MatrixMultiply(matOrigin, MatrixMultiply(matScale, matRotation)), matTranslation);
+    
+    rlMultMatrixf(MatrixToFloat(matTransform));
+}
+
+// Ends 2D mode custom camera usage
+void End2dMode(void)
+{
+    rlglDraw();                         // Draw Buffers (Only OpenGL 3+ and ES2)
+
+    rlLoadIdentity();                   // Reset current matrix (MODELVIEW)
+}
+
 // Initializes 3D mode for drawing (Camera setup)
 void Begin3dMode(Camera camera)
 {

+ 11 - 13
src/raylib.h

@@ -355,7 +355,7 @@ typedef struct Camera {
 // Camera2D type, defines a 2d camera
 typedef struct Camera2D {
     Vector2 offset;         // Camera offset (displacement from target)
-    Vector2 target;         // Camera target (for rotation and zoom)
+    Vector2 target;         // Camera target (rotation and zoom origin)
     float rotation;         // Camera rotation in degrees
     float zoom;             // Camera zoom (scaling), should be 1.0f by default
 } Camera2D;
@@ -386,16 +386,17 @@ typedef struct Mesh {
 typedef struct Shader {
     unsigned int id;      // Shader program id
     
-    // Variable attributes
+    // Variable attributes locations
     int vertexLoc;        // Vertex attribute location point (vertex shader)
     int texcoordLoc;      // Texcoord attribute location point (vertex shader)
     int normalLoc;        // Normal attribute location point (vertex shader)
     int colorLoc;         // Color attibute location point (vertex shader)
 
-    // Uniforms
+    // Uniform locations
     int mvpLoc;           // ModelView-Projection matrix uniform location point (vertex shader)
     int tintColorLoc;     // Color uniform location point (fragment shader)
     
+    // Texture map locations
     int mapDiffuseLoc;    // Diffuse map texture uniform location point (fragment shader)
     int mapNormalLoc;     // Normal map texture uniform location point (fragment shader)
     int mapSpecularLoc;   // Specular map texture uniform location point (fragment shader)
@@ -575,9 +576,10 @@ void DisableCursor(void);                                   // Disables cursor
 
 void ClearBackground(Color color);                          // Sets Background Color
 void BeginDrawing(void);                                    // Setup drawing canvas to start drawing
-void BeginDrawingEx(Camera2D camera);                       // Setup drawing canvas with 2d camera
 void EndDrawing(void);                                      // End canvas drawing and Swap Buffers (Double Buffering)
 
+void Begin2dMode(Camera2D camera);                          // Initialize 2D mode with custom camera
+void End2dMode(void);                                       // Ends 2D mode custom camera usage
 void Begin3dMode(Camera camera);                            // Initializes 3D mode for drawing (Camera setup)
 void End3dMode(void);                                       // Ends 3D mode and returns to default 2D orthographic mode
 void BeginTextureMode(RenderTexture2D target);              // Initializes render texture for drawing
@@ -832,18 +834,14 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
 Shader LoadShader(char *vsFileName, char *fsFileName);              // Load a custom shader and bind default locations
 unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load custom shaders strings and return program id
 void UnloadShader(Shader shader);                                   // Unload a custom shader from memory
-void SetCustomShader(Shader shader);                                // Set custom shader to be used in batch draw
 void SetDefaultShader(void);                                        // Set default shader to be used in batch draw
+void SetCustomShader(Shader shader);                                // Set custom shader to be used in batch draw
 void SetModelShader(Model *model, Shader shader);                   // Link a shader to a model
 
-int GetShaderLocation(Shader shader, const char *uniformName);                          // Get shader uniform location
-void SetShaderValue(Shader shader, int uniformLoc, float *value, int size);             // Set shader uniform value (float)
-void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size);              // Set shader uniform value (int)
-void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat);                   // Set shader uniform value (matrix 4x4)
-//void SetShaderMapDiffuse(Shader *shader, Texture2D texture);                            // Default diffuse shader map texture assignment
-//void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture);    // Normal map texture shader assignment
-//void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture);  // Specular map texture shader assignment
-//void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit); // TODO: Generic shader map assignment
+int GetShaderLocation(Shader shader, const char *uniformName);              // Get shader uniform location
+void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float)
+void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size);  // Set shader uniform value (int)
+void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat);       // Set shader uniform value (matrix 4x4)
 
 void SetBlendMode(int mode);                                        // Set blending mode (alpha, additive, multiplied)
 

+ 5 - 9
src/rlgl.c

@@ -1350,14 +1350,14 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro
     glBindTexture(GL_TEXTURE_2D, model.material.texDiffuse.id);
     glUniform1i(model.material.shader.mapDiffuseLoc, 0);        // Texture fits in active texture unit 0
     
-    if (model.material.texNormal.id != 0)
+    if ((model.material.texNormal.id != 0) && (model.material.shader.mapNormalLoc != -1))
     {
         glActiveTexture(GL_TEXTURE1);
         glBindTexture(GL_TEXTURE_2D, model.material.texNormal.id);
         glUniform1i(model.material.shader.mapNormalLoc, 1);     // Texture fits in active texture unit 1
     }
     
-    if (model.material.texSpecular.id != 0)
+    if ((model.material.texSpecular.id != 0) && (model.material.shader.mapSpecularLoc != -1))
     {
         glActiveTexture(GL_TEXTURE2);
         glBindTexture(GL_TEXTURE_2D, model.material.texSpecular.id);
@@ -2125,17 +2125,13 @@ Shader LoadShader(char *vsFileName, char *fsFileName)
 
         // After shader loading, we try to load default location names
         if (shader.id != 0) LoadDefaultShaderLocations(&shader);
-        else
-        {
-            TraceLog(WARNING, "Custom shader could not be loaded");
-            shader = defaultShader;
-        }
         
         // Shader strings must be freed
         free(vShaderStr);
         free(fShaderStr);
     }
-    else
+    
+    if (shader.id == 0)
     {
         TraceLog(WARNING, "Custom shader could not be loaded");
         shader = defaultShader;
@@ -2494,7 +2490,7 @@ static Shader LoadDefaultShader(void)
     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);
 
-    LoadDefaultShaderLocations(&shader);
+    if (shader.id != 0) LoadDefaultShaderLocations(&shader);
 
     return shader;
 }