Quick Start Guide

The most simple pygame_shaders project is as follows:

import pygame
import pygame_shaders

pygame.init()

clock = pygame.time.Clock()

#Create an opengl pygame Surface, this will act as our opengl context.
screen = pygame.display.set_mode((600, 600), pygame.OPENGL | pygame.DOUBLEBUF)

#This is our main display we will do all of our standard pygame rendering on.
display = pygame.Surface((600, 600))

#The shader we are using to communicate with the opengl context (standard pygame drawing functionality does not work on opengl displays)
screen_shader = pygame_shaders.DefaultScreenShader(display) # <- Here we supply our default display, it's this display which will be displayed onto the opengl context via the screen_shader

while True:
    #Fill the display with white
    display.fill((255, 255, 255))

    #Standard pygame event stuff
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()

    #Render a rect onto the display using the standard pygame method for drawing rects.
    pygame.draw.rect(display, (255, 0, 0), (200, 200, 20, 20))

    #Render the contents of "display" (main surface) onto the opengl screen.
    screen_shader.render()

    #Update the opengl context
    pygame.display.flip()
    clock.tick(60)

In this example, we are simpily setting up a DefaultScreenShader, this will be responsible for taking the contents of the main pygame surface, which is where we will doing all our regular pygame drawing stuff; and rendering it onto the OpenGL context. In this example we don’t actually do any actual shader rendering, just taking the Surface and putting it directly onto the OpenGL context. In order to do that, lets create a new shader:

import pygame
import pygame_shaders

pygame.init()

clock = pygame.time.Clock()

#Create an opengl pygame Surface, this will act as our opengl context.
screen = pygame.display.set_mode((600, 600), pygame.OPENGL | pygame.DOUBLEBUF)

#This is our main display we will do all of our standard pygame rendering on.
display = pygame.Surface((600, 600))

#The shader we are using to communicate with the opengl context (standard pygame drawing functionality does not work on opengl displays)
screen_shader = pygame_shaders.DefaultScreenShader(display) # <- Here we supply our default display, it's this display which will be displayed onto the opengl context via the screen_shader

#This is our shader object which we can use to render the given shaders onto the screen in various ways.
shader = pygame_shaders.Shader(pygame_shaders.DEFAULT_VERTEX_SHADER, "fragment.glsl", screen) #<- Because we plan on using this shader for direct rendering (we supply the surface on which we plan to do said direct rendering in this case, screen)

while True:
    #Fill the display with white
    display.fill((255, 255, 255))

    #Standard pygame event stuff
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()

    #Render a rect onto the display using the standard pygame method for drawing rects.
    pygame.draw.rect(display, (255, 0, 0), (200, 200, 20, 20))

    #Render the contents of "display" (main surface) onto the opengl screen.
    screen_shader.render()

    #Render the shader directly onto the display.
    shader.render_direct(pygame.Rect(0, 0, 100, 100))

    #Update the opengl context
    pygame.display.flip()
    clock.tick(60)

Here we add onto the previous example with a new pygame_shaders.Shader object which we will use by drawing the result of the shader directly onto the OpenGL context.

fragment.glsl:

#version 330

//Provided by the pygame_shaders library. Do not modify...
in vec3 fragmentColor;
in vec2 fragmentTexCoord;
uniform sampler2D imageTexture;

//Color output of the shader
out vec4 color;

//Note: Add your custom uniforms and variables here.

void main() {
    color = vec4(fragmentTexCoord.x, fragmentTexCoord.y, 0.0, 1.0);
}

Notice in the example the usage of .render_direct() this will render the outputted shader directly onto the OpenGL context at the position specified via the pygame.Rect object. An alternative method is to produce a pygame.Surface object:

import pygame
import pygame_shaders

pygame.init()

clock = pygame.time.Clock()

#Create an opengl pygame Surface, this will act as our opengl context.
screen = pygame.display.set_mode((600, 600), pygame.OPENGL | pygame.DOUBLEBUF)

#This is our main display we will do all of our standard pygame rendering on.
display = pygame.Surface((600, 600))

#The shader we are using to communicate with the opengl context (standard pygame drawing functionality does not work on opengl displays)
screen_shader = pygame_shaders.DefaultScreenShader(display) # <- Here we supply our default display, it's this display which will be displayed onto the opengl context via the screen_shader

shader_res = pygame.Surface((200, 200))
#This is our shader object which we can use to render the given shaders onto the screen in various ways.
shader = pygame_shaders.Shader(pygame_shaders.DEFAULT_VERTEX_SHADER, "fragment.glsl", shader_res)

while True:
    #Fill the display with white
    display.fill((255, 255, 255))

    #Standard pygame event stuff
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()

    #Render a rect onto the display using the standard pygame method for drawing rects.
    pygame.draw.rect(display, (255, 0, 0), (200, 200, 20, 20))

    shader_res = shader.render()
    display.blit(shader_res, (0, 0))

    #Render the contents of "display" (main surface) onto the opengl screen.
    screen_shader.render()

    #Update the opengl context
    pygame.display.flip()
    clock.tick(60)