Combing the basic knowledge of OpenGL - building an OpenGL operating environment on Windows

0. Preface

I have been in contact with and using OpenGL for more than a year since I started the car surround view project last year. In the project, individuals are more involved in the development of algorithm modules in the surround view (parameter calibration, image correction and stitching, color correction, car body transparency, etc.), and have not carefully sorted out and studied the creation of the OpenGL working environment. I feel that this should not be the case. Now start to carefully sort out the relevant knowledge and record it as a blog to deepen understanding, so letz dog!

1. Introduction to OpenGL

Official website: https://www.khronos.org/opengl/wiki/Main_Page , the full name is Open Graphics Library, a cross-language, cross-platform application programming interface for rendering 2D and 3D vector graphics. Note that OpenGL here is just a unified specification interface designated by a group of manufacturers after discussion, but the specific implementation on different platforms and different hardware is the responsibility of the manufacturer itself. This has advantages and disadvantages. The advantage is that the programming specification is unified; the disadvantage is that because the hardware is complicated and the OpenGL specification is still iterating, some hardware cannot fully support all interfaces, or some hardware supports some extension interfaces ahead of time, and these relatively " "Subtle" differences often lead to huge differences in the efficiency and even the results of the same program running on different platforms. This is deeply experienced in the Surround View project .

2. OpenGL start

Homepage: https://www.khronos.org/opengl/wiki/Getting_Started

The reason why this part is taken out is because when I was getting started with OpenGL, the tutorial gave a runnable project as soon as it came up, without much explanation. What freeglut, glew, what does this have to do with opengl? This problem was thrown out of mind with subsequent learning. In fact, this is an integral part of the construction of the OpenGL operating environment.

The official website describes the construction of OpenGL applications like this

 

Writing an OpenGL Application

The first step is to pick your language. Bindings for OpenGL exist in many languages, from C# and Java to Python and Lua. Some languages have multiple sets of OpenGL bindings, none of them being official. All of them are ultimately based on the C/C++ bindings.

If you are not using C/C++, you must download and install a package or library for your chosen language that includes the OpenGL bindings. Some come pre-installed, but others have separate downloads.

If you are using C/C++, then you must first set up a build environment (Visual Studio project, GNU makefile, CMake file, etc) that can link to OpenGL. Under Windows, you need to statically link to a library called OpenGL32.lib (note that you still link to OpenGL32.lib if you're building a 64-bit executable. The "32" part is meaningless). Visual Studio, and most Windows compilers, come with this library.

On Linux, you need to link to libGL. This is done with a command-line parameter of "-lGL".

Initialization

Before you can actually use OpenGL in a program, you must first initialize it. Because OpenGL is platform-independent, there is not a standard way to initialize OpenGL; each platform handles it differently. Non-C/C++ language bindings can also handle these differently.

There are two phases of OpenGL initialization. The first phase is the creation of an OpenGL Context; the second phase is to load all of the necessary functions to use OpenGL. Some non-C/C++ language bindings merge these into one.

OpenGL Context Creation

An OpenGL context represents all of OpenGL. Creating one is very platform-specific, as well as language-binding specific.

If you are using the C/C++ language binding for OpenGL, then you are strongly advised to use a window toolkit for managing this task. These libraries create a window, attach an OpenGL context to this window, and manage basic input for that window. Once you are comfortable with OpenGL, you can then start learning how to do this manually.

Most non-C/C++ language bindings will provide you with a language-specific mechanism for creating a context.

Getting Functions

If you are using a non-C/C++ language binding, then the maintainer of that binding will already handle this as part of context creation. If you are using C/C++, read on.

In order to use OpenGL, you must get OpenGL API functions. For most libraries you are familiar with, you simply #include a header file, make sure a library is linked into your project or makefile, and it all works. OpenGL doesn't work that way.

For reasons that are ultimately irrelevant to this discussion, you must manually load functions via a platform-specific API call. This boilerplate work is done with various OpenGL loading libraries; these make this process smooth. You are strongly advised to use one.

If you want to do it manually however, there is a guide as to how to load functions manually. You still should use an extension loader.

My own development environment is Windows, and the development language is C++. The following important information is extracted from the above description:

1 ) Regardless of using the x64/x86 compilation option, you need to link opengl32.lib

2) You need to build an OpenGL operating environment before you can actually use OpenGL (nonsense). The OpenGL library is platform-dependent, so there is no standard construction method. The construction process is divided into two stages, the first stage is to create the OpenGL context, and the second stage is to load the functions available on the specified platform.

3) For the first stage, its operations are related to the platform, such as window creation, event response, etc., which can be implemented by yourself, but the process is cumbersome and difficult to transplant; the official website recommends using development toolkits, including glut, freeglut, glfw, etc.

4) For the second stage, it is more complicated, because the specification versions and interfaces supported by different platforms are different. OpenGL is recommended to be implemented by loading library tools, including glew, glad, etc.

No wonder the previous tutorial included freeglut and glew first. . .

3. OpenGL Toolkit

