aboutsummaryrefslogtreecommitdiff
path: root/src/rlgl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rlgl.c')
-rw-r--r--src/rlgl.c543
1 files changed, 290 insertions, 253 deletions
diff --git a/src/rlgl.c b/src/rlgl.c
index 12a25736..163fa35a 100644
--- a/src/rlgl.c
+++ b/src/rlgl.c
@@ -7,7 +7,7 @@
* OpenGL 3.3+ - Vertex data is stored in VAOs, call rlglDraw() to render
* OpenGL ES 2 - Same behaviour as OpenGL 3.3+
*
-* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@@ -33,20 +33,21 @@
#include <string.h> // Declares strcmp(), strlen(), strtok()
#if defined(GRAPHICS_API_OPENGL_11)
- #ifdef __APPLE__ // OpenGL include for OSX
+ #ifdef __APPLE__ // OpenGL include for OSX
#include <OpenGL/gl.h>
#else
- #include <GL/gl.h> // Basic OpenGL include
+ #include <GL/gl.h> // Basic OpenGL include
#endif
#endif
#if defined(GRAPHICS_API_OPENGL_33)
#define GLEW_STATIC
- #ifdef __APPLE__ // OpenGL include for OSX
+ #ifdef __APPLE__ // OpenGL include for OSX
#include <OpenGL/gl3.h>
#else
- #include <GL/glew.h> // Extensions loading lib
- //#include "glad.h" // TODO: Other extensions loading lib? --> REVIEW
+ #include <GL/glew.h> // GLEW extensions loading lib
+ //#include "glad.h" // glad extensions loading lib: ERRORS: windows.h
+ //#include "gl_core_3_3.h" // glLoadGen extension loading lib: ERRORS: windows.h
#endif
#endif
@@ -56,6 +57,10 @@
#include <GLES2/gl2ext.h>
#endif
+#if defined(RLGL_STANDALONE)
+ #include <stdarg.h> // Used for functions with variable number of parameters (TraceLog())
+#endif
+
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
@@ -177,6 +182,10 @@ typedef struct {
unsigned char a;
} pixel;
+#if defined(RLGL_STANDALONE)
+typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
+#endif
+
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
@@ -218,7 +227,6 @@ static bool useTempBuffer = false;
// Flags for supported extensions
static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support VAO extension)
-static bool npotSupported = false; // NPOT textures full support
// Compressed textures support flags
//static bool texCompDXTSupported = false; // DDS texture compression support
@@ -236,7 +244,8 @@ static bool enabledPostpro = false;
#endif
// Compressed textures support flags
-static bool texCompDXTSupported = false; // DDS texture compression support
+static bool texCompDXTSupported = false; // DDS texture compression support
+static bool npotSupported = false; // NPOT textures full support
#if defined(GRAPHICS_API_OPENGL_ES2)
// NOTE: VAO functionality is exposed through extensions (OES)
@@ -246,6 +255,11 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays;
//static PFNGLISVERTEXARRAYOESPROC glIsVertexArray; // NOTE: Fails in WebGL, omitted
#endif
+// Save screen size data (render size), required for postpro quad
+static int screenWidth, screenHeight;
+
+static int blendMode = 0;
+
// White texture useful for plain color polys (required by shader)
// NOTE: It's required in shapes and models modules!
unsigned int whiteTexture;
@@ -273,6 +287,10 @@ static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight);
static char** StringSplit(char *baseString, const char delimiter, int *numExt);
#endif
+#if defined(RLGL_STANDALONE)
+static void TraceLog(int msgType, const char *text, ...);
+#endif
+
//----------------------------------------------------------------------------------
// Module Functions Definition - Matrix operations
//----------------------------------------------------------------------------------
@@ -838,35 +856,69 @@ void rlglInit(void)
//for (int i = 0; i < numComp; i++) TraceLog(INFO, "Supported compressed format: 0x%x", format[i]);
// NOTE: We don't need that much data on screen... right now...
+
+#if defined(GRAPHICS_API_OPENGL_11)
+ TraceLog(INFO, "OpenGL 1.1 profile initialized");
+#endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Get supported extensions list
GLint numExt;
#if defined(GRAPHICS_API_OPENGL_33)
+
+#define GLEW_EXTENSIONS_LOADER
+#if defined(GLEW_EXTENSIONS_LOADER)
// Initialize extensions using GLEW
glewExperimental = 1; // Needed for core profile
-
GLenum error = glewInit();
if (error != GLEW_OK) TraceLog(ERROR, "Failed to initialize GLEW - Error Code: %s\n", glewGetErrorString(error));
-
+
if (glewIsSupported("GL_VERSION_3_3"))
{
- TraceLog(INFO, "OpenGL 3.3 Core profile");
+ TraceLog(INFO, "OpenGL 3.3 Core profile supported");
vaoSupported = true;
npotSupported = true;
}
+ else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported");
+
+ // With GLEW, we can check if an extension has been loaded in two ways:
+ //if (GLEW_ARB_vertex_array_object) { }
+ //if (glewIsSupported("GL_ARB_vertex_array_object")) { }
// NOTE: GLEW is a big library that loads ALL extensions, we can use some alternative to load only required ones
// Alternatives: glLoadGen, glad, libepoxy
- //if (!gladLoadGL()) TraceLog("ERROR: Failed to initialize glad\n");
+
+#elif defined(GLAD_EXTENSIONS_LOADER)
+ // NOTE: glad is generated and contains only required OpenGL version and core extensions
+ if (!gladLoadGL()) TraceLog(ERROR, "Failed to initialize glad\n");
+ //if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) TraceLog(ERROR, "Failed to initialize glad\n");
- // With GLEW we can check if an extension has been loaded in two ways:
- //if (GLEW_ARB_vertex_array_object) { }
- //if (glewIsSupported("GL_ARB_vertex_array_object")) { }
+ if (GLAD_GL_VERSION_3_3)
+ {
+ TraceLog(INFO, "OpenGL 3.3 Core profile supported");
+
+ vaoSupported = true;
+ npotSupported = true;
+ }
+ else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported");
+
+ // 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
+#elif defined(GLLOADGEN_EXTENSIONS_LOADER)
+ // NOTE: glLoadGen already generates a header with required OpenGL version and core extensions
+ if (ogl_LoadFunctions() != ogl_LOAD_FAILED)
+ {
+ TraceLog(INFO, "OpenGL 3.3 Core profile supported");
+
+ vaoSupported = true;
+ npotSupported = true;
+ }
+ else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported");
+#endif
// NOTE: We don't need to check again supported extensions but we do (in case GLEW is replaced sometime)
// We get a list of available extensions and we check for some of them (compressed textures)
@@ -995,6 +1047,7 @@ void rlglInit(void)
}
// Init postpro system
+// NOTE: Uses global variables screenWidth and screenHeight
void rlglInitPostpro(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@@ -1003,57 +1056,82 @@ void rlglInitPostpro(void)
glBindTexture(GL_TEXTURE_2D, fboColorTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GetScreenWidth(), GetScreenHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
- // Create the texture that will serve as the depth attachment for the framebuffer.
+ // Create the renderbuffer that will serve as the depth attachment for the framebuffer.
+ glGenRenderbuffers(1, &fboDepthTexture);
+ glBindRenderbuffer(GL_RENDERBUFFER, fboDepthTexture);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, screenWidth, screenHeight);
+
+ // NOTE: We can also use a texture for depth buffer (GL_ARB_depth_texture/GL_OES_depth_texture extensions)
+ // A renderbuffer is simpler than a texture and could offer better performance on embedded devices
+/*
glGenTextures(1, &fboDepthTexture);
glBindTexture(GL_TEXTURE_2D, fboDepthTexture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GetScreenWidth(), GetScreenHeight(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
+*/
// Create the framebuffer object
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- // Attach color texture and depth texture to FBO
+ // Attach color texture and depth renderbuffer to FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboColorTexture, 0);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fboDepthTexture, 0);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboDepthTexture);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) TraceLog(WARNING, "Framebuffer object could not be created...");
- else TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", fbo);
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ TraceLog(WARNING, "Framebuffer object could not be created...");
+
+ switch(status)
+ {
+ case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(WARNING, "Framebuffer is unsupported"); break;
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete attachment"); break;
+#if defined(GRAPHICS_API_OPENGL_ES2)
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TraceLog(WARNING, "Framebuffer incomplete dimensions"); break;
+#endif
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete missing attachment"); break;
+ default: break;
+ }
+ }
+ else
+ {
+ TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
- // Create a simple quad model to render fbo texture
- VertexData quadData;
-
- quadData.vertexCount = 6;
-
- float w = GetScreenWidth();
- float h = GetScreenHeight();
-
- float quadPositions[6*3] = { w, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, h, 0.0, 0, h, 0.0, w, h, 0.0, w, 0.0, 0.0 };
- float quadTexcoords[6*2] = { 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 };
- float quadNormals[6*3] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0 };
- unsigned char quadColors[6*4] = { 255 };
-
- quadData.vertices = quadPositions;
- quadData.texcoords = quadTexcoords;
- quadData.normals = quadNormals;
- quadData.colors = quadColors;
-
- postproQuad = rlglLoadModel(quadData);
-
- // NOTE: fboColorTexture id must be assigned to postproQuad model shader
+ // Create a simple quad model to render fbo texture
+ VertexData quadData;
+
+ quadData.vertexCount = 6;
+
+ float w = screenWidth;
+ float h = screenHeight;
+
+ float quadPositions[6*3] = { w, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, h, 0.0, 0, h, 0.0, w, h, 0.0, w, 0.0, 0.0 };
+ float quadTexcoords[6*2] = { 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 };
+ float quadNormals[6*3] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0 };
+ unsigned char quadColors[6*4] = { 255 };
+
+ quadData.vertices = quadPositions;
+ quadData.texcoords = quadTexcoords;
+ quadData.normals = quadNormals;
+ quadData.colors = quadColors;
+
+ postproQuad = rlglLoadModel(quadData);
+
+ // NOTE: fboColorTexture id must be assigned to postproQuad model shader
+ }
#endif
}
@@ -1116,7 +1194,20 @@ void rlglClose(void)
{
glDeleteFramebuffers(1, &fbo);
- UnloadModel(postproQuad);
+ // Unload postpro quad model data
+#if defined(GRAPHICS_API_OPENGL_11)
+ free(postproQuad.mesh.vertices);
+ free(postproQuad.mesh.texcoords);
+ free(postproQuad.mesh.normals);
+#endif
+
+ rlDeleteBuffers(postproQuad.mesh.vboId[0]);
+ rlDeleteBuffers(postproQuad.mesh.vboId[1]);
+ rlDeleteBuffers(postproQuad.mesh.vboId[2]);
+
+ rlDeleteVertexArrays(postproQuad.mesh.vaoId);
+
+ TraceLog(INFO, "Unloaded postpro quad data");
}
free(draws);
@@ -1287,7 +1378,7 @@ void rlglDrawPostpro(void)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
- rlglDrawModel(postproQuad, (Vector3){0,0,0}, 0.0f, (Vector3){0,0,0}, (Vector3){1.0f, 1.0f, 1.0f}, WHITE, false);
+ rlglDrawModel(postproQuad, (Vector3){0,0,0}, 0.0f, (Vector3){0,0,0}, (Vector3){1.0f, 1.0f, 1.0f}, (Color){ 255, 255, 255, 255 }, false);
#endif
}
@@ -1352,15 +1443,16 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r
// NOTE: Drawing in OpenGL 3.3+, transform is passed to shader
glUniformMatrix4fv(model.shader.projectionLoc, 1, false, GetMatrixVector(projection));
glUniformMatrix4fv(model.shader.modelviewLoc, 1, false, GetMatrixVector(modelviewworld));
-
+
// Apply color tinting to model
// NOTE: Just update one uniform on fragment shader
float vColor[4] = { (float)color.r/255, (float)color.g/255, (float)color.b/255, (float)color.a/255 };
glUniform4fv(model.shader.tintColorLoc, 1, vColor);
-
+
// Set shader textures (diffuse, normal, specular)
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, model.shader.texDiffuseId);
+ glUniform1i(model.shader.mapDiffuseLoc, 0);
if (model.shader.texNormalId != 0)
{
@@ -1390,14 +1482,21 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r
glEnableVertexAttribArray(model.shader.texcoordLoc);
// Add normals support
- glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[2]);
- glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
- glEnableVertexAttribArray(model.shader.normalLoc);
+ if (model.shader.normalLoc != -1)
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[2]);
+ glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(model.shader.normalLoc);
+ }
}
// Draw call!
glDrawArrays(GL_TRIANGLES, 0, model.mesh.vertexCount);
+ //glDisableVertexAttribArray(model.shader.vertexLoc);
+ //glDisableVertexAttribArray(model.shader.texcoordLoc);
+ //if (model.shader.normalLoc != -1) glDisableVertexAttribArray(model.shader.normalLoc);
+
if (model.shader.texNormalId != 0)
{
glActiveTexture(GL_TEXTURE1);
@@ -1426,17 +1525,23 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r
}
// Initialize Graphics Device (OpenGL stuff)
+// NOTE: Stores global variables screenWidth and screenHeight
void rlglInitGraphics(int offsetX, int offsetY, int width, int height)
{
+ // Save screen size data (global vars), required on postpro quad
+ // NOTE: Size represents render size, it could differ from screen size!
+ screenWidth = width;
+ screenHeight = 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.
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, depth buffer is used for 3D
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background 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
glEnable(GL_DEPTH_TEST); // Enables depth testing (required for 3D)
glDepthFunc(GL_LEQUAL); // Type of depth testing to apply
@@ -1468,170 +1573,61 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height)
// Possible options: GL_SMOOTH (Color interpolation) or GL_FLAT (no interpolation)
#endif
- TraceLog(INFO, "OpenGL Graphics initialized successfully");
+ TraceLog(INFO, "OpenGL graphic device initialized successfully");
}
// Get world coordinates from screen coordinates
// TODO: It doesn't work! It drives me crazy!
+// NOTE: Using global variables: screenWidth, screenHeight
Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view)
{
+ Vector3 result = { 0, 0, 0 }; // Object coordinates
+
//GLint viewport[4];
- //glGetIntegerv(GL_VIEWPORT, viewport);
+ //glGetIntegerv(GL_VIEWPORT, viewport); // Not available on OpenGL ES 2.0
// Viewport data
-/*
- int x = 0;
- int y = 0;
- int width = GetScreenWidth();
- int height = GetScreenHeight();
- float minDepth = 0.0f;
- float maxDepth = 1.0f;
-*/
-/*
- Matrix modelviewprojection = MatrixMultiply(modelview, projection);
+ int x = 0; // viewport[0]
+ int y = 0; // viewport[1]
+ int width = screenWidth; // viewport[2]
+ int height = screenHeight; // viewport[3]
+
+ Matrix modelviewprojection = MatrixMultiply(view, proj);
MatrixInvert(&modelviewprojection);
-
- Vector3 vector;
-
- vector.x = (((source.x - x) / ((float)width)) * 2.0f) - 1.0f;
- vector.y = -((((source.y - y) / ((float)height)) * 2.0f) - 1.0f);
- vector.z = (source.z - minDepth) / (maxDepth - minDepth);
-
- //float a = (((vector.x * matrix.M14) + (vector.y * matrix.M24)) + (vector.z * matrix.M34)) + matrix.M44;
- //float a = (((vector.x * modelviewprojection.m3) + (vector.y * modelviewprojection.m7)) + (vector.z * modelviewprojection.m11)) + modelviewprojection.m15;
- VectorTransform(&vector, modelviewprojection);
-
- //if (!MathUtil.IsOne(a)) vector = (vector / a);
- //VectorScale(&vector, 1/a);
-
- return vector;
-*/
/*
- Vector3 worldPoint;
-
- // Transformation matrices
- Matrix modelviewprojection = MatrixIdentity();
- Quaternion quat;
-
- // Calculation for inverting a matrix, compute projection x modelview
- modelviewprojection = MatrixMultiply(proj, view);
- MatrixInvert(&modelviewprojection);
+ // NOTE: Compute unproject using Vector3
// Transformation of normalized coordinates between -1 and 1
- quat.x = ((source.x - (float)x)/(float)width*2.0) - 1.0f;
- quat.y = ((source.y - (float)y)/(float)height*2.0) - 1.0f;
- quat.z = 2.0*source.z - 1.0;
- quat.w = 1.0;
-
- // Objects coordinates
- QuaternionTransform(&quat, modelviewprojection);
-
- //if (quat.w == 0.0) return 0;
-
- worldPoint.x = quat.x/quat.w;
- worldPoint.y = quat.y/quat.w;
- worldPoint.z = quat.z/quat.w;
+ result.x = ((source.x - (float)x)/(float)width)*2.0f - 1.0f;
+ result.y = ((source.y - (float)y)/(float)height)*2.0f - 1.0f;
+ result.z = source.z*2.0f - 1.0f;
- return worldPoint;
- */
-/*
- Quaternion quat;
- Vector3 vec;
-
- quat.x = 2.0f * GetMousePosition().x / (float)width - 1;
- quat.y = -(2.0f * GetMousePosition().y / (float)height - 1);
- quat.z = 0;
- quat.w = 1;
-
- Matrix invView;
- MatrixInvert(&view);
- Matrix invProj;
- MatrixInvert(&proj);
-
- quat.x = invProj.m0 * quat.x + invProj.m4 * quat.y + invProj.m8 * quat.z + invProj.m12 * quat.w;
- quat.y = invProj.m1 * quat.x + invProj.m5 * quat.y + invProj.m9 * quat.z + invProj.m13 * quat.w;
- quat.z = invProj.m2 * quat.x + invProj.m6 * quat.y + invProj.m10 * quat.z + invProj.m14 * quat.w;
- quat.w = invProj.m3 * quat.x + invProj.m7 * quat.y + invProj.m11 * quat.z + invProj.m15 * quat.w;
-
- quat.x = invView.m0 * quat.x + invView.m4 * quat.y + invView.m8 * quat.z + invView.m12 * quat.w;
- quat.y = invView.m1 * quat.x + invView.m5 * quat.y + invView.m9 * quat.z + invView.m13 * quat.w;
- quat.z = invView.m2 * quat.x + invView.m6 * quat.y + invView.m10 * quat.z + invView.m14 * quat.w;
- quat.w = invView.m3 * quat.x + invView.m7 * quat.y + invView.m11 * quat.z + invView.m15 * quat.w;
-
- vec.x /= quat.w;
- vec.y /= quat.w;
- vec.z /= quat.w;
-
- return vec;
- */
-/*
- Vector3 worldPoint;
-
- // Transformation matrices
- Matrix modelviewprojection;
+ // Object coordinates (multiply vector by matrix)
+ VectorTransform(&result, modelviewprojection);
+*/
+
+ // NOTE: Compute unproject using Quaternion (Vector4)
Quaternion quat;
-
- // Calculation for inverting a matrix, compute projection x modelview
- modelviewprojection = MatrixMultiply(view, proj);
-
- // Now compute the inverse of matrix A
- MatrixInvert(&modelviewprojection);
-
- // Transformation of normalized coordinates between -1 and 1
- quat.x = ((source.x - (float)x)/(float)width*2.0) - 1.0f;
- quat.y = ((source.y - (float)y)/(float)height*2.0) - 1.0f;
- quat.z = 2.0*source.z - 1.0;
+
+ quat.x = ((source.x - (float)x)/(float)width)*2.0f - 1.0f;
+ quat.y = ((source.y - (float)y)/(float)height)*2.0f - 1.0f;
+ quat.z = source.z*2.0f - 1.0f;
quat.w = 1.0;
+
+ QuaternionTransform(&quat, modelviewprojection);
- // Traspose quaternion and multiply
- Quaternion result;
- result.x = modelviewprojection.m0 * quad.x + modelviewprojection.m4 * quad.y + modelviewprojection.m8 * quad.z + modelviewprojection.m12 * quad.w;
- result.y = modelviewprojection.m1 * quad.x + modelviewprojection.m5 * quad.y + modelviewprojection.m9 * quad.z + modelviewprojection.m13 * quad.w;
- result.z = modelviewprojection.m2 * quad.x + modelviewprojection.m6 * quad.y + modelviewprojection.m10 * quad.z + modelviewprojection.m14 * quad.w;
- result.w = modelviewprojection.m3 * quad.x + modelviewprojection.m7 * quad.y + modelviewprojection.m11 * quad.z + modelviewprojection.m15 * quad.w;
-
- // Invert
- result.w = 1.0f / result.w;
-
- //if (quat.w == 0.0) return 0;
-
- worldPoint.x = quat.x * quat.w;
- worldPoint.y = quat.y * quat.w;
- worldPoint.z = quat.z * quat.w;
-
- return worldPoint;
- */
-/*
- // Needed Vectors
- Vector3 normalDeviceCoordinates;
- Quaternion rayClip;
- Quaternion rayEye;
- Vector3 rayWorld;
-
- // Getting normal device coordinates
- float x = (2.0 * mousePosition.x) / GetScreenWidth() - 1.0;
- float y = 1.0 - (2.0 * mousePosition.y) / GetScreenHeight();
- float z = 1.0;
- normalDeviceCoordinates = (Vector3){ x, y, z };
-
- // Getting clip vector
- rayClip = (Quaternion){ normalDeviceCoordinates.x, normalDeviceCoordinates.y, -1, 1 };
-
- Matrix invProjection = projection;
- MatrixInvert(&invProjection);
-
- rayEye = MatrixQuaternionMultiply(invProjection, rayClip);
- rayEye = (Quaternion){ rayEye.x, rayEye.y, -1, 0 };
-
- Matrix invModelview = modelview;
- MatrixInvert(&invModelview);
+ if (quat.w != 0.0)
+ {
+ quat.x /= quat.w;
+ quat.y /= quat.w;
+ quat.z /= quat.w;
+ }
- rayWorld = MatrixVector3Multiply(invModelview, (Vector3){rayEye.x, rayEye.y, rayEye.z} );
- VectorNormalize(&rayWorld);
+ result.x = quat.x;
+ result.y = quat.y;
+ result.z = quat.z;
- return rayWorld;
-*/
- return (Vector3){ 0, 0, 0 };
+ return result;
}
// Convert image data to OpenGL texture (returns OpenGL valid Id)
@@ -1780,9 +1776,9 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
#endif
// Magnification and minification filters
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
-
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Alternative: GL_LINEAR
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Alternative: GL_LINEAR
+
#if defined(GRAPHICS_API_OPENGL_33)
if (mipmapCount > 1)
{
@@ -1883,9 +1879,10 @@ Model rlglLoadModel(VertexData mesh)
model.shader.id = 0; // No shader used
#elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- model.texture.id = whiteTexture; // Default whiteTexture
- model.texture.width = 1; // Default whiteTexture width
- model.texture.height = 1; // Default whiteTexture height
+ model.texture.id = whiteTexture; // Default whiteTexture
+ model.texture.width = 1; // Default whiteTexture width
+ model.texture.height = 1; // Default whiteTexture height
+ model.shader = simpleShader; // Default model shader
GLuint vaoModel = 0; // Vertex Array Objects (VAO)
GLuint vertexBuffer[3]; // Vertex Buffer Objects (VBO)
@@ -1903,22 +1900,20 @@ Model rlglLoadModel(VertexData mesh)
// Enable vertex attributes: position
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.vertices, GL_STATIC_DRAW);
- glEnableVertexAttribArray(simpleShader.vertexLoc);
- glVertexAttribPointer(simpleShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
+ glVertexAttribPointer(model.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(model.shader.vertexLoc);
// Enable vertex attributes: texcoords
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh.vertexCount, mesh.texcoords, GL_STATIC_DRAW);
- glEnableVertexAttribArray(simpleShader.texcoordLoc);
- glVertexAttribPointer(simpleShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
+ glVertexAttribPointer(model.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(model.shader.texcoordLoc);
// Enable vertex attributes: normals
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.normals, GL_STATIC_DRAW);
- glEnableVertexAttribArray(simpleShader.normalLoc);
- glVertexAttribPointer(simpleShader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
-
- model.shader = simpleShader; // By default, simple shader will be used
+ glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(model.shader.normalLoc);
model.mesh.vboId[0] = vertexBuffer[0]; // Vertex position VBO
model.mesh.vboId[1] = vertexBuffer[1]; // Texcoords VBO
@@ -1975,6 +1970,8 @@ void *rlglReadTexturePixels(unsigned int textureId, unsigned int format)
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
int width, height;
+ glBindTexture(GL_TEXTURE_2D, textureId);
+
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
//glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
@@ -1995,15 +1992,13 @@ void *rlglReadTexturePixels(unsigned int textureId, unsigned int format)
case UNCOMPRESSED_R8G8B8A8: pixels = (unsigned char *)malloc(size*4); glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; break; // 32 bpp
default: TraceLog(WARNING, "Texture format not suported"); break;
}
-
- glBindTexture(GL_TEXTURE_2D, textureId);
// NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding.
// Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting.
// GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.)
// GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
glPixelStorei(GL_PACK_ALIGNMENT, 1);
-
+
glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
glBindTexture(GL_TEXTURE_2D, 0);
@@ -2027,39 +2022,54 @@ Shader LoadShader(char *vsFileName, char *fsFileName)
// Shaders loading from external text file
char *vShaderStr = TextFileRead(vsFileName);
char *fShaderStr = TextFileRead(fsFileName);
-
- shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
-
- if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Custom shader loaded successfully", shader.id);
- else TraceLog(WARNING, "[SHDR ID %i] Custom shader could not be loaded", shader.id);
-
- // Shader strings must be freed
- free(vShaderStr);
- free(fShaderStr);
- // Set shader textures ids (all 0 by default)
- shader.texDiffuseId = 0;
- shader.texNormalId = 0;
- shader.texSpecularId = 0;
-
- // Get handles to GLSL input attibute locations
- //-------------------------------------------------------------------
- shader.vertexLoc = glGetAttribLocation(shader.id, "vertexPosition");
- shader.texcoordLoc = glGetAttribLocation(shader.id, "vertexTexCoord");
- shader.normalLoc = glGetAttribLocation(shader.id, "vertexNormal");
- // NOTE: custom shader does not use colorLoc
- shader.colorLoc = -1;
-
- // Get handles to GLSL uniform locations (vertex shader)
- shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix");
- shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix");
+ if ((vShaderStr != NULL) && (fShaderStr != NULL))
+ {
+ shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
- // Get handles to GLSL uniform locations (fragment shader)
- shader.tintColorLoc = glGetUniformLocation(shader.id, "tintColor");
- shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0");
- shader.mapNormalLoc = -1; // It can be set later
- shader.mapSpecularLoc = -1; // It can be set later
- //--------------------------------------------------------------------
+ if (shader.id != 0)
+ {
+ TraceLog(INFO, "[SHDR ID %i] Custom shader loaded successfully", shader.id);
+
+ // Set shader textures ids (all 0 by default)
+ shader.texDiffuseId = 0;
+ shader.texNormalId = 0;
+ shader.texSpecularId = 0;
+
+ // Get handles to GLSL input attibute locations
+ //-------------------------------------------------------------------
+ shader.vertexLoc = glGetAttribLocation(shader.id, "vertexPosition");
+ shader.texcoordLoc = glGetAttribLocation(shader.id, "vertexTexCoord");
+ shader.normalLoc = glGetAttribLocation(shader.id, "vertexNormal");
+ // NOTE: custom shader does not use colorLoc
+ shader.colorLoc = -1;
+
+ // Get handles to GLSL uniform locations (vertex shader)
+ shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix");
+ shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix");
+
+ // Get handles to GLSL uniform locations (fragment shader)
+ shader.tintColorLoc = glGetUniformLocation(shader.id, "tintColor");
+ shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0");
+ shader.mapNormalLoc = -1; // It can be set later
+ shader.mapSpecularLoc = -1; // It can be set later
+ //--------------------------------------------------------------------
+ }
+ else
+ {
+ TraceLog(WARNING, "Custom shader could not be loaded");
+ shader = simpleShader;
+ }
+
+ // Shader strings must be freed
+ free(vShaderStr);
+ free(fShaderStr);
+ }
+ else
+ {
+ TraceLog(WARNING, "Custom shader could not be loaded");
+ shader = simpleShader;
+ }
#endif
return shader;
@@ -2169,6 +2179,8 @@ unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr)
void UnloadShader(Shader shader)
{
rlDeleteShader(shader.id);
+
+ TraceLog(INFO, "[SHDR ID %i] Unloaded shader program data", shader.id);
}
// Set custom shader to be used on batch draw
@@ -2205,6 +2217,7 @@ void SetCustomShader(Shader shader)
}
// Set postprocessing shader
+// NOTE: Uses global variables screenWidth and screenHeight
void SetPostproShader(Shader shader)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@@ -2218,8 +2231,8 @@ void SetPostproShader(Shader shader)
Texture2D texture;
texture.id = fboColorTexture;
- texture.width = GetScreenWidth();
- texture.height = GetScreenHeight();
+ texture.width = screenWidth;
+ texture.height = screenHeight;
SetShaderMapDiffuse(&postproQuad.shader, texture);
@@ -2236,9 +2249,12 @@ void SetDefaultShader(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
SetCustomShader(defaultShader);
- SetPostproShader(defaultShader);
- enabledPostpro = false;
+ if (enabledPostpro)
+ {
+ SetPostproShader(defaultShader);
+ enabledPostpro = false;
+ }
#endif
}
@@ -2267,7 +2283,8 @@ void SetModelShader(Model *model, Shader shader)
if (vaoSupported) glBindVertexArray(0); // Unbind VAO
- //if (model->texture.id > 0) model->shader.texDiffuseId = model->texture.id;
+ // NOTE: If SetModelTexture() is called previously, texture is not assigned to new shader
+ if (model->texture.id > 0) model->shader.texDiffuseId = model->texture.id;
#endif
}
@@ -2423,6 +2440,26 @@ void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textur
*/
}
+// Set blending mode (alpha, additive, multiplied)
+// NOTE: Only 3 blending modes predefined
+void SetBlendMode(int mode)
+{
+ if ((blendMode != mode) && (mode < 3))
+ {
+ rlglDraw();
+
+ switch (mode)
+ {
+ case BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break;
+ case BLEND_ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; // Alternative: glBlendFunc(GL_ONE, GL_ONE);
+ case BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); break;
+ default: break;
+ }
+
+ blendMode = mode;
+ }
+}
+
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
void PrintProjectionMatrix(void)
{
@@ -3026,7 +3063,7 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
// Output a trace log message
// NOTE: Expected msgType: (0)Info, (1)Error, (2)Warning
-void TraceLog(int msgType, const char *text, ...)
+static void TraceLog(int msgType, const char *text, ...)
{
va_list args;
va_start(args, text);