Site Name

Copyright © 2019 All rights reserved | This template is made with ♥ by Gulshan

Example for use of Mode, View and Projection Matrix by drawing a rectangle filled with texture using OpenGL in C++30

//============================================================================ // Name : GLFWwithCPP.cpp // Author : Gulshan Chaurasia // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ /*following libraries have been included for compiling this * gcc -o "HelloGLFW" ./Main.o -lGLEW -lglfw3 -lGL -lm -ldl -lX11 -lpthread -lXrandr -lXi * * you need to have following libraries installed for it to compile correctly: * -GLEW * -GLFW3 * -GL * -GLU * On Ubuntu, all of these can be installed by running below command: * sudo apt-get install libglfw3-dev libgl1-mesa-dev libglu1-mesa-dev libglew-dev * * Also, you need SOIL library to work with images in OpenGL * Have written my own GMatrix class containing all the required functions for Rotation, * Scaling, Translation, Transpose, Orthographic Projection and Perspective Projection matrix. **/ #include #include // GLEW #define GLEW_STATIC #include // GLFW #include using namespace std; #include #include "Shader.h" #include "GMatrix.cpp" void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); int main() { cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr); if (window == nullptr) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { std::cout << "Failed to initialize GLEW" << std::endl; return -1; } glViewport(0, 0, 800, 600); //registering callback, for event handling!! glfwSetKeyCallback(window, key_callback); //INITIALIZING opengl parameters before drawing //triangle coordinates GLfloat vertices[] = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f }; //vertex buffer objects (VBO) that can store a large number //of vertices in the GPU’s memory //Just like any object in OpenGL this buffer has a unique ID corresponding to that //buffer, so we can generate one with a buffer ID using the glGenBuffers function: GLuint VBO; glGenBuffers(1, &VBO); //We can bind the newly created buffer to the GL_ARRAY_BUFFER target //with the glBindBuffer function: glBindBuffer(GL_ARRAY_BUFFER, VBO); //From that point on any buffer calls we make (on the GL_ARRAY_BUFFER target) will be used //to configure the currently bound buffer, which is VBO. //Then we can make a call to glBufferData //function that copies the previously defined vertex data into the buffer’s memory: glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); Shader myShader("src/vertexshader.vs","src/fragmentshader.frag"); Shader myShader2("src/vertexshader3.vs","src/fragmentshader3.frag"); //we can tell OpenGL how it should interpret the vertex data (per vertex //attribute) using glVertexAttribPointer: glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); //The process to generate a VAO looks simliar to that of a VBO: GLuint VAO; glGenVertexArrays(1, &VAO); // 1. Bind Vertex Array Object glBindVertexArray(VAO); // 2. Copy our vertices array in a buffer for OpenGL to use //glBindBuffer(GL_ARRAY_BUFFER, VBO);these steps already done above!! //glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 3. Then set our vertex attributes pointers glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), ( GLvoid*)0); glEnableVertexAttribArray(0); //4. Unbind the VAO glBindVertexArray(0); //INITIALIZING rectangle parameters!! GLfloat vertices2[] = { //Positions //Colors //Texture Coords 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top Right 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Bottom Right -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Bottom Left -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f // Top Left }; GLuint indices2[] = { // Note that we start from 0! 0, 1, 3, // First Triangle 1, 2, 3 // Second Triangle }; GLuint VAO2; glGenVertexArrays(1, &VAO2); glBindVertexArray(VAO2); GLuint VBO2; glGenBuffers(1, &VBO2); glBindBuffer(GL_ARRAY_BUFFER, VBO2); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW); GLuint EBO2; glGenBuffers(1, &EBO2); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO2); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW); // Position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); // Color attribute glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); // TexCoord attribute glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); glEnableVertexAttribArray(2); // 4. Unbind VAO (NOT the EBO) glBindVertexArray(0); //-----------------------Working with textures------------------------------- glEnable(GL_TEXTURE_2D); //need to call below two functions for transparency to work!! glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //LOADING image from a file using SOIL library , for using as 2D texture int width, height; std::string path = "src/logo.png";//if image doesn't load, make sure to check the path is appropriate. //IDEs change the relative path for binaries , even if they are in same folder, its relative path is //different, try using absolute path to image, if it loads image correctly, you know you have problem //with relative path and try to figure it out!! unsigned char* image = SOIL_load_image(path.c_str(), &width, &height, 0, SOIL_LOAD_AUTO); std::cout << width << ", " << height << endl; //Like any of the previous objects in OpenGL, textures are referenced with an ID; let’s create one: GLuint texture; glGenTextures(1, &texture); //Just like other objects we need to bind it so any subsequent texture commands will configure the //currently bound texture: glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);//GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);//GL_MIRRORED_REPEAT); //float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f }; //glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //Now that the texture is bound, we can start generating a texture using the previously loaded //image data. Textures are generated with glTexImage2D: //using GL_RGBA for jpg image causes program to crash, thus am checking if its jpg, jpeg or png before //calling glTexImage2D, and use GL_RGB for jpg,jpeg images, and GL_RGBA for png!! std::string extention = path.substr(path.size()-4, path.size()-1); if( extention == ".png" )//has transparency { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); } else if (extention == ".jpg" || extention == "jpeg")//no transparency { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); } else std::cout << "Unknown image format!!" << std::endl; //Once glTexImage2D is called, the currently bound texture object now has the texture image attached to it. glGenerateMipmap(GL_TEXTURE_2D); //After we’re done generating the texture and its corresponding mipmaps, it is good practice to //free the image memory and unbind the texture object: SOIL_free_image_data(image); glBindTexture(GL_TEXTURE_2D, 0); //All that’s left to do now is to bind the texture before calling the glDrawElements and it will //then automatically assign the texture to the fragment shader’s sampler //in the game loop!! //-----------------------#Working with textures------------------------------- //creating identity matrix for transformation; cause if we apply transformation to identity matrix and finally multiply //our vector representing our coordinates with the matrix, it gets transformed!! // Applying Scaling -> Rotation -> Translation in this order , gives best result!! GMatrix matrix1; matrix1.identity(); matrix1.print(0); //first scaling above matrix GMatrix modelMatrix4x4 = matrix1.scale(1,1,1); //then, rotating along Z axis //modelMatrix4x4 = modelMatrix4x4.rotateAlongZAxis(75); //then finally along x axis modelMatrix4x4 = modelMatrix4x4.rotateAlongXAxis(75); modelMatrix4x4.print(2); //we need to supply this matrix as 1D array to opengl function in game loop GLfloat modelMatrix[16]; modelMatrix4x4.toFloatArray(modelMatrix); GMatrix viewMatrix4x4 = matrix1;//for now its simply an Identity matrix viewMatrix4x4.print(6); GLfloat viewMatrix[16]; viewMatrix4x4.toFloatArray(viewMatrix); //-0.5 to 0.5 for left to right and bottom to top works for opengl!! //for perspective projection 30 to 100 for near to far works //for orthographic projection 0.1 to 100 for near to far works!! //GMatrix projectionMatrix4x4 = matrix1.perspectiveProjectionMatrix(-0.5f, 0.5f, -0.5f, 0.5f, 30.0f, 100.0f); GMatrix projectionMatrix4x4 = matrix1.orthographicProjectionMatrix(-0.5f, 0.5f, -0.5f, 0.5f, 30.0f, 100.0f); projectionMatrix4x4.print(6); GLfloat projectionMatrix[16]; projectionMatrix4x4.toFloatArray(projectionMatrix); //GLint nrAttributes; //glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes); //std::cout << "Maximum nr of vertex attributes supported: " << nrAttributes << std::endl; //this is the game loop while(!glfwWindowShouldClose(window)) { glfwPollEvents(); //all the rendering is done here!! glClearColor(0.5f, 0.3f, 0.7f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, texture); GLint vertexColorLocation = glGetUniformLocation(myShader2.getProgram(), "ourColor"); GLuint modelLoc = glGetUniformLocation(myShader2.getProgram(), "model"); GLuint viewLoc = glGetUniformLocation(myShader2.getProgram(), "view"); GLuint projectionLoc = glGetUniformLocation(myShader2.getProgram(), "projection"); myShader2.useProgram(); glUniform4f(vertexColorLocation, 1.0f, 1.0f, 1.0f, 0.0f); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, modelMatrix); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, viewMatrix); glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, projectionMatrix);//modelMatrix is actually a 1D array!!,cause we need to supply this matrix as 1D array to opengl function glBindVertexArray(VAO2); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);//GL_LINE for wireframe, GL_FILL for solid glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glBindVertexArray(0); //The result is a program object that we can activate by calling glUseProgram with the newly //created program object as its argument: //First, we retrieve the running time in seconds via glfwGetTime(). Then we vary the color //in the range of 0.0 - 1.0 by using the sin function and store the result in greenValue. GLfloat timeValue = glfwGetTime(); GLfloat greenValue = (sin(timeValue) / 2) + 0.5; //Then we query for the location of the ourColor uniform using glGetUniformLocation. vertexColorLocation = glGetUniformLocation(myShader.getProgram(), "ourColor"); myShader.useProgram(); glUniform4f(vertexColorLocation, 1.0f, greenValue, 1-greenValue, 1.0f); //actual drawing takes place here //Lastly we can set the uniform value using the glUniform4f function. glBindVertexArray(VAO); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//GL_LINE for wireframe, GL_FILL for solid glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0); //updating transformation matrix modelMatrix4x4 = matrix1;//.scale(1,1,1);//matrix1 is identity matrix modelMatrix4x4 = modelMatrix4x4.rotateAlongYAxis(180*greenValue); //modelMatrix4x4 = modelMatrix4x4.rotateAlongXAxis(75*greenValue); modelMatrix4x4 = modelMatrix4x4.translate(0, 0.2, -1); //std::cout << greenValue << std::endl; modelMatrix4x4.toFloatArray(modelMatrix); glfwSwapBuffers(window); } glfwTerminate(); return 0; } void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { // When a user presses the escape key, we set the WindowShouldClose property to true, // closing the application if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); }

published by gulshan on 2019-12-19 10:06:53

0 likes 0 dislikes