diff --git a/examples/oculus_glfw_sample/oculus_glfw_sample.c b/examples/oculus_glfw_sample/oculus_glfw_sample.c index f6287631..19de0188 100644 --- a/examples/oculus_glfw_sample/oculus_glfw_sample.c +++ b/examples/oculus_glfw_sample/oculus_glfw_sample.c @@ -91,12 +91,13 @@ int main() { // Initialization //-------------------------------------------------------------------------------------- + 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"); - ovrSession session; - ovrGraphicsLuid luid; // Useless for OpenGL since SDK 0.7 - 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; } diff --git a/examples/oculus_glfw_sample/oculus_glfw_sample_new.c b/examples/oculus_glfw_sample/oculus_glfw_sample_new.c new file mode 100644 index 00000000..4a468949 --- /dev/null +++ b/examples/oculus_glfw_sample/oculus_glfw_sample_new.c @@ -0,0 +1,280 @@ + +#include +#include +#include + +#include "glad.h" // Extensions loading library +#include + +#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(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; +} diff --git a/src/core.c b/src/core.c index 7b1d5960..dd904692 100644 --- a/src/core.c +++ b/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) { diff --git a/src/raylib.h b/src/raylib.h index f4ea875e..ade581d3 100644 --- a/src/raylib.h +++ b/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) diff --git a/src/rlgl.c b/src/rlgl.c index 5b181a86..b1b020ec 100644 --- a/src/rlgl.c +++ b/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; }