opengl draw line 3d gl4
[alphabetize]
"Hullo Triangle"
OpenGL 4 Up and Running
Anton Gerdelan. Final Updated 2 October 2016
The idea of this article is to give a cursory overview of all of the keys parts of an OpenGL 4 programme, without looking at each function in any detail. If you lot accept used another graphics API (or an older version of OpenGL) before, and you want an at-a-glance expect at the differences, then this commodity is for you. If you lot take never done graphics programming before then this is as well a dainty way of getting started with something that "works", and tin can be modified. The following articles will step back and explain each role in more particular.
Install Libraries
Go Main OpenGL Libraries
The main library that you need is libGL. In that location is also a gear up of utility functions in a library called libGLU, but you lot more than likely won't need information technology. OpenGL is a bit weird in that you don't download a library from the website. The Khronos group that command the specification only provides the interface. The actual implementations are done by video hardware manufacturers or other developers. You lot need to have a very modernistic graphics processor to support OpenGL version 4.x, and even so y'all might be express to an earlier implementation if the drivers don't exist however.
To get the latest libgl:
- Windows - Just upgrade the video drivers (Nvidia, AMD, or Intel).
- Linux - By default MESA is used, but typically information technology is a chip slow, and is currently only supporting OpenGL 3.0. To get OpenGL 4 back up, switch to proprietary hardware drivers (Nvidia or AMD - Intel uses MESA) or download from manufacturer website.
- Mac - Apple tree has its own OpenGL implementation, and this comes with each version of Os X. Apple provides OpenGL Capabilities Tables. If you can get OpenGL 3.two or newer then you can do most things from OpenGL 4.
Starting the GL Context With GLFW and GLEW
GLFW is a helper library that will start the OpenGL "context" for us so that it talks to (nearly) any operating system in the aforementioned way. The context is a running copy of OpenGL, tied to a window on the operating system. Note: I've updated this tutorial to use GLFW version 3.0. The interface differs slightly from the previous versions.
The compiled libraries that I downloaded from the website didn't work for me, so I built them myself from the source code. You lot might need to practise this.
The documentation tells the states that nosotros demand to add a #define earlier including the header if we are going to use the dynamic version of the library:
#define GLFW_DLL #include <GLFW/glfw3.h>
There'south a library called GLEW that makes sure that nosotros include the latest version of GL, and not a default [aboriginal] version on the system path. It also handles GL extensions. On Windows if yous try to compile without GLEW you will meet a list of unrecognised GL functions and constants - that ways you're using the '90s Microsoft GL. If you are using MinGW then you lot'll need to compile the library yourself. Much the same every bit with GLFW, the binaries on the webpage aren't entirely reliable - rebuild locally for best results.
Include GLEW before GLFW to employ the latest GL libraries:
#include <GL/glew.h> #define GLFW_DLL #include <GLFW/glfw3.h>
I've uploaded my Windows builds of both for MinGW'south GCC compilers hither:
- GLFW3 Win32 MinGW .dll
- GLEW Win32 MinGW .dll
Initialisation Code
Okay, we can code upward a minimal shell that will start the GL context, print the version, and quit. You lot might like to compile and run this in a terminal to brand sure that everything is working so far, and that your video drivers can support OpenGL 4.
#include <GL/glew.h> // include GLEW and new version of GL on Windows #include <GLFW/glfw3.h> // GLFW helper library #include <stdio.h> int principal() { // get-go GL context and O/Due south window using the GLFW helper library if (!glfwInit()) { fprintf(stderr, "ERROR: could not start GLFW3\n"); return 1; } // uncomment these lines if on Apple tree Os Ten /*glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);*/ GLFWwindow* window = glfwCreateWindow(640, 480, "Hullo Triangle", NULL, NULL); if (!window) { fprintf(stderr, "Mistake: could not open window with GLFW3\north"); glfwTerminate(); return 1; } glfwMakeContextCurrent(window); // beginning GLEW extension handler glewExperimental = GL_TRUE; glewInit(); // get version info const GLubyte* renderer = glGetString(GL_RENDERER); // go renderer string const GLubyte* version = glGetString(GL_VERSION); // version every bit a string printf("Renderer: %s\north", renderer); printf("OpenGL version supported %s\due north", version); // tell GL to only draw onto a pixel if the shape is closer to the viewer glEnable(GL_DEPTH_TEST); // enable depth-testing glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer" /* OTHER STUFF GOES Here NEXT */ // close GL context and any other GLFW resource glfwTerminate(); return 0; } There are 4 lines in the to a higher place code that you should uncomment if yous're on Apple Os 10. We will talk nearly this in the next tutorial. The brusque explanation is that it will go the newest available version of OpenGL on Apple, which will be 4.1 or 3.iii on Mavericks, and 3.2 on pre-Mavericks systems. On other systems information technology will tend to pick three.ii instead of the newest version, which is unhelpful. To improve support for newer OpenGL releases, we can put the flag glewExperimental = GL_TRUE; earlier starting GLEW.
Make sure that your library paths to GLFW and GLEW are correct. I copied the include folders from GLEW and GLFW into the aforementioned folder equally my projection, and then my include folder contains a folder called GLFW, and a folder called GL. I am using MinGW and compile with this line:
g++ -o hellot.exe main.cpp glfw3dll.a libglew32.dll.a -I include -L./ -lglew32 -lglfw3 -lopengl32
I put the GLFW and GLEW library files in my local folder, and told it to expect in that location for the dynamic libraries with -L ./. It should detect the opengl32 library on the system path. On Linux y'all'll most probable install via repositories, and you won't demand the -I or -L path bits. You also won't need the glfw3dll.a and libglew32.dll.a files. The OpenGL library will be called libGL. On Linux I have this command:
thou++ -o hellot main.cpp -lglfw -lGL -lGLEW
Of course, you lot can compile this every bit pure C with gcc or another C compiler every bit well. I tend to sneak in a few C++ short-cuts as a personal preference; I tend to use what they call "C++--".
If you're having trouble linking the libraries, then I suggest building the samples that come with the libraries first, and having a read through their install instructions for your operating system. Practice y'all accept the correct version of the library for your compiler? Are you building a debug or release version - if so are the libraries in the respective place in the IDE carte? Are you building a 32-fleck or 64-bit programme - if so does the library match? If information technology even so isn't working, effort edifice your ain copy of the libraries from source code - I had to do this for both GLFW3 and GLEW.
If I run hellot.exe in the control line I get this:
This tells me that my Windows driver can run up to OpenGL version iv.3. On Mac it might say version 3.2 or 3.3. That's okay, we can make a few pocket-size changes and it will run almost all of the stuff from version 4. I'll signal these out.
Define a Triangle in a Vertex Buffer
Okay, let's define a triangle from 3 points. Later on, we can wait at doing transformations and perspective, merely for now permit'south draw information technology apartment onto the last screen area; 10 between -one and 1, y between -one and 1, and z = 0.
Information technology always helps to describe your problem on paper first. Here I want to ascertain a triangle, with the points given in clock-wise order, that fits into the screen surface area of -1:1 on x and y axes.
Nosotros will pack all of these points into a big array of floating-point numbers; 9 in full. We will start with the top point, and proceed clock-wise in order: xyzxyzxyz. The order should always be in the same winding management, so that we can afterwards determine which side is the front, and which side is the back. We can start writing this under the "/* OTHER STUFF GOES Hither Side by side */" comment, from above.
float points[] = { 0.0f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, -0.5f, 0.0f }; We will copy this chunk of memory onto the graphics menu in a unit called a vertex buffer object (VBO). To do this we "generate" an empty buffer, fix it every bit the electric current buffer in OpenGL's state car past "bounden", then copy the points into the currently leap buffer:
GLuint vbo = 0; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW);
The last line tells GL that the buffer is the size of ix floating point numbers, and gives information technology the address of the kickoff value.
Now an unusual step. Most meshes will use a collection of ane or more vertex buffer objects to hold vertex points, texture-coordinates, vertex normals, etc. In older GL implementations nosotros would have to bind each i, and define their memory layout, every time that we draw the mesh. To simplify that, we take new thing called the vertex array object (VAO), which remembers all of the vertex buffers that you want to use, and the retentivity layout of each i. We ready the vertex array object one time per mesh. When we desire to draw, all we do and so is demark the VAO and depict.
GLuint vao = 0; glGenVertexArrays(1, &vao); glBindVertexArray(vao); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vbo); glVertexAttribPointer(0, three, GL_FLOAT, GL_FALSE, 0, NULL);
Here we tell GL to generate a new VAO for us. It sets an unsigned integer to identify it with later. We demark it, to bring it in to focus in the country machine. This lets usa enable the offset attribute; 0. We are only using a single vertex buffer, so we know that information technology will be attribute location 0. The glVertexAttribPointer function defines the layout of our first vertex buffer; "0" means ascertain the layout for attribute number 0. "3" ways that the variables are vec3 made from every 3 floats (GL_FLOAT) in the buffer.
You might try compiling at this point to make sure that there were no mistakes.
Shaders
We demand to use a shader plan, written in OpenGL Shader Language (GLSL), to define how to draw our shape from the vertex array object. You volition see that the aspect arrow from the VAO will match upwards to our input variables in the shader.
This shader programme is fabricated from the minimum 2 parts; a vertex shader, which describes where the 3d points should cease up on the display, and a fragment shader which colours the surfaces. Both are be written in plainly text, and look a lot like C programmes. Loading these from plain-text files would be nicer; I just wanted to save a bit of web real-estate by hard-coding them here.
const char* vertex_shader = "#version 400\north" "in vec3 vp;" "void main() {" " gl_Position = vec4(vp, 1.0);" "}"; The first line says which version of the shading language to use; in this case iv.0.0. If yous're express to OpenGL iii, modify the kickoff line from "400" to "150"; the version of the shading language compatible with OpenGL 3.two, or "330", for OpenGL iii.3. My vertex shader has 1 input variable; a vec3 (vector made from 3 floats), which matches up to our VAO'southward attribute pointer. This means that each vertex shader gets 3 of the 9 floats from our buffer - therefore iii vertex shaders volition run concurrently; each i positioning one of the vertices. The output has a reserved proper name gl_Position and expects a 4d float. You tin can see that I haven't modified this at all, just added a i to the 4th component. The 1 at the end but means "don't calculate any perspective".
const char* fragment_shader = "#version 400\due north" "out vec4 frag_colour;" "void main() {" " frag_colour = vec4(0.5, 0.0, 0.5, ane.0);" "}"; Again, you may need to alter the first line of the fragment shader if you are on OpenGL 3.ii or 3.3. My fragment shader will run once per pixel-sized fragment that the surface of the shape covers. We still haven't told GL that it will be a triangle (information technology could be 2 lines). Y'all tin can approximate that for a triangle, we will have lots more fragment shaders running than vertex shaders for this shape. The fragment shader has one job - setting the colour of each fragment. It therefore has 1 output - a 4d vector representing a color made from ruddy, bluish, greenish, and blastoff components - each component has a value between 0 and 1. Nosotros aren't using the blastoff component. Can you lot guess what colour this is?
Before using the shaders we have to load the strings into a GL shader, and compile them.
GLuint vs = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vs, 1, &vertex_shader, Nothing); glCompileShader(vs); GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fs, 1, &fragment_shader, Zip); glCompileShader(fs);
Now, these compiled shaders must exist combined into a single, executable GPU shader programme. We create an empty "program", attach the shaders, and then link them together.
GLuint shader_programme = glCreateProgram(); glAttachShader(shader_programme, fs); glAttachShader(shader_programme, vs); glLinkProgram(shader_programme);
Drawing
We draw in a loop. Each iteration draws the screen once; a "frame" of rendering. The loop finishes if the window is closed. Later we tin also ask GLFW is the escape key has been pressed.
while(!glfwWindowShouldClose(window)) { // wipe the drawing surface clear glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(shader_programme); glBindVertexArray(vao); // draw points 0-3 from the currently bound VAO with electric current in-use shader glDrawArrays(GL_TRIANGLES, 0, 3); // update other events similar input handling glfwPollEvents(); // put the stuff we've been cartoon onto the display glfwSwapBuffers(window); } Showtime we articulate the drawing surface, and then set the shader programme that should be "in use" for all further cartoon. We set our VAO (not the VBO) as the input variables that should be used for all further cartoon (in our case just some vertex points). Then nosotros can describe, and we want to describe in triangles mode (1 triangle for every 3 points), and describe from point number 0, for 3 points. GLFW3 requires that we manually call glfwPollEvents() to update non-graphical events like key-presses. Finally, we flip the swap surface onto the screen, and the screen onto the next cartoon surface (nosotros take 2 drawing buffers). Washed!
Experimenting
- Load the shader strings from text files called test_vs.glsl and test_fs.glsl (a naming convention is handy).
- Change the colour of the triangle in the fragment shader.
- Try to motility the shape in the vertex shader e.g. vec4(vp.x, vp.y + one.0, vp.z, 1.0);
- Be Square! Attempt to add together another triangle to the listing of points and make a square shape. Yous volition have to alter several variables when setting up the buffer and drawing the shape. Which variables do you need to keep track of for each triangle (hint: not much...).
- Try drawing with GL_LINE_STRIP or GL_LINES or GL_POINTS instead of triangles. Does it put the lines where you expect? How big are the points by default?
- Effort changing the background color by using glClearColor() before the rendering loop. Something grey-ish is usually fairly neutral; 0.6f, 0.6f, 0.8f, one.0f.
- Now I Want to Come across Two Dragons! Try creating a second VAO, and drawing 2 shapes (remember to demark the second VAO earlier drawing once more).
- Endeavour creating a second shader plan, and draw the 2nd shape a different color (remember to "use" the second shader programme before drawing again).
Common Mistakes
Firstly, if you get a crash executing glGenVertexArrays(), try adding the glewExperimental = GL_TRUE; line earlier initialising GLEW. If you lot're on an Apple car, try uncommenting the lawmaking where we "hint" the version to use.
GLSL Mistakes
In OpenGL, your mistakes are mostly from mis-using the interface (it's non the nigh intuitive API ever... to put information technology kindly). These mistakes often happen in the shaders. In the next commodity nosotros will look at press out any mistakes that are found when the shaders compile, and print any problems with matching the vertex shader to the fragment shader establish during the linking process. This is going to catch near all of your errors, so this should be your first port-of-phone call when diagnosing a trouble.
GL Function Parameter Mistakes
Y'all can besides easily brand small mistakes in the C interface. GL uses a lot of [unsigned] integers (aka "GLuint") to identify handles to variables i.east. the vertex buffer, the vertex array, the shaders, the shader program, and so on. GL also uses a lot of enumerated types similar GL_TRIANGLES which besides resolve to integers. This ways that if you lot mix these up (past putting office parameters in the wrong lodge, for example), GL will think that you have given it valid inputs, and won't mutter. In other words, the GL interface is very poor at using stiff typing for picking upwards errors. These mistakes ofttimes outcome in a black screen, or "no effect", and can be very frustrating. The only way to find them is ofttimes to pick through, and bank check every GL function confronting its prototype to make certain that you lot have given information technology the correct parameters. My well-nigh common error of this type is mixing up location numbers with other indices (happens often when setting upwards textures, for example) - which tin be very hard to spot.
GL State Car Mistakes
Another, very tricky to spot, source of error is knowing which states to set in the country machine earlier calling certain functions. I will try to point all of these out as they announced. An case from our code, above, is the glDrawArrays office. It will use the well-nigh recently leap vertex array, and the most recently used shader programme to draw. If we want to draw a different set up of buffers, and then we need to bind that earlier drawing again. If no valid buffer or shader has been set in the state machine then it will crash.
Next Steps
We will look at initialisation in more item - particularly logging helpful debugging data. We will discuss the functionality of shaders and the hardware architecture. We will create more than circuitous objects with more than 1 vertex buffer, and wait at loading geometry from a file.
richmondthametiones.blogspot.com
Source: https://antongerdelan.net/opengl/hellotriangle.html
0 Response to "opengl draw line 3d gl4"
Post a Comment