In this Python Opengl article we are going to talk about Modern Opengl Programming in Python. also i want to show you Drawing of Triangle where we have vertex shaders and fragment shaders that runs on GPU (Graphic Process Unit).
So before this we had two articles on Python Opengl Programming
1: Introduction To Python Opengl Programming
2: Python Opengl Programming Drawing Teapot
Why Modern Opengl Programming ?
The first question I would like to answer is why there is a term called ‘modern OpenGL’. Is there ‘old OpenGL ‘ as well? Basically modern means “using programmable graphics pipeline”, old means “fixed pipeline”.
What is the difference? This is quite a broad topic, but for now I think it is good to know that fixed pipeline was like a black box. You inserted the vertex data in the front (at the input) and you got triangles written to the framebuffer (screen) at the end. You could of course tweak this box to your needs but at some point, it was not enough.
Programmable pipeline is more like a white, transparent box where not only you put input data and wait for the result, but you can insert/change internal mechanisms as well. There is a general form of the pipeline, but a lot of parts are fully controlled by you – thanks to shaders.
What Are Shaders ?
Shaders are little programs that rest on the GPU. These programs are run for each specific section of the graphics pipeline. So In a basic sense, shaders are nothing more than programs transforming inputs to outputs. Shaders are also very isolated programs in that they’re not allowed to communicate with each other; the only communication they have is via their inputs and outputs.
What Is GLSL ?
Shaders are written in the C-like language GLSL. GLSL is tailored for use with graphics and contains useful features specifically targeted at vector and matrix manipulation.
Also Shaders always begin with a version declaration, followed by a list of input and output variables, uniforms and its main function.
Each shader’s entry point is at its main function where we process any input variables and output the results in its output variables.
Don’t worry if you don’t know what uniforms are, we’ll get to those shortly.
So now this is the complete code for Python Modern Opengl Drawing Triangle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
from OpenGL.GLUT import * from OpenGL.GL import * from OpenGL.GL import shaders import numpy as np VERTEX_SHADER = """ #version 330 in vec4 position; void main() { gl_Position = position; } """ FRAGMENT_SHADER = """ #version 330 void main() { gl_FragColor = vec4(1.0f, 0.0f,0.0f,1.0f); } """ shaderProgram = None def initliaze(): global VERTEXT_SHADER global FRAGMEN_SHADER global shaderProgram vertexshader = shaders.compileShader(VERTEX_SHADER, GL_VERTEX_SHADER) fragmentshader = shaders.compileShader(FRAGMENT_SHADER, GL_FRAGMENT_SHADER) shaderProgram = shaders.compileProgram(vertexshader, fragmentshader) triangles = [-0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, 0.0] triangles = np.array(triangles, dtype=np.float32) VBO = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, VBO) glBufferData(GL_ARRAY_BUFFER, triangles.nbytes, triangles, GL_STATIC_DRAW) position = glGetAttribLocation(shaderProgram, 'position') glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(position) def render(): global shaderProgram global VAO glClearColor(0, 0, 0, 1) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glUseProgram(shaderProgram) glDrawArrays(GL_TRIANGLES, 0, 3) glUseProgram(0) glutSwapBuffers() def main(): glutInit([]) glutInitWindowSize(640, 480) glutCreateWindow("pyopengl with glut") initliaze() glutDisplayFunc(render) glutMainLoop() if __name__ == '__main__': main() |
So at the top these are Vertex and Fragment shaders
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
VERTEX_SHADER = """ #version 330 in vec4 position; void main() { gl_Position = position; } """ FRAGMENT_SHADER = """ #version 330 void main() { gl_FragColor = vec4(1.0f, 0.0f,0.0f,1.0f); } """ |
These lines are for compiling the shaders
1 2 |
vertexshader = shaders.compileShader(VERTEX_SHADER, GL_VERTEX_SHADER) fragmentshader = shaders.compileShader(FRAGMENT_SHADER, GL_FRAGMENT_SHADER) |
After compiling the shaders we need to compile the program
1 |
shaderProgram = shaders.compileProgram(vertexshader, fragmentshader) |
These are the triangle position
1 2 3 4 5 |
triangles = [-0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, 0.0] triangles = np.array(triangles, dtype=np.float32) |
So in modern opengl programming you need create VBO (Vertex Buffer Object).
A vertex buffer object (VBO) is an OpenGL feature that provides methods for uploading vertex data (position, normal vector, color, etc.) to the video device for non-immediate-mode rendering.
1 2 3 |
VBO = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, VBO) glBufferData(GL_ARRAY_BUFFER,triangles.nbytes, triangles, GL_STATIC_DRAW ) |
In here we need to enable the array and set up the data
1 2 3 |
position = glGetAttribLocation(shaderProgram, 'position') glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(position) |
This is our render method and i have commented the code
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def render(): global shaderProgram global VAO glClearColor(0, 0, 0, 1) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # active shader program glUseProgram(shaderProgram) # draw triangle glDrawArrays(GL_TRIANGLES, 0, 3) #delete shader program glUseProgram(0) glutSwapBuffers() |
Run the code and this will be the result for Python Modern Opengl Drawing Triangle
Subscribe and Get Free Video Courses & Articles in your Email