#include <iostream> // cout, cerr #include <cstdlib> // EXIT_FAILURE #include <GL/glew.h> // GLEW library #include <GLFW/glfw3.h> // GLFW library // GLM Math Header inclusions #include <glm/glm.hpp> #include <glm/gtx/transform.hpp> #include <glm/gtc/type_ptr.hpp> using namespace std; // Standard namespace /*Shader program Macro*/ #ifndef GLSL #define GLSL(Version, Source) "#version " #Version " core \n" #Source #endif // Unnamed namespace namespace { const char* const WINDOW_TITLE = "3-3 Assignment: Building a 3D Pyramid (Diego Bez Zambiazzi)"; // Macro for window title // Variables for window width and height const int WINDOW_WIDTH = 800; const int WINDOW_HEIGHT = 600; // Stores the GL data relative to a given mesh struct GLMesh { GLuint vao; // Handle for the vertex array object GLuint vbos[2]; // Handles for the vertex buffer objects GLuint nIndices; // Number of indices of the mesh }; // Main GLFW window GLFWwindow* gWindow = nullptr; // Triangle mesh data GLMesh gMesh; // Shader program GLuint gProgramId; } /* User-defined Function prototypes to: * initialize the program, set the window size, * redraw graphics on the window when resized, * and render graphics on the screen */ bool UInitialize(int, char* [], GLFWwindow** window); void UResizeWindow(GLFWwindow* window, int width, int height); void UProcessInput(GLFWwindow* window); void UCreateMesh(GLMesh& mesh); void UDestroyMesh(GLMesh& mesh); void URender(); bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId); void UDestroyShaderProgram(GLuint programId); /* Vertex Shader Source Code*/ const GLchar* vertexShaderSource = GLSL(440, layout(location = 0) in vec3 position; // Vertex data from Vertex Attrib Pointer 0 layout(location = 1) in vec4 color; // Color data from Vertex Attrib Pointer 1 out vec4 vertexColor; // variable to transfer color data to the fragment shader //Global variables for the transform matrices uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view * model * vec4(position, 1.0f); // transforms vertices to clip coordinates vertexColor = color; // references incoming color data } ); /* Fragment Shader Source Code*/ const GLchar* fragmentShaderSource = GLSL(440, in vec4 vertexColor; // Variable to hold incoming color data from vertex shader out vec4 fragmentColor; void main() { fragmentColor = vec4(vertexColor); } ); int main(int argc, char* argv[]) { if (!UInitialize(argc, argv, &gWindow)) return EXIT_FAILURE; // Create the mesh UCreateMesh(gMesh); // Calls the function to create the Vertex Buffer Object // Create the shader program if (!UCreateShaderProgram(vertexShaderSource, fragmentShaderSource, gProgramId)) return EXIT_FAILURE; // Sets the background color of the window to black (it will be implicitely used by glClear) glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // render loop // ----------- while (!glfwWindowShouldClose(gWindow)) { // input // ----- UProcessInput(gWindow); // Render this frame URender(); glfwPollEvents(); } // Release mesh data UDestroyMesh(gMesh); // Release shader program UDestroyShaderProgram(gProgramId); exit(EXIT_SUCCESS); // Terminates the program successfully } // Initialize GLFW, GLEW, and create a window bool UInitialize(int argc, char* argv[], GLFWwindow** window) { // GLFW: initialize and configure // ------------------------------ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif // GLFW: window creation // --------------------- * window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, NULL, NULL); if (*window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return false; } glfwMakeContextCurrent(*window); glfwSetFramebufferSizeCallback(*window, UResizeWindow); // GLEW: initialize // ---------------- // Note: if using GLEW version 1.13 or earlier glewExperimental = GL_TRUE; GLenum GlewInitResult = glewInit(); if (GLEW_OK != GlewInitResult) { std::cerr << glewGetErrorString(GlewInitResult) << std::endl; return false; } // Displays GPU OpenGL version cout << "INFO: OpenGL Version: " << glGetString(GL_VERSION) << endl; return true; } // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly void UProcessInput(GLFWwindow* window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } // glfw: whenever the window size changed (by OS or user resize) this callback function executes void UResizeWindow(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } // Functioned called to render a frame void URender() { // Enable z-depth glEnable(GL_DEPTH_TEST); // Clear the frame and z buffers glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 1. Scales the object by 2 glm::mat4 scale = glm::scale(glm::vec3(2.0f, 2.0f, 2.0f)); // 2. Rotates shape by 3.141592f * 0.6f pi radians around the Z axis glm::mat4 rotation = glm::rotate(3.141592f * 0.66f, glm::vec3(0.0f, 0.0f, 1.0f)); // 3. Place object at the origin glm::mat4 translation = glm::translate(glm::vec3(0.0f, 0.0f, 0.0f)); // Model matrix: transformations are applied right-to-left order glm::mat4 model = translation * rotation * scale; // Transforms the camera: move the camera back (z axis) glm::mat4 viewTranslation = glm::translate(glm::vec3(0.0f, 0.0f, -5.0f)); // Rotates the view around the X axis glm::mat4 viewRotation = glm::rotate(-3.141592f * 0.45f, glm::vec3(1.0f, 0.0f, 0.0f)); glm::mat4 view = viewTranslation * viewRotation; // Creates a perspective projection glm::mat4 projection = glm::perspective(45.0f, (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 0.1f, 100.0f); // Set the shader to be used glUseProgram(gProgramId); // Retrieves and passes transform matrices to the Shader program GLint modelLoc = glGetUniformLocation(gProgramId, "model"); GLint viewLoc = glGetUniformLocation(gProgramId, "view"); GLint projLoc = glGetUniformLocation(gProgramId, "projection"); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection)); // Activate the VBOs contained within the mesh's VAO glBindVertexArray(gMesh.vao); // Draws the triangles glDrawElements(GL_TRIANGLES, gMesh.nIndices, GL_UNSIGNED_SHORT, NULL); // Draws the triangle // Deactivate the Vertex Array Object glBindVertexArray(0); // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) glfwSwapBuffers(gWindow); // Flips the the back buffer with the front buffer every frame. } // Implements the UCreateMesh function void UCreateMesh(GLMesh& mesh) { // Position and Color data GLfloat verts[] = { // Vertex Positions // Colors (r,g,b,a) 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Vertex 0 Top Right Cyan 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Vertex 1 Bottom Right Blue -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, // Vertex 2 Bottom Left Yellow -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Vertex 3 Top Left Pink 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, // Vertex 4 Pyramid top White }; // Index data to share position data GLushort indices[] = { 0, 1, 2, // Triangle 1 0, 3, 2, // Triangle 2 0, 1, 4, // Triangle 3 1, 2, 4, // Triangle 4 2, 3, 4, // Triangle 5 3, 0, 4, // Triangle 6 }; const GLuint floatsPerVertex = 3; const GLuint floatsPerColor = 4; glGenVertexArrays(1, &mesh.vao); // we can also generate multiple VAOs or buffers at the same time glBindVertexArray(mesh.vao); // Create 2 buffers: first one for the vertex data; second one for the indices glGenBuffers(2, mesh.vbos); glBindBuffer(GL_ARRAY_BUFFER, mesh.vbos[0]); // Activates the buffer glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); // Sends vertex or coordinate data to the GPU mesh.nIndices = sizeof(indices) / sizeof(indices[0]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.vbos[1]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // Strides between vertex coordinates is 6 (x, y, z, r, g, b, a). A tightly packed stride is 0. GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);// The number of floats before each // Create Vertex Attribute Pointers glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex)); glEnableVertexAttribArray(1); } void UDestroyMesh(GLMesh& mesh) { glDeleteVertexArrays(1, &mesh.vao); glDeleteBuffers(2, mesh.vbos); } // Implements the UCreateShaders function bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId) { // Compilation and linkage error reporting int success = 0; char infoLog[512]; // Create a Shader program object. programId = glCreateProgram(); // Create the vertex and fragment shader objects GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); // Retrive the shader source glShaderSource(vertexShaderId, 1, &vtxShaderSource, NULL); glShaderSource(fragmentShaderId, 1, &fragShaderSource, NULL); // Compile the vertex shader, and print compilation errors (if any) glCompileShader(vertexShaderId); // compile the vertex shader // check for shader compile errors glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertexShaderId, 512, NULL, infoLog); std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; return false; } glCompileShader(fragmentShaderId); // compile the fragment shader // check for shader compile errors glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragmentShaderId, sizeof(infoLog), NULL, infoLog); std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; return false; } // Attached compiled shaders to the shader program glAttachShader(programId, vertexShaderId); glAttachShader(programId, fragmentShaderId); glLinkProgram(programId); // links the shader program // check for linking errors glGetProgramiv(programId, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(programId, sizeof(infoLog), NULL, infoLog); std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; return false; } glUseProgram(programId); // Uses the shader program return true; } void UDestroyShaderProgram(GLuint programId) { glDeleteProgram(programId); }
Write, Run & Share C++ code online using OneCompiler's C++ online compiler for free. It's one of the robust, feature-rich online compilers for C++ language, running on the latest version 17. Getting started with the OneCompiler's C++ compiler is simple and pretty fast. The editor shows sample boilerplate code when you choose language as C++
and start coding!
OneCompiler's C++ online compiler supports stdin and users can give inputs to programs using the STDIN textbox under the I/O tab. Following is a sample program which takes name as input and print your name with hello.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name;
cout << "Enter name:";
getline (cin, name);
cout << "Hello " << name;
return 0;
}
C++ is a widely used middle-level programming language.
When ever you want to perform a set of operations based on a condition If-Else is used.
if(conditional-expression) {
//code
}
else {
//code
}
You can also use if-else for nested Ifs and If-Else-If ladder when multiple conditions are to be performed on a single variable.
Switch is an alternative to If-Else-If ladder.
switch(conditional-expression){
case value1:
// code
break; // optional
case value2:
// code
break; // optional
......
default:
code to be executed when all the above cases are not matched;
}
For loop is used to iterate a set of statements based on a condition.
for(Initialization; Condition; Increment/decrement){
//code
}
While is also used to iterate a set of statements based on a condition. Usually while is preferred when number of iterations are not known in advance.
while (condition) {
// code
}
Do-while is also used to iterate a set of statements based on a condition. It is mostly used when you need to execute the statements atleast once.
do {
// code
} while (condition);
Function is a sub-routine which contains set of statements. Usually functions are written when multiple calls are required to same set of statements which increases re-usuability and modularity. Function gets run only when it is called.
return_type function_name(parameters);
function_name (parameters)
return_type function_name(parameters) {
// code
}