In this Python Modern Opengl article we are going to talk about Drawing Triangle in Python OpenGL. also i want to show you Drawing of Triangle where we have vertex shaders and fragment shaders that runs on GPU (Graphic Process Unit).
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.
Python Modern Opengl Drawing Triangle
Let’s create our example, so now this is the complete code for 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 101 102 103 104 105 106 107 108 109 110 |
import glfw from OpenGL.GL import * from OpenGL.GL import shaders import numpy as np # Vertex shader source code VERTEX_SHADER = """ #version 330 in vec4 position; void main() { gl_Position = position; } """ # Fragment shader source code FRAGMENT_SHADER = """ #version 330 void main() { gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f); } """ shaderProgram = None def initialize(): """ Initialize the OpenGL environment. Compile shaders, set up vertex buffer objects (VBOs), and configure vertex attributes. """ global VERTEX_SHADER global FRAGMENT_SHADER global shaderProgram # Compile vertex and fragment shaders vertex_shader = shaders.compileShader(VERTEX_SHADER, GL_VERTEX_SHADER) fragment_shader = shaders.compileShader(FRAGMENT_SHADER, GL_FRAGMENT_SHADER) # Create shader program shaderProgram = shaders.compileProgram(vertex_shader, fragment_shader) # Define vertex data for a triangle 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) # Create vertex buffer object (VBO) and bind data VBO = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, VBO) glBufferData(GL_ARRAY_BUFFER, triangles.nbytes, triangles, GL_STATIC_DRAW) # Configure vertex attributes position = glGetAttribLocation(shaderProgram, 'position') glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(position) def render(window): """ Render the scene. Clear the framebuffer, use the shader program, draw the triangle, and swap buffers. """ global shaderProgram glClearColor(0, 0, 0, 1) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Use shader program glUseProgram(shaderProgram) # Draw the triangle glDrawArrays(GL_TRIANGLES, 0, 3) # Unbind shader program glUseProgram(0) # Swap buffers glfw.swap_buffers(window) def main(): """ Main function to create the window, initialize OpenGL, and run the rendering loop. """ if not glfw.init(): return -1 # Create a window window = glfw.create_window(640, 480, "Codeloop.org - Modern OpenGL", None, None) if not window: glfw.terminate() return -1 # Set the current OpenGL context to the window glfw.make_context_current(window) # Initialize OpenGL environment initialize() # Rendering loop while not glfw.window_should_close(window): render(window) glfw.poll_events() # Terminate GLFW glfw.terminate() 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 this article.
Subscribe and Get Free Video Courses & Articles in your Email