Add support for custom shaders

Custom shaders for models
Postprocessig on FBO (in progress)
Some useless spaces removed
This commit is contained in:
raysan5 2015-02-02 00:57:08 +01:00
parent b9e53cd135
commit 42c92e4f2e
4 changed files with 443 additions and 241 deletions

View File

@ -154,7 +154,6 @@ static int gamepadStream = -1; // Gamepad device file descripto
static EGLDisplay display; // Native display device (physical screen connection) static EGLDisplay display; // Native display device (physical screen connection)
static EGLSurface surface; // Surface to draw on, framebuffers (connected to context) static EGLSurface surface; // Surface to draw on, framebuffers (connected to context)
static EGLContext context; // Graphic context, mode in which drawing can be done static EGLContext context; // Graphic context, mode in which drawing can be done
static uint64_t baseTime; // Base time measure for hi-res timer static uint64_t baseTime; // Base time measure for hi-res timer
static bool windowShouldClose = false; // Flag to set window for closing static bool windowShouldClose = false; // Flag to set window for closing
#endif #endif
@ -207,6 +206,12 @@ static double targetTime = 0.0; // Desired time for one frame, if 0
static char configFlags = 0; static char configFlags = 0;
static bool showLogo = false; static bool showLogo = false;
static bool customCamera = true;
//static int cameraMode = CUSTOM; // FREE, FIRST_PERSON, THIRD_PERSON
static bool enabledPostpro = false;
static unsigned int fboShader = 0;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Other Modules Functions Declaration (required by core) // Other Modules Functions Declaration (required by core)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -474,13 +479,15 @@ void BeginDrawing(void)
updateTime = currentTime - previousTime; updateTime = currentTime - previousTime;
previousTime = currentTime; previousTime = currentTime;
if (enabledPostpro) rlEnableFBO();
rlClearScreenBuffers(); rlClearScreenBuffers();
rlLoadIdentity(); // Reset current matrix (MODELVIEW) rlLoadIdentity(); // Reset current matrix (MODELVIEW)
rlMultMatrixf(GetMatrixVector(downscaleView)); // If downscale required, apply it here rlMultMatrixf(GetMatrixVector(downscaleView)); // If downscale required, apply it here
// rlTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL 1.1 //rlTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL 1.1
// NOTE: Not required with OpenGL 3.3+ // NOTE: Not required with OpenGL 3.3+
} }
@ -489,6 +496,9 @@ void EndDrawing(void)
{ {
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2) rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
// TODO: Set postprocessing shader to be passed: SetPostproShader()?
if (enabledPostpro) rlglDrawPostpro(fboShader); // Draw postprocessing effect (shader)
SwapBuffers(); // Copy back buffer to front buffer SwapBuffers(); // Copy back buffer to front buffer
PollInputEvents(); // Poll user events PollInputEvents(); // Poll user events
@ -533,8 +543,15 @@ void Begin3dMode(Camera camera)
rlLoadIdentity(); // Reset current matrix (MODELVIEW) rlLoadIdentity(); // Reset current matrix (MODELVIEW)
// Setup Camera view // Setup Camera view
if (customCamera)
{
Matrix matLookAt = MatrixLookAt(camera.position, camera.target, camera.up); Matrix matLookAt = MatrixLookAt(camera.position, camera.target, camera.up);
rlMultMatrixf(GetMatrixVector(matLookAt)); // Multiply MODELVIEW matrix by view matrix (camera) rlMultMatrixf(GetMatrixVector(matLookAt)); // Multiply MODELVIEW matrix by view matrix (camera)
}
else
{
// TODO: Add support for multiple automatic camera modes
}
} }
// Ends 3D mode and returns to default 2D orthographic mode // Ends 3D mode and returns to default 2D orthographic mode
@ -1188,6 +1205,18 @@ void InitGraphics(void)
#endif #endif
} }
void InitPostShader(void)
{
rlglInitPostpro();
enabledPostpro = true;
}
void SetPostShader(unsigned int shader)
{
fboShader = shader;
}
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
// GLFW3 Error Callback, runs on GLFW3 error // GLFW3 Error Callback, runs on GLFW3 error
static void ErrorCallback(int error, const char *description) static void ErrorCallback(int error, const char *description)

View File