Next, briefly introduce the OpenGL toolkit that I have come into contact with.

1)glut

Main page: https://www.opengl.org/resources/libraries/glut/glut_downloads.php#3.6

Although OpenGL can achieve cross-platform rendering, it needs to create a working environment for it when the program is running. We need to create windows and respond to input events (mouse, keyboard). This part of the operation needs to call the interface provided by the running platform. OpenGL does not pay attention . In order to avoid the learning cost brought about by this, GLUT appeared.

GLUT is a utility library written by Mark Kilgard for the routines in the second edition of the OpenGL Red Book. Its purpose is to facilitate learners to learn OpenGL, so it is dedicated to handling complex operations related to the system, including creating windows and initializing OpenGL. Context, handling input events, etc.; it is cross-platform and portable, the latest version is version 3.7 in August 1998. .

2)freeglut

Homepage: http://freeglut.sourceforge.net/

Freeglut is a free and open-source GLUT replacement, because GLUT seems to have given up updates and license reasons, freeglut appeared. freeglut is basically compatible with glut's interface, and adds some new features, including mouse wheel event handling, multi-touch input, and more platform support. I currently use this library when running OpenGL routines on the Windows platform.

The compilation reference of freeglut on windows https://blog.csdn.net/yapingxin/article/details/51678279 , I used V3.2.1; one thing to note is that if you want to use the compiled static library, you need to include Add the macro definition of FREEGLUT_STATIC before freeglut.h

3)glfw

Homepage: https://www.glfw.org/index.html

This tool library is occasionally seen in some OpenGL routines, so let's have a brief understanding. Its function is similar to freeglut, glut was replaced by freeglut because it is too old, but it is said that freeglut has more bugs and is not stable? GLFW came into being. I haven't used it personally, so I won't comment.

4) deafness

Homepage: http://glew.sourceforge.net/

Windows has added support for OpenGL, but only supports OpenGL1.1 version, including header files gl.h, glu.h, library files opengl32.lib and opengl32.dll; here I personally understand that the version of OpenGL supported in the library is higher than The version defined by the header file, but because the relevant interface definition is not included in the header file, it cannot be used in the application. If you want to use a higher version interface, you need to determine whether the interface exists and find the interface address from the library. glew does this.

Header files and library files used on the Windows platform can be directly downloaded from the official website.

4. Engineering construction

1) Introduce freeglut

If we use the OpenGL1.1 version to build the project, we generally need to add references to the OpenGL library and header files; for the convenience of development, we add the use of freeglut, and the first OpenGL fixed pipeline rendering program is released. . .

#define FREEGLUT_STATIC
#include <GL/freeglut.h>

void Initialization()
{
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

	GLfloat lightSpecular[] = { 1.0, 1.0, 1.0, 1.0 };
	GLfloat lightPosition[] = { 0.5, 0.5, 4.0, 0.0 };

	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //指定混合函数
	glShadeModel(GL_SMOOTH);

	glMaterialfv(GL_FRONT, GL_SPECULAR, lightSpecular);
	glMaterialf(GL_FRONT, GL_SHININESS, 100.0);
	glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);

	glEnable(GL_BLEND);        //启用混合状态
	glEnable(GL_LIGHTING);        //启用光照
	glEnable(GL_LIGHT0);        //打开光源0
	glEnable(GL_DEPTH_TEST);    //启用深度检测
	glEnable(GL_COLOR_MATERIAL);//材质跟踪当前绘图色

}

void OnDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  //双缓冲机制 

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glPushMatrix();   //装载
	{
		glTranslatef(0.0f, 0.0f, -3.0f);
		glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
		glutSolidTorus(1.0f, 2.0f, 30.0f, 30.0f);//绘制圆环
	}
	glPopMatrix();  //装出


	glPushMatrix();
	{
		glTranslatef(1.0f, 1.0f, 3.0f);
		glColor4f(0.0f, 1.0f, 0.0f, 0.5);
		glutSolidSphere(2.0f, 30.0f, 30.0f);//绘制球体
	}
	glPopMatrix();

	glPushMatrix();
	glTranslatef(-1, -1, 4);
	glColor4f(0.0f, 0.0f, 1.0f, 0.5);
	glBegin(GL_QUADS);  //绘制四边形
	glVertex3f(0, 0, 0);
	glVertex3f(5, 0, 0);
	glVertex3f(5, 5, 0);
	glVertex3f(0, 5, 0);
	glEnd();
	glPopMatrix();

	glPushMatrix();
	glColor4f(0.0f, 1.0f, 1.0f, 0.5);
	glTranslatef(-1, -1, 5);
	glRotatef(60, 0, 0, 1);
	glBegin(GL_QUADS);
	glVertex3f(0, 0, 0);
	glVertex3f(5, 0, 0);
	glVertex3f(5, 5, 0);
	glVertex3f(0, 5, 0);
	glEnd();
	glPopMatrix();

	glutSwapBuffers();
}

