Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Learn OpenGL #123

Closed
acs opened this issue Jul 18, 2020 · 28 comments
Closed

Learn OpenGL #123

acs opened this issue Jul 18, 2020 · 28 comments
Labels
research Research a Topic

Comments

@acs
Copy link
Contributor

acs commented Jul 18, 2020

It is time to start learning OpenGL. Needed for #122 and in general, to understand the details of computer 3D graphics.

The two main references are:

My idea is to start using the NeHe Python tutorials. Let's see.

“Modern” OpenGL (version 3.x and higher, latest is 4.5) which uses lower level API’s to give you more flexibility. But we are using the older versions during the learning process. From this cool intro: http://15462.courses.cs.cmu.edu/spring2018content/lectures/00_opengl/00_opengl_slides.pdf

Great book with lots of references to free resources: http://www.realtimerendering.com/

https://learnopengl.com/book/book_pdf.pdf

«OpenGL is an API for accessing a hardware-based rasterizer. As such, it conforms to the model for rasterization-based 3D renderers. A rasterizer receives a sequence of triangles from the user, performs operations on them, and writes pixels based on this triangle data. This is a simplification of how rasterization works in OpenGL, but it is useful for our purposes.»
https://paroj.github.io/gltut/Basics/Intro%20Graphics%20and%20Rendering.html

@acs
Copy link
Contributor Author

acs commented Jul 18, 2020

GLUT is the windowing library used instead of pygame of pyglet. It seems to be more low level. Let's see. Because it is unmaintained for more then 20 years: https://www.opengl.org/resources/libraries/glut/ But probably FreeGLUT is what we are using inside PyOpenGL: http://freeglut.sourceforge.net/ (An alternative: https://www.glfw.org/ with python support https://github.com/pyglfw/pyglfw)

The idea is to use https://wiki.python.org/moin/PyOpenGL and in the Python examples is used: https://github.com/gamedev-net/nehe-opengl/blob/master/python/lesson01/ztvE1/lesson1.py

The contents from this lesso1 is in NeHe tutorials at: http://nehe.gamedev.net/tutorial/creating_an_opengl_window_(win32)/13001/

Let's check if it useful this combination to learn OpenGL. The first thing is to try to run the code. And as expected, there are issue, Some functions don't exist anymore:

glutSetIdleFuncCallback
glutSetReshapeFuncCallback
glutSetKeyboardFuncCallback

And of course, it is python2 code which needs some love to work on python3. Once all is fixed following lesson02 a nice blank sreen is show:

Screenshot from 2020-07-18 11-51-48

It seems that lesson2 has updated code: https://github.com/gamedev-net/nehe-opengl/blob/master/python/lesson02/ztvDB/Lesson%2002/lesson02.py

This one works like a charm (just fix the print so it works in python3):

Screenshot from 2020-07-18 11-49-30

Let's comparte and try to fix also lesson1.

@acs
Copy link
Contributor Author

acs commented Jul 18, 2020

http://www.wag.caltech.edu/home/rpm/python_course/Lecture_7.pdf A nice intro to OpenGL from 2000 by Richard P. Muller

This code is pretty similar to the one the the tutorials, so it is great to confirm things.

@acs
Copy link
Contributor Author

acs commented Jul 18, 2020

Lesson 1: "This program will create a blank OpenGL window"

Original my own fixed working with PyOpenGL and Python3.

The contents of the tutorial (1-5): lesson1

Is it possible that a tutorial for C++ in Windows from 2000 is useful for learning OpenGL in Python in 2020? Let's see.

  • OpenGL Rendering Context: every OpenGL program has one
  • Device Context
  • Graphis Device Interface: Window

The Rendering Context is linked to the Device Context which is linked to the GDI to show OpenGL results in a window.

The GDI I remember is something specific for Windows.

The creation and destroy oof the window in our case is done by GLUT. So we can forget about this part of the tutorial. But it is important to know that there is a OpenGL Rendering Context. In our case is the window created and destoryed by GLUT:

        window = glutCreateWindow("Jeff Molofee's GL Code Tutorial ... NeHe '99")
...
        glutDestroyWindow(window)

There are a lot of things at the start of lesson1 that are handled by the GLUT library in our case. But the concepts are the same, so it is not a waste of time reading them. And once we are totally OpenGL, the window is juts where our work will be shown, the code will be the same in the tutorial and in Python.