@ -268,9 +268,15 @@ typedef struct Model {
unsigned int vaoId; unsigned int vaoId;
unsigned int vboId[4]; unsigned int vboId[4];
unsigned int textureId; unsigned int textureId;
unsigned int shaderId;
//Matrix transform; //Matrix transform;
} Model; } Model;
// Shader type
typedef struct Shader {
unsigned int id;
} Shader;
// Sound source type // Sound source type
typedef struct Sound { typedef struct Sound {
unsigned int source; unsigned int source;
@ -334,6 +340,9 @@ Color Fade(Color color, float alpha); // Color fade-in or
void SetupFlags(char flags); // Enable some window configurations void SetupFlags(char flags); // Enable some window configurations
void ShowLogo(void); // Activates raylib logo at startup (can be done with flags) void ShowLogo(void); // Activates raylib logo at startup (can be done with flags)
void InitPostShader(void);
void SetPostShader(unsigned int shader);
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Input Handling Functions (Module: core) // Input Handling Functions (Module: core)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -466,6 +475,7 @@ Model LoadHeightmap(Image heightmap, float maxHeight);
Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based) Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based)
void UnloadModel(Model model); // Unload 3d model from memory void UnloadModel(Model model); // Unload 3d model from memory
void SetModelTexture(Model *model, Texture2D texture); // Link a texture to a model void SetModelTexture(Model *model, Texture2D texture); // Link a texture to a model
void SetModelShader(Model *model, unsigned int shader);
void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set)
void DrawModelEx(Model model, Vector3 position, Vector3 rotation, Vector3 scale, Color tint); // Draw a model with extended parameters void DrawModelEx(Model model, Vector3 position, Vector3 rotation, Vector3 scale, Color tint); // Draw a model with extended parameters
@ -474,6 +484,8 @@ void DrawModelWires(Model model, Vector3 position, float scale, Color color);
void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture
void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec
unsigned int LoadCustomShader(char *vsFileName, char *fsFileName); // Load a custom shader (vertex shader + fragment shader)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Audio Loading and Playing Functions (Module: audio) // Audio Loading and Playing Functions (Module: audio)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------

View File

