/******************************************************************************************* * * raylib [rlgl] example - Using rlgl module as standalone module * * NOTE: This example requires OpenGL 3.3 or ES2 versions for shaders support, * OpenGL 1.1 does not support shaders but it can also be used. * * DEPENDENCIES: * rlgl.h - OpenGL 1.1 immediate-mode style coding translation layer * glad.h - OpenGL extensions initialization library (required by rlgl) * raymath.h - 3D math library (required by rlgl) * glfw3 - Windows and context initialization library * * rlgl library is provided as a single-file header-only library, this library * allows coding in a pseudo-OpenGL 1.1 style while translating calls to multiple * OpenGL versions backends (1.1, 2.1, 3.3, ES 2.0). * * COMPILATION: * gcc -o rlgl_standalone.exe rlgl_standalone.c -s -Iexternal\include -I..\..\src \ * -L. -Lexternal\lib -lglfw3 -lopengl32 -lgdi32 -Wall -std=c99 \ * -DRAYMATH_IMPLEMENTATION -DGRAPHICS_API_OPENGL_33 * * LICENSE: zlib/libpng * * This example is licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software: * * Copyright (c) 2014-2018 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. * * Permission is granted to anyone to use this software for any purpose, including commercial * applications, and to alter it and redistribute it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not claim that you * wrote the original software. If you use this software in a product, an acknowledgment * in the product documentation would be appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not be misrepresented * as being the original software. * * 3. This notice may not be removed or altered from any source distribution. * ********************************************************************************************/ #define RLGL_IMPLEMENTATION #define RLGL_STANDALONE #include "rlgl.h" // OpenGL 1.1 immediate-mode style coding #ifdef __EMSCRIPTEN__ #define GLFW_INCLUDE_ES2 #endif #include // Windows/Context and inputs management #define RED (Color){ 230, 41, 55, 255 } // Red #define RAYWHITE (Color){ 245, 245, 245, 255 } // My own White (raylib logo) #define DARKGRAY (Color){ 80, 80, 80, 255 } // Dark Gray //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- static void ErrorCallback(int error, const char* description); static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); // Drawing functions (uses rlgl functionality) static void DrawGrid(int slices, float spacing); static void DrawCube(Vector3 position, float width, float height, float length, Color color); static void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); static void DrawRectangleV(Vector2 position, Vector2 size, Color color); //---------------------------------------------------------------------------------- // Main Entry point //---------------------------------------------------------------------------------- int main(void) { // Initialization //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; // GLFW3 Initialization + OpenGL 3.3 Context + Extensions //-------------------------------------------------------- glfwSetErrorCallback(ErrorCallback); if (!glfwInit()) { TraceLog(LOG_WARNING, "GLFW3: Can not initialize GLFW"); return 1; } else TraceLog(LOG_INFO, "GLFW3: GLFW initialized successfully"); glfwWindowHint(GLFW_SAMPLES, 4); glfwWindowHint(GLFW_DEPTH_BITS, 16); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, "rlgl standalone", NULL, NULL); if (!window) { glfwTerminate(); return 2; } else TraceLog(LOG_INFO, "GLFW3: Window created successfully"); glfwSetWindowPos(window, 200, 200); glfwSetKeyCallback(window, KeyCallback); glfwMakeContextCurrent(window); glfwSwapInterval(1); // Load OpenGL 3.3 supported extensions rlLoadExtensions(glfwGetProcAddress); //-------------------------------------------------------- // Initialize OpenGL context (states and resources) rlglInit(screenWidth, screenHeight); // Initialize viewport and internal projection/modelview matrices rlViewport(0, 0, screenWidth, screenHeight); rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix rlLoadIdentity(); // Reset current matrix (PROJECTION) rlOrtho(0, screenWidth, screenHeight, 0, 0.0f, 1.0f); // Orthographic projection with top-left corner at (0,0) rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix rlLoadIdentity(); // Reset current matrix (MODELVIEW) rlClearColor(245, 245, 245, 255); // Define clear color rlEnableDepthTest(); // Enable DEPTH_TEST for 3D Camera camera; camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) camera.fovy = 45.0f; // Camera field-of-view Y Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; // Cube default position (center) //-------------------------------------------------------------------------------------- // Main game loop while (!glfwWindowShouldClose(window)) { // Update //---------------------------------------------------------------------------------- // ... //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- rlClearScreenBuffers(); // Clear current framebuffer // Draw '3D' elements in the scene //----------------------------------------------- // Calculate projection matrix (from perspective) and view matrix from camera look at Matrix matProj = MatrixPerspective(camera.fovy*DEG2RAD, (double)screenWidth/(double)screenHeight, 0.01, 1000.0); Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); SetMatrixModelview(matView); // Set internal modelview matrix (default shader) SetMatrixProjection(matProj); // Set internal projection matrix (default shader) DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, RAYWHITE); DrawGrid(10, 1.0f); // NOTE: Internal buffers drawing (3D data) rlglDraw(); //----------------------------------------------- // Draw '2D' elements in the scene (GUI) //----------------------------------------------- #define RLGL_CREATE_MATRIX_MANUALLY #if defined(RLGL_CREATE_MATRIX_MANUALLY) matProj = MatrixOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0); matView = MatrixIdentity(); SetMatrixModelview(matView); // Set internal modelview matrix (default shader) SetMatrixProjection(matProj); // Set internal projection matrix (default shader) #else // Let rlgl generate and multiply matrix internally rlMatrixMode(RL_PROJECTION); // Enable internal projection matrix rlLoadIdentity(); // Reset internal projection matrix rlOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0); // Recalculate internal projection matrix rlMatrixMode(RL_MODELVIEW); // Enable internal modelview matrix rlLoadIdentity(); // Reset internal modelview matrix #endif DrawRectangleV((Vector2){ 10.0f, 10.0f }, (Vector2){ 780.0f, 20.0f }, DARKGRAY); // NOTE: Internal buffers drawing (2D data) rlglDraw(); //----------------------------------------------- glfwSwapBuffers(window); glfwPollEvents(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- rlglClose(); // Unload rlgl internal buffers and default shader/texture glfwDestroyWindow(window); // Close window glfwTerminate(); // Free GLFW3 resources //-------------------------------------------------------------------------------------- return 0; } //---------------------------------------------------------------------------------- // Module specific Functions Definitions //---------------------------------------------------------------------------------- // GLFW3: Error callback static void ErrorCallback(int error, const char* description) { TraceLog(LOG_ERROR, description); } // GLFW3: Keyboard callback 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); } } // Draw rectangle using rlgl OpenGL 1.1 style coding (translated to OpenGL 3.3 internally) static void DrawRectangleV(Vector2 position, Vector2 size, Color color) { rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); rlVertex2i(position.x, position.y); rlVertex2i(position.x, position.y + size.y); rlVertex2i(position.x + size.x, position.y + size.y); rlVertex2i(position.x, position.y); rlVertex2i(position.x + size.x, position.y + size.y); rlVertex2i(position.x + size.x, position.y); rlEnd(); } // Draw a grid centered at (0, 0, 0) static void DrawGrid(int slices, float spacing) { int halfSlices = slices / 2; rlBegin(RL_LINES); for(int i = -halfSlices; i <= halfSlices; i++) { if (i == 0) { rlColor3f(0.5f, 0.5f, 0.5f); rlColor3f(0.5f, 0.5f, 0.5f); rlColor3f(0.5f, 0.5f, 0.5f); rlColor3f(0.5f, 0.5f, 0.5f); } else { rlColor3f(0.75f, 0.75f, 0.75f); rlColor3f(0.75f, 0.75f, 0.75f); rlColor3f(0.75f, 0.75f, 0.75f); rlColor3f(0.75f, 0.75f, 0.75f); } rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing); rlVertex3f((float)i*spacing, 0.0f, (float)halfSlices*spacing); rlVertex3f((float)-halfSlices*spacing, 0.0f, (float)i*spacing); rlVertex3f((float)halfSlices*spacing, 0.0f, (float)i*spacing); } rlEnd(); } // Draw cube // NOTE: Cube position is the center position void DrawCube(Vector3 position, float width, float height, float length, Color color) { float x = 0.0f; float y = 0.0f; float z = 0.0f; rlPushMatrix(); // NOTE: Be careful! Function order matters (rotate -> scale -> translate) rlTranslatef(position.x, position.y, position.z); //rlScalef(2.0f, 2.0f, 2.0f); //rlRotatef(45, 0, 1, 0); rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); // Front Face ----------------------------------------------------- rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right // Back Face ------------------------------------------------------ rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left // Top Face ------------------------------------------------------- rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left rlVertex3f(x-width/2, y+height/2, z+length/2); // Bottom Left rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right // Bottom Face ---------------------------------------------------- rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Right rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left // Right face ----------------------------------------------------- rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left // Left Face ------------------------------------------------------ rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Right rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right rlEnd(); rlPopMatrix(); } // Draw cube wires void DrawCubeWires(Vector3 position, float width, float height, float length, Color color) { float x = 0.0f; float y = 0.0f; float z = 0.0f; rlPushMatrix(); rlTranslatef(position.x, position.y, position.z); //rlRotatef(45, 0, 1, 0); rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); // Front Face ----------------------------------------------------- // Bottom Line rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right // Left Line rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right // Top Line rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left // Right Line rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left // Back Face ------------------------------------------------------ // Bottom Line rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right // Left Line rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right // Top Line rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left // Right Line rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left // Top Face ------------------------------------------------------- // Left Line rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left Front rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left Back // Right Line rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right Front rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right Back // Bottom Face --------------------------------------------------- // Left Line rlVertex3f(x-width/2, y-height/2, z+length/2); // Top Left Front rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left Back // Right Line rlVertex3f(x+width/2, y-height/2, z+length/2); // Top Right Front rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Right Back rlEnd(); rlPopMatrix(); }