We have some important matrices:

  • Projection Matrix: responsible for adding perspective to our scene
  • Model Matrix: where our object information is stored

and critical concepts:

  • The depth buffer keeps track of how deep objects are into the screen and it is a very important part of OpenGL

This is not in Python: glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) which tell OpenGL we want the best perspective correction to be done.

  • InitGL() where we can set up lighting, textures, and anything else that needs to be setup
  • By using double buffering we get smooth flicker free animation

Ok, after reading this first lesson, yes, we can learn OpenGL from this tutorials. There are tons of Windows specific stuff that is not needed because of GLUT, but the OpenGL code it the same except the glHint line. So great!

@acs
Copy link
Contributor Author

acs commented Jul 18, 2020

Common to all lessons

  • GLUT window creation, positioning and registering of draw functions and key control
  • DrawGLScene: method to draw the OpenGL Scene
  • ReSizeGLScene method to resize the OpenGL Scene
  • keyPressed method to control key interaction
  • InitGL: method to initialize OpenGL
  • glutMainLoop: method for processing events in the app (main loop)

So it seems that all the code can be reused and just change the DrawGLScene from lesson to lesson.

@acs
Copy link
Contributor Author

acs commented Jul 18, 2020

After reviewing all lessons, probably we should focus in the first 10 lessons. After them, the rest are pretty specialized. At this point we should move to other goals.

@acs acs added the research Research a Topic label Jul 19, 2020
@acs
Copy link
Contributor Author

acs commented Jul 19, 2020

Lesson 2

Drawing 3D models it is no that hard for basic shapes:

  • Triangle:
    # Draw a triangle
    glBegin(GL_POLYGON)  # Start drawing a polygon
    glVertex3f(0.0, 1.0, 0.0)  # Top
    glVertex3f(1.0, -1.0, 0.0)  # Bottom Right
    glVertex3f(-1.0, -1.0, 0.0)  # Bottom Left
    glEnd()  # We are done with the polygon
  • Square:
    glBegin(GL_QUADS)  # Start drawing a 4 sided polygon
    glVertex3f(-1.0, 1.0, 0.0)  # Top Left
    glVertex3f(1.0, 1.0, 0.0)  # Top Right
    glVertex3f(1.0, -1.0, 0.0)  # Bottom Right
    glVertex3f(-1.0, -1.0, 0.0)  # Bottom Left
    glEnd()  # We are done with the polygon

To show the results when you are working with Double Buffering:

glutSwapBuffers()

Units

It is important to understand for example in the glVertex3 how to define the coordinates. We are working in 2D: the z coordinate is always 0. But, whats is the value for 1.0?

Screenshot from 2020-07-19 23-52-13

The dimensions of the GLUT Window are:

glutInitWindowSize(640, 480)

So, howto translate then top of the triangle 'glVertex3f(0.0, 1.0, 0.0)' to a pixel coordinates?

Probably this is done with the perspective:

gluPerspective(45.0, float(Width) / float(Height), 0.1, 100.0)

with the aspect ratio: float(Width) / float(Height). But I am not totally sure about that.

The coordinates are relatives to the block glBegin(GL_POLYGON) ... glEnd()

(0, 0, 0) is the center of the glBegin block. The top y-axis of the window seems to be a 2.5. So 480/2 = 240 = 2.5

But doing this exercise is wrong. The size of the shapes depends on the perspective, the position of the viewer ... so it is all relative. By default 1 is related the max size with respect to the aspect ratio and the dimensions of the screen.

And the drawing begins in tthe center of the glBegin block. Ok, let's continue with this intuitive idea.

@acs
Copy link
Contributor Author

acs commented Jul 20, 2020

Lesson3

This is a pretty easy lesson un which I directly modify the lesson2 sample. The Python code from the tutorial is not always updated with the tutorial contents (probably the content was updated), so it is better to follow this approach.

You set a color before adding a vertex. When the figure is closed, for example the triangle, if all the vertexes are from the same color, the triangle color will be the same. If not, the inside color will change from the color of a vertex to the color of the other vertex. The smoothing of colors is because of glShadeModel(GL_SMOOTH).

To set a vertex color:

glColor3f(1.0, 0.0, 0.0)

Screenshot from 2020-07-20 07-20-45