@ -164,6 +164,12 @@ static GLuint simpleVertexLoc, simpleTexcoordLoc, simpleNormalLoc, simpleColorLo
static GLuint simpleProjectionMatrixLoc, simpleModelviewMatrixLoc; static GLuint simpleProjectionMatrixLoc, simpleModelviewMatrixLoc;
static GLuint simpleTextureLoc; static GLuint simpleTextureLoc;
// Custom Shader program attibutes binding locations
static GLuint customVertexLoc, customTexcoordLoc, customNormalLoc, customColorLoc;
static GLuint customProjectionMatrixLoc, customModelviewMatrixLoc;
static GLuint customTextureLoc;
static bool customShader = false;
// Vertex Array Objects (VAO) // Vertex Array Objects (VAO)
static GLuint vaoLines, vaoTriangles, vaoQuads; static GLuint vaoLines, vaoTriangles, vaoQuads;
@ -182,6 +188,9 @@ static bool useTempBuffer = false;
// Support for VAOs (OpenGL ES2 could not support VAO extensions) // Support for VAOs (OpenGL ES2 could not support VAO extensions)
static bool vaoSupported = false; static bool vaoSupported = false;
// Framebuffer object and texture
static GLuint fbo, fboColorTexture, fboDepthTexture, fboShader = 0;
#endif #endif
#if defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_ES2)
@ -208,7 +217,6 @@ static void InitializeBuffersGPU(void);
static void UpdateBuffers(void); static void UpdateBuffers(void);
// Custom shader files loading (external) // Custom shader files loading (external)
static GLuint LoadCustomShader(char *vertexFileName, char *fragmentFileName);
static char *TextFileRead(char *fn); static char *TextFileRead(char *fn);
#endif #endif
@ -696,6 +704,17 @@ void rlDeleteTextures(unsigned int id)
glDeleteTextures(1, &id); glDeleteTextures(1, &id);
} }
// Unload shader from GPU memory
void rlDeleteShader(unsigned int id)
{
glDeleteProgram(id);
}
void rlEnableFBO(void)
{
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
}
// Unload vertex data (VAO) from GPU memory // Unload vertex data (VAO) from GPU memory
void rlDeleteVertexArrays(unsigned int id) void rlDeleteVertexArrays(unsigned int id)
{ {
@ -851,7 +870,8 @@ void rlglInit(void)
// Init default Shader (GLSL 110) -> Common for GL 3.3+ and ES2 // Init default Shader (GLSL 110) -> Common for GL 3.3+ and ES2
defaultShaderProgram = LoadDefaultShader(); defaultShaderProgram = LoadDefaultShader();
simpleShaderProgram = LoadSimpleShader(); simpleShaderProgram = LoadSimpleShader();
//customShaderProgram = LoadShaders("simple150.vert", "simple150.frag"); //simpleShaderProgram = LoadCustomShader("custom.vs", "custom.fs"); // Works ok
//customShaderProgram = LoadCustomShader("simple150.vert", "simple150.frag");
// Get handles to GLSL input vars locations for defaultShaderProgram // Get handles to GLSL input vars locations for defaultShaderProgram
//------------------------------------------------------------------- //-------------------------------------------------------------------
@ -912,6 +932,49 @@ void rlglInit(void)
#endif #endif
} }
// Init postpro system
void rlglInitPostpro(void)
{
// Create the texture that will serve as the color attachment for the framebuffer
glGenTextures(1, &fboColorTexture);
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);
glBindTexture(GL_TEXTURE_2D, 0);
// Create the texture that will serve as the depth attachment for the framebuffer.
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);
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 colort texture and depth texture to FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboColorTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fboDepthTexture, 0);
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);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
fboShader = 0;
// TODO: Init simple quad VAO and data here?
}
// Vertex Buffer Object deinitialization (memory free) // Vertex Buffer Object deinitialization (memory free)
void rlglClose(void) void rlglClose(void)
{ {
@ -950,6 +1013,7 @@ void rlglClose(void)
//glDeleteShader(v); //glDeleteShader(v);
//glDeleteShader(f); //glDeleteShader(f);
glDeleteProgram(defaultShaderProgram); glDeleteProgram(defaultShaderProgram);
glDeleteProgram(simpleShaderProgram);
// Free vertex arrays memory // Free vertex arrays memory
free(lines.vertices); free(lines.vertices);
@ -966,6 +1030,8 @@ void rlglClose(void)
// Free GPU texture // Free GPU texture
glDeleteTextures(1, &whiteTexture); glDeleteTextures(1, &whiteTexture);
if (fbo != 0) glDeleteFramebuffers(1, &fbo);
free(draws); free(draws);
#endif #endif
} }
@ -977,7 +1043,10 @@ void rlglDraw(void)
if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0)) if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0))
{ {
glUseProgram(defaultShaderProgram); // Use our shader if (fbo == 0) glUseProgram(defaultShaderProgram); // Use our default shader
else glUseProgram(fboShader); // Use our postpro shader
glUseProgram(defaultShaderProgram);
glUniformMatrix4fv(defaultProjectionMatrixLoc, 1, false, GetMatrixVector(projection)); glUniformMatrix4fv(defaultProjectionMatrixLoc, 1, false, GetMatrixVector(projection));
glUniformMatrix4fv(defaultModelviewMatrixLoc, 1, false, GetMatrixVector(modelview)); glUniformMatrix4fv(defaultModelviewMatrixLoc, 1, false, GetMatrixVector(modelview));
@ -1116,6 +1185,67 @@ void rlglDraw(void)
#endif #endif
} }
void rlglDrawPostpro(unsigned int shaderId)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// TODO: Draw screen quad with texture
/*
const float quadPositions[] = { 1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, -1.0, 0.0,
-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0 };
const float quadTexcoords[] = { 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 };
glBindBuffer(GL_ARRAY_BUFFER, quadVbo);
glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), quadPositions);
glVertexAttribPointer(ATTRIB_TEXCOORD0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), quadTexcoords);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glEnableVertexAttribArray(ATTRIB_TEXCOORD0);
glBindTexture(GL_TEXTURE_2D, fboColorTexture);
glDrawArrays(GL_TRIANGLES, 0, 2*3);
// Quad render using triangle strip
glBindBuffer(GL_ARRAY_BUFFER, uiVBO[1]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
*/
rlEnableTexture(fboColorTexture);
rlPushMatrix();
rlBegin(RL_QUADS);
rlColor4ub(255, 255, 255, 255);
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
// Bottom-left corner for texture and quad
rlTexCoord2f(0.0f, 1.0f);
rlVertex2f(0.0f, 0.0f);
// Bottom-right corner for texture and quad
rlTexCoord2f(0.0f, 0.0f);
rlVertex2f(0.0f, GetScreenHeight());
// Top-right corner for texture and quad
rlTexCoord2f(1.0f, 0.0f);
rlVertex2f(GetScreenWidth(), GetScreenHeight());
// Top-left corner for texture and quad
rlTexCoord2f(1.0f, 1.0f);
rlVertex2f(GetScreenWidth(), 0.0f);
rlEnd();
rlPopMatrix();
fboShader = shaderId;
rlglDraw();
}
// Draw a 3d model // Draw a 3d model
void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scale, Color color, bool wires) void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scale, Color color, bool wires)
{ {
@ -1159,7 +1289,8 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scal
#endif #endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glUseProgram(simpleShaderProgram); // Use our simple shader if (customShader) glUseProgram(model.shaderId);
else glUseProgram(simpleShaderProgram); // Use our simple shader
VectorScale(&rotation, DEG2RAD); VectorScale(&rotation, DEG2RAD);
@ -1168,14 +1299,25 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scal
Matrix modelviewworld = MatrixMultiply(transform, modelview); Matrix modelviewworld = MatrixMultiply(transform, modelview);
// NOTE: Drawing in OpenGL 3.3+, transform is passed to shader // NOTE: Drawing in OpenGL 3.3+, transform is passed to shader
if (customShader)
{
glUniformMatrix4fv(customProjectionMatrixLoc, 1, false, GetMatrixVector(projection));
glUniformMatrix4fv(customModelviewMatrixLoc, 1, false, GetMatrixVector(modelviewworld));
glUniform1i(customTextureLoc, 0);
}
else
{
glUniformMatrix4fv(simpleProjectionMatrixLoc, 1, false, GetMatrixVector(projection)); glUniformMatrix4fv(simpleProjectionMatrixLoc, 1, false, GetMatrixVector(projection));
glUniformMatrix4fv(simpleModelviewMatrixLoc, 1, false, GetMatrixVector(modelviewworld)); glUniformMatrix4fv(simpleModelviewMatrixLoc, 1, false, GetMatrixVector(modelviewworld));
glUniform1i(simpleTextureLoc, 0); glUniform1i(simpleTextureLoc, 0);
}
// Apply color tinting to model // Apply color tinting to model
// NOTE: Just update one uniform on fragment shader // 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 }; float vColor[4] = { (float)color.r/255, (float)color.g/255, (float)color.b/255, (float)color.a/255 };
glUniform4fv(simpleColorLoc, 1, vColor);
if (customShader) glUniform4fv(customColorLoc, 1, vColor);
else glUniform4fv(simpleColorLoc, 1, vColor);
if (vaoSupported) if (vaoSupported)
{ {
@ -1376,7 +1518,7 @@ Model rlglLoadModel(VertexData mesh)
model.vboId[2] = 0; // Normals VBO model.vboId[2] = 0; // Normals VBO
#elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
model.textureId = 1; // Default whiteTexture model.textureId = whiteTexture; // Default whiteTexture
GLuint vaoModel = 0; // Vertex Array Objects (VAO) GLuint vaoModel = 0; // Vertex Array Objects (VAO)
GLuint vertexBuffer[3]; // Vertex Buffer Objects (VBO) GLuint vertexBuffer[3]; // Vertex Buffer Objects (VBO)
@ -1510,6 +1652,102 @@ unsigned int rlglLoadCompressedTexture(unsigned char *data, int width, int heigh
return id; return id;
} }
// Load a shader (vertex shader + fragment shader) from text data
unsigned int rlglLoadShader(char *vShaderStr, char *fShaderStr)
{
unsigned int program;
GLuint vertexShader;
GLuint fragmentShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
const char *pvs = vShaderStr;
const char *pfs = fShaderStr;
glShaderSource(vertexShader, 1, &pvs, NULL);
glShaderSource(fragmentShader, 1, &pfs, NULL);
GLint success = 0;
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (success != GL_TRUE)
{
TraceLog(WARNING, "[VSHDR ID %i] Failed to compile vertex shader...", vertexShader);
int maxLength = 0;
int length;
glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength);
char log[maxLength];
glGetShaderInfoLog(vertexShader, maxLength, &length, log);
TraceLog(INFO, "%s", log);
}
else TraceLog(INFO, "[VSHDR ID %i] Vertex shader compiled successfully", vertexShader);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (success != GL_TRUE)
{
TraceLog(WARNING, "[FSHDR ID %i] Failed to compile fragment shader...", fragmentShader);
int maxLength = 0;
int length;
glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength);
char log[maxLength];
glGetShaderInfoLog(fragmentShader, maxLength, &length, log);
TraceLog(INFO, "%s", log);
}
else TraceLog(INFO, "[FSHDR ID %i] Fragment shader compiled successfully", fragmentShader);
program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (success == GL_FALSE)
{
TraceLog(WARNING, "[SHDR ID %i] Failed to link shader program...", program);
int maxLength = 0;
int length;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
char log[maxLength];
glGetProgramInfoLog(program, maxLength, &length, log);
TraceLog(INFO, "%s", log);
glDeleteProgram(program);
program = 0;
}
else TraceLog(INFO, "[SHDR ID %i] Shader program loaded successfully", program);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return program;
}
// Read screen pixel data (color buffer) // Read screen pixel data (color buffer)
unsigned char *rlglReadScreenPixels(int width, int height) unsigned char *rlglReadScreenPixels(int width, int height)
{ {
@ -1534,6 +1772,66 @@ unsigned char *rlglReadScreenPixels(int width, int height)
return imgData; // NOTE: image data should be freed return imgData; // NOTE: image data should be freed
} }
unsigned int LoadCustomShader(char *vsFileName, char *fsFileName)
{
// Shaders loading from external text file
char *vShaderStr = TextFileRead(vsFileName);
char *fShaderStr = TextFileRead(fsFileName);
unsigned int shaderId = rlglLoadShader(vShaderStr, fShaderStr);
if (shaderId != 0) TraceLog(INFO, "[SHDR ID %i] Custom shader loaded successfully", shaderId);
else TraceLog(WARNING, "[SHDR ID %i] Custom shader could not be loaded", shaderId);
return shaderId;
// Shader strings must be freed
free(vShaderStr);
free(fShaderStr);
return shaderId;
}
// Link shader to model
void SetModelShader(Model *model, unsigned int shader)
{
// Get handles to GLSL input vars locations for simpleShaderProgram
customVertexLoc = glGetAttribLocation(shader, "vertexPosition");
customTexcoordLoc = glGetAttribLocation(shader, "vertexTexCoord");
customNormalLoc = glGetAttribLocation(shader, "vertexNormal");
// Get handles to GLSL uniform vars locations (vertex-shader)
customModelviewMatrixLoc = glGetUniformLocation(shader, "modelviewMatrix");
customProjectionMatrixLoc = glGetUniformLocation(shader, "projectionMatrix");
// Get handles to GLSL uniform vars locations (fragment-shader)
customTextureLoc = glGetUniformLocation(shader, "texture0");
customColorLoc = glGetUniformLocation(shader, "fragColor");
if (vaoSupported) glBindVertexArray(model->vaoId);
// Enable vertex attributes: position
glBindBuffer(GL_ARRAY_BUFFER, model->vboId[0]);
glEnableVertexAttribArray(customVertexLoc);
glVertexAttribPointer(customVertexLoc, 3, GL_FLOAT, 0, 0, 0);
// Enable vertex attributes: texcoords
glBindBuffer(GL_ARRAY_BUFFER, model->vboId[1]);
glEnableVertexAttribArray(customTexcoordLoc);
glVertexAttribPointer(customTexcoordLoc, 2, GL_FLOAT, 0, 0, 0);
// Enable vertex attributes: normals
glBindBuffer(GL_ARRAY_BUFFER, model->vboId[2]);
glEnableVertexAttribArray(customNormalLoc);
glVertexAttribPointer(customNormalLoc, 3, GL_FLOAT, 0, 0, 0);
if (vaoSupported) glBindVertexArray(0); // Unbind VAO
model->shaderId = shader;
customShader = true;
}
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
void PrintProjectionMatrix() void PrintProjectionMatrix()
@ -1559,10 +1857,12 @@ void PrintModelviewMatrix()
static GLuint LoadDefaultShader(void) static GLuint LoadDefaultShader(void)
{ {
// NOTE: Shaders are written using GLSL 110 (desktop), that is equivalent to GLSL 100 on ES2 // NOTE: Shaders are written using GLSL 110 (desktop), that is equivalent to GLSL 100 on ES2
// NOTE: Detected an error on ATI cards if defined #version 110 while OpenGL 3.3+
// Just defined #version 330 despite shader is #version 110
// Vertex shader directly defined, no external file required // Vertex shader directly defined, no external file required
#if defined(GRAPHICS_API_OPENGL_33) #if defined(GRAPHICS_API_OPENGL_33)
char vShaderStr[] = " #version 110 \n" // NOTE: Equivalent to version 100 on ES2 char vShaderStr[] = " #version 330 \n" // NOTE: Actually, #version 110 (quivalent to #version 100 on ES2)
#elif defined(GRAPHICS_API_OPENGL_ES2) #elif defined(GRAPHICS_API_OPENGL_ES2)
char vShaderStr[] = " #version 100 \n" // NOTE: Must be defined this way! 110 doesn't work! char vShaderStr[] = " #version 100 \n" // NOTE: Must be defined this way! 110 doesn't work!
#endif #endif
@ -1582,7 +1882,7 @@ static GLuint LoadDefaultShader(void)
// Fragment shader directly defined, no external file required // Fragment shader directly defined, no external file required
#if defined(GRAPHICS_API_OPENGL_33) #if defined(GRAPHICS_API_OPENGL_33)
char fShaderStr[] = " #version 110 \n" // NOTE: Equivalent to version 100 on ES2 char fShaderStr[] = " #version 330 \n" // NOTE: Actually, #version 110 (quivalent to #version 100 on ES2)
#elif defined(GRAPHICS_API_OPENGL_ES2) #elif defined(GRAPHICS_API_OPENGL_ES2)
char fShaderStr[] = " #version 100 \n" // NOTE: Must be defined this way! 110 doesn't work! char fShaderStr[] = " #version 100 \n" // NOTE: Must be defined this way! 110 doesn't work!
"precision mediump float; \n" // WebGL, required for emscripten "precision mediump float; \n" // WebGL, required for emscripten
@ -1595,63 +1895,12 @@ static GLuint LoadDefaultShader(void)
" gl_FragColor = texture2D(texture0, fragTexCoord) * fragColor; \n" " gl_FragColor = texture2D(texture0, fragTexCoord) * fragColor; \n"
"} \n"; "} \n";
GLuint program; unsigned int shaderId = rlglLoadShader(vShaderStr, fShaderStr);
GLuint vertexShader;
GLuint fragmentShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER); if (shaderId != 0) TraceLog(INFO, "[SHDR ID %i] Default shader loaded successfully", shaderId);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); else TraceLog(WARNING, "[SHDR ID %i] Default shader could not be loaded", shaderId);
const char *pvs = vShaderStr; return shaderId;
const char *pfs = fShaderStr;
glShaderSource(vertexShader, 1, &pvs, NULL);
glShaderSource(fragmentShader, 1, &pfs, NULL);
GLint success = 0;
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (success != GL_TRUE) TraceLog(WARNING, "[VSHDR ID %i] Failed to compile default vertex shader...", vertexShader);
else TraceLog(INFO, "[VSHDR ID %i] Default vertex shader compiled successfully", vertexShader);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (success != GL_TRUE) TraceLog(WARNING, "[FSHDR ID %i] Failed to compile default fragment shader...", fragmentShader);
else TraceLog(INFO, "[FSHDR ID %i] Default fragment shader compiled successfully", fragmentShader);
program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (success == GL_FALSE)
{
int maxLength;
int length;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
char log[maxLength];
glGetProgramInfoLog(program, maxLength, &length, log);
TraceLog(INFO, "Shader program fail log: %s", log);
}
else TraceLog(INFO, "[SHDR ID %i] Default shader program loaded successfully", program);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return program;
} }
// Load Simple Shader (Vertex and Fragment) // Load Simple Shader (Vertex and Fragment)
@ -1659,10 +1908,12 @@ static GLuint LoadDefaultShader(void)
static GLuint LoadSimpleShader(void) static GLuint LoadSimpleShader(void)
{ {
// NOTE: Shaders are written using GLSL 110 (desktop), that is equivalent to GLSL 100 on ES2 // NOTE: Shaders are written using GLSL 110 (desktop), that is equivalent to GLSL 100 on ES2
// NOTE: Detected an error on ATI cards if defined #version 110 while OpenGL 3.3+
// Just defined #version 330 despite shader is #version 110
// Vertex shader directly defined, no external file required // Vertex shader directly defined, no external file required
#if defined(GRAPHICS_API_OPENGL_33) #if defined(GRAPHICS_API_OPENGL_33)
char vShaderStr[] = " #version 110 \n" // NOTE: Equivalent to version 100 on ES2 char vShaderStr[] = " #version 330 \n" // NOTE: Actually, #version 110 (quivalent to #version 100 on ES2)
#elif defined(GRAPHICS_API_OPENGL_ES2) #elif defined(GRAPHICS_API_OPENGL_ES2)
char vShaderStr[] = " #version 100 \n" // NOTE: Must be defined this way! 110 doesn't work! char vShaderStr[] = " #version 100 \n" // NOTE: Must be defined this way! 110 doesn't work!
#endif #endif
@ -1680,7 +1931,7 @@ static GLuint LoadSimpleShader(void)
// Fragment shader directly defined, no external file required // Fragment shader directly defined, no external file required
#if defined(GRAPHICS_API_OPENGL_33) #if defined(GRAPHICS_API_OPENGL_33)
char fShaderStr[] = " #version 110 \n" // NOTE: Equivalent to version 100 on ES2 char fShaderStr[] = " #version 330 \n" // NOTE: Actually, #version 110 (quivalent to #version 100 on ES2)
#elif defined(GRAPHICS_API_OPENGL_ES2) #elif defined(GRAPHICS_API_OPENGL_ES2)
char fShaderStr[] = " #version 100 \n" // NOTE: Must be defined this way! 110 doesn't work! char fShaderStr[] = " #version 100 \n" // NOTE: Must be defined this way! 110 doesn't work!
"precision mediump float; \n" // precision required for OpenGL ES2 (WebGL) "precision mediump float; \n" // precision required for OpenGL ES2 (WebGL)
@ -1693,117 +1944,22 @@ static GLuint LoadSimpleShader(void)
" gl_FragColor = texture2D(texture0, fragTexCoord) * fragColor; \n" " gl_FragColor = texture2D(texture0, fragTexCoord) * fragColor; \n"
"} \n"; "} \n";
GLuint program; unsigned int shaderId = rlglLoadShader(vShaderStr, fShaderStr);
GLuint vertexShader;
GLuint fragmentShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER); if (shaderId != 0) TraceLog(INFO, "[SHDR ID %i] Simple shader loaded successfully", shaderId);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); else TraceLog(WARNING, "[SHDR ID %i] Simple shader could not be loaded", shaderId);
const char *pvs = vShaderStr; return shaderId;
const char *pfs = fShaderStr;
glShaderSource(vertexShader, 1, &pvs, NULL);
glShaderSource(fragmentShader, 1, &pfs, NULL);
GLint success = 0;
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (success != GL_TRUE) TraceLog(WARNING, "[VSHDR ID %i] Failed to compile simple vertex shader...", vertexShader);
else TraceLog(INFO, "[VSHDR ID %i] Simple vertex shader compiled successfully", vertexShader);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (success != GL_TRUE) TraceLog(WARNING, "[FSHDR ID %i] Failed to compile simple fragment shader...", fragmentShader);
else TraceLog(INFO, "[FSHDR ID %i] Simple fragment shader compiled successfully", fragmentShader);
program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (success == GL_FALSE)
{
int maxLength;
int length;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
char log[maxLength];
glGetProgramInfoLog(program, maxLength, &length, log);
TraceLog(INFO, "Shader program fail log: %s", log);
}
else TraceLog(INFO, "[SHDR ID %i] Simple shader program loaded successfully", program);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return program;
} }
// Load shaders from text files // Read text file
static GLuint LoadCustomShader(char *vertexFileName, char *fragmentFileName)
{
// Shaders loading from external text file
char *vShaderStr = TextFileRead(vertexFileName);
char *fShaderStr = TextFileRead(fragmentFileName);
GLuint program;
GLuint vertexShader;
GLuint fragmentShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
const char *pvs = vShaderStr;
const char *pfs = fShaderStr;
glShaderSource(vertexShader, 1, &pvs, NULL);
glShaderSource(fragmentShader, 1, &pfs, NULL);
glCompileShader(vertexShader);
glCompileShader(fragmentShader);
TraceLog(INFO, "[VSHDR ID %i] Vertex shader compiled successfully", vertexShader);
TraceLog(INFO, "[FSHDR ID %i] Fragment shader compiled successfully", fragmentShader);
program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
free(vShaderStr);
free(fShaderStr);
TraceLog(INFO, "[SHDR ID %i] Shader program loaded successfully", program);
return program;
}
// Read shader text file
// NOTE: text chars array should be freed manually // NOTE: text chars array should be freed manually
static char *TextFileRead(char *fileName) static char *TextFileRead(char *fileName)
{ {
FILE *textFile; FILE *textFile;
char *text = NULL; char *text = NULL;
int count=0; int count = 0;
if (fileName != NULL) if (fileName != NULL)
{ {
@ -1817,7 +1973,7 @@ static char *TextFileRead(char *fileName)
if (count > 0) if (count > 0)
{ {
text = (char *)malloc(sizeof(char) * (count+1)); text = (char *)malloc(sizeof(char) * (count + 1));
count = fread(text, sizeof(char), count, textFile); count = fread(text, sizeof(char), count, textFile);
text[count] = '\0'; text[count] = '\0';
} }

View File

@ -145,22 +145,27 @@ void rlColor4f(float x, float y, float z, float w); // Define one vertex (color)
void rlEnableTexture(unsigned int id); // Enable texture usage void rlEnableTexture(unsigned int id); // Enable texture usage
void rlDisableTexture(void); // Disable texture usage void rlDisableTexture(void); // Disable texture usage
void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU
void rlDeleteShader(unsigned int id); // Delete OpenGL shader program from GPU
void rlDeleteVertexArrays(unsigned int id); // Unload vertex data (VAO) from GPU memory void rlDeleteVertexArrays(unsigned int id); // Unload vertex data (VAO) from GPU memory
void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from GPU memory void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from GPU memory
void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color
void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth) void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth)
int rlGetVersion(void); // Returns current OpenGL version int rlGetVersion(void); // Returns current OpenGL version
void rlEnableFBO(void);
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Functions Declaration - rlgl functionality // Functions Declaration - rlgl functionality
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
void rlglInit(void); // Initialize rlgl (shaders, VAO, VBO...) void rlglInit(void); // Initialize rlgl (shaders, VAO, VBO...)
void rlglInitPostpro(void); // Initialize postprocessing system
void rlglClose(void); // De-init rlgl void rlglClose(void); // De-init rlgl
void rlglDraw(void); // Draw VAO/VBO void rlglDraw(void); // Draw VAO/VBO
void rlglDrawPostpro(unsigned int shaderId); // Draw with postpro shader
void rlglInitGraphics(int offsetX, int offsetY, int width, int height); // Initialize Graphics (OpenGL stuff) void rlglInitGraphics(int offsetX, int offsetY, int width, int height); // Initialize Graphics (OpenGL stuff)
unsigned int rlglLoadTexture(unsigned char *data, int width, int height, bool genMipmaps); // Load in GPU OpenGL texture unsigned int rlglLoadTexture(unsigned char *data, int width, int height, bool genMipmaps); // Load in GPU OpenGL texture
unsigned int rlglLoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int format); unsigned int rlglLoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int format);
unsigned int rlglLoadShader(char *vShaderStr, char *fShaderStr); // Load a shader from text data
Model rlglLoadModel(VertexData mesh); // Upload vertex data into GPU and provided VAO/VBO ids Model rlglLoadModel(VertexData mesh); // Upload vertex data into GPU and provided VAO/VBO ids
void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scale, Color color, bool wires); void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scale, Color color, bool wires);