Skip to content
Back to top
View this page

# One familiar triangle

As with any graphics library guide, we also have a guide on how to draw a triangle. Below is a slightly modified line drawing code from the previous tutorial. The following code draws one triangle:

Entire source

     1import moderngl
     2import numpy as np
     3
     4from PIL import Image
     5
     6ctx = moderngl.create_context(standalone=True)
     7
     8prog = ctx.program(
     9    vertex_shader="""
    10        #version 330
    11
    12        in vec2 in_vert;
    13        in vec3 in_color;
    14
    15        out vec3 v_color;
    16
    17        void main() {
    18            v_color = in_color;
    19            gl_Position = vec4(in_vert, 0.0, 1.0);
    20        }
    21    """,
    22    fragment_shader="""
    23        #version 330
    24
    25        in vec3 v_color;
    26
    27        out vec3 f_color;
    28
    29        void main() {
    30            f_color = v_color;
    31        }
    32    """,
    33)
    34
    35vertices = np.asarray([
    36
    37    -0.75, -0.75,  1, 0, 0,
    38    0.75, -0.75,  0, 1, 0,
    39    0.0, 0.649,  0, 0, 1
    40
    41], dtype='f4')
    42
    43vbo = ctx.buffer(vertices.tobytes())
    44vao = ctx.vertex_array(prog, vbo, "in_vert", "in_color")
    45
    46fbo = ctx.framebuffer(
    47    color_attachments=[ctx.texture((512, 512), 3)]
    48)
    49fbo.use()
    50fbo.clear(0.0, 0.0, 0.0, 1.0)
    51vao.render()  # "mode" is moderngl.TRIANGLES by default
    52
    53Image.frombytes(
    54    "RGB", fbo.size, fbo.color_attachments[0].read(),
    55    "raw", "RGB", 0, -1
    56).show()

When you run the code you will see this:

Triangle

As you may have noticed, we only specified three colors for each vertex, but OpenGL interpolates our triangle and we see a soft transition of colors.

At this point you can try out the fragment shader, for example, let’s draw a lighting effect:

Fragment shader

    #version 330

    in vec3 v_color;

    out vec3 f_color;

    void main() {
        vec2 pixel_coord = (gl_FragCoord.xy-256.0)/256.0;
        f_color = v_color*(1.0-length(pixel_coord));
    }

Lighted triangle

Shaders are not very fond of branching algorithms and operations such as `if (condition) {action} else {action}`. It is recommended to use formulas more often.