@acs
Copy link
Contributor Author

acs commented Jul 20, 2020

Refactoring

Ok, after 3 tutorials, is clear that the code to modify between tutorials is going to be small. So let's create a basic OpenGLApp class with all the shared code and inherit from it in each sample. And we will just redefined the needed methods.

Also, I do a heavy refactoring of the code to be more pythonic.

@acs
Copy link
Contributor Author

acs commented Jul 20, 2020

Lesson4

Completed also lesson4 with rotations pretty fast. i have created a gif animation with peek

  • Triangle rotating based on y
  • Square rotating based on x

The rotation speed is x1, x10 (x1: 1 degree per refresh)

lesson4_x1
lesson4_x10

@acs
Copy link
Contributor Author

acs commented Jul 20, 2020

Lesson 5

Ok, let's add volumen to our trianble and square converting them in a pyramid and a cube! Our 2D scene will show its 3D nature (ok, in the rotation sample, the 3D was clear also).

Lesson completed for the Pyramid. Things are getting cooler but we need to start selecting better colors :)

lesson5_pyr

@acs
Copy link
Contributor Author

acs commented Jul 21, 2020

And the rotating cube

lesso5_cube

@acs
Copy link
Contributor Author

acs commented Jul 21, 2020

Performance testing starts:

cubes

https://twitter.com/acstw/status/1285697498825338893

@acs
Copy link
Contributor Author

acs commented Jul 22, 2020

Lesson 6

Ok, let's continue with textures. This sample seems to be more tricky because it has two versions, one with glaux (for loading images) and the other one with SOIL. There are bindings for python: https://pypi.org/project/pysoil/ (but they are unmaintained, the project does not exists anymore and there are no samples).

Let's try to find some other tutorials that we can use as the base for loading the texture. The python version for this lesson could help: https://github.com/gamedev-net/nehe-opengl/blob/master/python/lesson6/lesson6.py

There are other samples like: http://www.magikcode.com/?p=122

And pretty goood: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/ But using C.

The translation details to Python to NeHe lesson 6: http://pyopengl.sourceforge.net/context/tutorials/nehe6.html

Ok, I have my first texture applied to a square:

Screenshot from 2020-07-22 08-29-05

Next step is to play with real textures and apply them to 3D objects!

@acs
Copy link
Contributor Author

acs commented Jul 23, 2020

And the textures working in 3D models:

voxopengl

@acs
Copy link
Contributor Author

acs commented Jul 23, 2020

So what's next? I don't pretend to learn all OpenGL with deep this time, but there are three more topics I would like to cover:

Taking a look to the tutorials, 7-10 must be covered also.

And then I will try to jump to:

  • Collision Detection (30)
  • Introduction to Physical Simulations (39)
  • Rope Physics (40)

Let's see how far I reach. During the trip I am refactoring the Python code so probably at the end, a mini framework for OpenGL with Python will emerge.

@acs
Copy link
Contributor Author

acs commented Jul 24, 2020

Lesson 7: Texture Filters, Lighting & Keyboard Control

Topics: use three different texture filters, move an object using keys on the keyboard, apply simple lighting to your OpenGL scene

All done: https://twitter.com/acstw/status/1286713147831844864

@acs
Copy link
Contributor Author

acs commented Jul 24, 2020

Lesson 8: Blending

What is so important about blending? "Blending is used to combine the color of a given pixel that is about to be drawn with the pixel that is already on the screen." It materials are opaque there is no blending, just draw the pixel of the outer object. But if they are transparent in some grade, the blending magic starts. Ok, time to explore this world of blending.

All done:

acs/opengl-samples@8db755a

@acs
Copy link
Contributor Author

acs commented Jul 24, 2020

Ok, I would like to focus now in physics. But I am not totally sure where is the best place to learn about physics in 3D. ¿OpenGL? ¿Vulkan? Is it the same?

Maybe it is time to learn a bit Vulkan API. I will stop here my OpenGL trip until I decide where to continue.

@acs
Copy link
Contributor Author

acs commented Jul 24, 2020

After taking a quick look, OpenGL has more resources about physics than Vulkan, so I will continue with OpenGL. Next step is to find then best way to learn howto apply physics to 3D models with OpenGL.

https://github.com/bulletphysics/bullet3 Is this what we are searching for? Playing with it we will learn more about collision detection and physics engines which is a good thing. And probably we will know better the way to follow.