void OnReShape(int w, int h)
{
	glViewport(0, 0, w, h);

	glMatrixMode(GL_PROJECTION); //将当前矩阵指定为投影模式
	glLoadIdentity();

	if (h != 0)
	{
		GLfloat aspect = GLfloat(w) / GLfloat(h);

		if (w < h)
		{
			glOrtho(-6.0f, 6.0f, -6.0f * aspect, 6.0f * aspect, -6.0f, 6.0f);//三维正交投影
		}
		else
		{
			glOrtho(-6.0f / aspect, 6.0f / aspect, -6.0f, 6.0f, -6.0f, 6.0f);
		}
	}
	glMatrixMode(GL_MODELVIEW);
}


void main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(600, 480);
	glutCreateWindow("OpenGL透明");

	glutReshapeFunc(OnReShape);
	glutDisplayFunc(OnDisplay);

	Initialization();
	glutMainLoop();  //主程序循环
}

The rendering result is shown in the figure below.

Note: 1) Only the interface supported by OpenGL1.1 is called in the program, so glew/glad is not introduced; 2) gl.h is not included in the program, and opengl32.lib is not introduced in the project settings, although it is specified in the project The freeglut library path, but the additional library name freeglut.lib or freeglut_static.lib is not set, but the program can run normally, why? By looking at freeglut_std.h, it is found that gl.h and glu.h are included in the header file, and the OpenGL library file included in the Windows system and the freeglut library file are introduced through pragma comment; 3) Due to the introduction of freeglut.h, the program gl.h/glu.h can no longer be included in the file, otherwise an error will be reported when compiling .

#   if FREEGLUT_LIB_PRAGMAS
#       pragma comment (lib, "glu32.lib")    /* link OpenGL Utility lib     */
#       pragma comment (lib, "opengl32.lib") /* link Microsoft OpenGL lib   */
#       pragma comment (lib, "gdi32.lib")    /* link Windows GDI lib        */
#       pragma comment (lib, "winmm.lib")    /* link Windows MultiMedia lib */
#       pragma comment (lib, "user32.lib")   /* link Windows user lib       */
#   endif


/* Windows static library */
#   ifdef FREEGLUT_STATIC

#       define FGAPI
#       define FGAPIENTRY

        /* Link with Win32 static freeglut lib */
#       if FREEGLUT_LIB_PRAGMAS
#           ifdef NDEBUG
#              pragma comment (lib, "freeglut_static.lib")
#           else
#              pragma comment (lib, "freeglut_staticd.lib")
#           endif
#       endif

/* Windows shared library (DLL) */
#   else

#       define FGAPIENTRY __stdcall
#       if defined(FREEGLUT_EXPORTS)
#           define FGAPI __declspec(dllexport)
#       else
#           define FGAPI __declspec(dllimport)

            /* Link with Win32 shared freeglut lib */
#           if FREEGLUT_LIB_PRAGMAS
#               ifdef NDEBUG
#                   pragma comment (lib, "freeglut.lib")
#               else
#                   pragma comment (lib, "freeglutd.lib")
#               endif
#           endif

#       endif

#   endif

Hidden enough.

2) Introduce glew

Since programmable pipeline rendering is required, a higher version of the OpenGL interface function must be used, which cannot be supported by gl.h/glu.h in Windows, so the glew tool library is introduced. The code is as follows, note that in order to use the static library of glew, the macro definition of GLEW_STATIC is added before including glew.h

#include <stdio.h>
#define GLEW_STATIC
#include <GL/glew.h>
#define FREEGLUT_STATIC
#include <GL/freeglut.h>

GLuint VBO;

static void RenderSceneCB()
{
	glClear(GL_COLOR_BUFFER_BIT);

	glEnableVertexAttribArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

	glDrawArrays(GL_TRIANGLES, 0, 3);

	glDisableVertexAttribArray(0);

	glutSwapBuffers();
}


static void InitializeGlutCallbacks()
{
	glutDisplayFunc(RenderSceneCB);
}

static void CreateVertexBuffer()
{
	float Vertices[9];

	Vertices[0] = -1;
	Vertices[1] = -1;
	Vertices[2] = -1;

	Vertices[3] = 1;
	Vertices[4] = -1;
	Vertices[5] = -1;

	Vertices[6] = 0;
	Vertices[7] = 1;
	Vertices[8] = -1;

	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}


int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(1024, 768);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("Tutorial 03");

	InitializeGlutCallbacks();

	// Must be done after glut is initialized!
	GLenum res = glewInit();
	if (res != GLEW_OK) {
		fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
		return 1;
	}

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	CreateVertexBuffer();
	glFrontFace(GL_CCW);
	glCullFace(GL_BACK);
	glEnable(GL_CULL_FACE);

	glutMainLoop();

	return 0;
}

The code execution effect is as shown in the figure below.

In the subsequent project development, freeglut+glew was used to build the OpenGL operating environment on the Windows platform. This is the end of this article, and the next article will start to sort out the construction of the OpenGLES operating environment.

Guess you like

Origin blog.csdn.net/lwx309025167/article/details/102588055