@acs
Copy link
Contributor Author

acs commented Jul 24, 2020

Ok, after researching about physics engines, it is a huge topic, so let's try to get some basics concepts from the tutorial:

http://nehe.gamedev.net/tutorial/introduction_to_physical_simulations/18005/

also, reading and reading it seems that this chapter is more valuable:

https://sites.google.com/site/letsmakeavoxelengine/home/physics

@acs
Copy link
Contributor Author

acs commented Jul 25, 2020

Lesson 9: Moving Bitmaps In 3D Space

http://nehe.gamedev.net/tutorial/moving_bitmaps_in_3d_space/17001/

It is the same that what I have already done for cubes.py sample. The logic is more complex so I have decided not to invest time in this tutorial.

@acs
Copy link
Contributor Author

acs commented Jul 25, 2020

Probably we must also learn from more updated resources like:

https://learnopengl.com/Getting-started/Hello-Triangle

in order to use modern OpenGL and windowing systems, like GLFW: https://learnopengl.com/Getting-started/Creating-a-window

@acs
Copy link
Contributor Author

acs commented Jul 25, 2020

Matrices

In the code of OpenGL all are matrices. And the different operations are done with them. Let's review why matrices are used and the basic math around them.

http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/
https://open.gl/transformations

After reading both articles, in OpenGL we work normally with vectors of 4d and convert them using different transformations. A key concept in transformations is the order in which they have to be applied:

  • Scaling
  • Rotation
  • Translation

The order it not commutative and if we don't follow it, we will have strange results.

«The job of transforming 3D points into 2D coordinates on your screen is also accomplished through matrix transformations»

3D to 2D pipeline:

Screenshot from 2020-07-25 17-29-24

@acs
Copy link
Contributor Author

acs commented Jul 26, 2020

OpenGL in Linux

The OpenGL implementation in Linux is done by Mesa: https://en.wikipedia.org/wiki/Mesa_(computer_graphics) It offers the API for OpenGL, Vulkan and others APis. And it implements them using the video driver specific for the available graphics card. It seems that Mesa used DRM API which is the one implemented by the graphics drivers.

OpenGL in Linux

Linux Graphics Stack

In my case it is:

[~]$ glxinfo | grep -i opengl
OpenGL vendor string: Intel
OpenGL renderer string: Mesa Intel(R) UHD Graphics 620 (KBL GT2)
OpenGL core profile version string: 4.6 (Core Profile) Mesa 20.1.3
OpenGL core profile shading language version string: 4.60
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 4.6 (Compatibility Profile) Mesa 20.1.3
OpenGL shading language version string: 4.60
OpenGL context flags: (none)
OpenGL profile mask: compatibility profile
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.2 Mesa 20.1.3
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
OpenGL ES profile extensions:

Then intel drivers are described in: https://01.org/linuxgraphics: «The Intel Linux Graphics project is composed by different components, such as Kernel, Mesa, VAAPI, xf86-video-intel, and LibDRM. »

The name of the driver is i915:

[~]$ lsmod | grep i915
i915                 2600960  39
i2c_algo_bit           16384  1 i915
cec                    61440  1 i915
drm_kms_helper        249856  1 i915
drm                   618496  12 drm_kms_helper,i915
video                  53248  2 thinkpad_acpi,i915

For testing OpenGL in Linux:

  • glxgears (original pretty basic)
  • glmark2: 2728, 2769 in two consecutives iterations

@acs
Copy link
Contributor Author

acs commented Jul 27, 2020

Ok, time to return to the NeHe tutorials, the 10 about creating a simple 3D World.

Loading And Moving Through A 3D World

@acs
Copy link
Contributor Author

acs commented Jul 30, 2020

I have decided to stop my research in OpenGl, which is for rendering rasterized graphics, in order to put our focus in ray tracing. if needed, I will continue with OpenGL in the future. It has been a great time. And we have the python samples ready to be used in the future.

@acs acs closed this as completed Jul 30, 2020
@acs
Copy link
Contributor Author

acs commented Oct 9, 2020

Great tutorials using C: https://antongerdelan.net/opengl/hellotriangle.html

@acs
Copy link
Contributor Author

acs commented Oct 9, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
research Research a Topic
Projects
None yet
Development

No branches or pull requests

1 participant