PyOpenGL с шейдерами
- четверг, 1 января 2015 г. в 02:10:26
from OpenGL.GL import *
from OpenGL.GLUT import *
from random import random
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)
glutInitWindowSize(300, 300)
glutInitWindowPosition(50, 50)
glutInit(sys.argv)
glutCreateWindow(b"Shaders!")
glutDisplayFunc(draw)
glutIdleFunc(draw)
glutSpecialFunc(specialkeys)
glClearColor(0.2, 0.2, 0.2, 1)
# Процедура подготовки шейдера (тип шейдера, текст шейдера)
def create_shader(shader_type, source):
# Создаем пустой объект шейдера
shader = glCreateShader(shader_type)
# Привязываем текст шейдера к пустому объекту шейдера
glShaderSource(shader, source)
# Компилируем шейдер
glCompileShader(shader)
# Возвращаем созданный шейдер
return shader
# Положение вершин не меняется
# Цвет вершины - такой же как и в массиве цветов
vertex = create_shader(GL_VERTEX_SHADER, """
varying vec4 vertex_color;
void main(){
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vertex_color = gl_Color;
}""")
# Определяет цвет каждого фрагмента как "смешанный" цвет его вершин
fragment = create_shader(GL_FRAGMENT_SHADER, """
varying vec4 vertex_color;
void main() {
gl_FragColor = vertex_color;
}""")
program = glCreateProgram()
glAttachShader(program, vertex)
glAttachShader(program, fragment)
glLinkProgram(program)
glUseProgram(program)
pointdata = [[0, 0.5, 0], [-0.5, -0.5, 0], [0.5, -0.5, 0]]
pointcolor = [[1, 1, 0], [0, 1, 1], [1, 0, 1]]
glutMainLoop()
# Процедура обработки специальных клавиш
def specialkeys(key, x, y):
# Сообщаем о необходимости использовать глобального массива pointcolor
global pointcolor
# Обработчики специальных клавиш
if key == GLUT_KEY_UP: # Клавиша вверх
glRotatef(5, 1, 0, 0) # Вращаем на 5 градусов по оси X
if key == GLUT_KEY_DOWN: # Клавиша вниз
glRotatef(-5, 1, 0, 0) # Вращаем на -5 градусов по оси X
if key == GLUT_KEY_LEFT: # Клавиша влево
glRotatef(5, 0, 1, 0) # Вращаем на 5 градусов по оси Y
if key == GLUT_KEY_RIGHT: # Клавиша вправо
glRotatef(-5, 0, 1, 0) # Вращаем на -5 градусов по оси Y
if key == GLUT_KEY_END: # Клавиша END
# Заполняем массив pointcolor случайными числами в диапазоне 0-1
pointcolor = [[random(), random(), random()], [random(), random(), random()], [random(), random(), random()]]
glClear(GL_COLOR_BUFFER_BIT)
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_COLOR_ARRAY)
glVertexPointer(3, GL_FLOAT, 0, pointdata)
glColorPointer(3, GL_FLOAT, 0, pointcolor)
glDrawArrays(GL_TRIANGLES, 0, 3)
glDisableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_COLOR_ARRAY)
glutSwapBuffers()
# -*- coding: utf-8 -*-
# Импортируем все необходимые библиотеки:
from OpenGL.GL import *
from OpenGL.GLUT import *
#import sys
# Из модуля random импортируем одноименную функцию random
from random import random
# объявляем массив pointcolor глобальным (будет доступен во всей программе)
global pointcolor
# Процедура обработки специальных клавиш
def specialkeys(key, x, y):
# Сообщаем о необходимости использовать глобального массива pointcolor
global pointcolor
# Обработчики специальных клавиш
if key == GLUT_KEY_UP: # Клавиша вверх
glRotatef(5, 1, 0, 0) # Вращаем на 5 градусов по оси X
if key == GLUT_KEY_DOWN: # Клавиша вниз
glRotatef(-5, 1, 0, 0) # Вращаем на -5 градусов по оси X
if key == GLUT_KEY_LEFT: # Клавиша влево
glRotatef(5, 0, 1, 0) # Вращаем на 5 градусов по оси Y
if key == GLUT_KEY_RIGHT: # Клавиша вправо
glRotatef(-5, 0, 1, 0) # Вращаем на -5 градусов по оси Y
if key == GLUT_KEY_END: # Клавиша END
# Заполняем массив pointcolor случайными числами в диапазоне 0-1
pointcolor = [[random(), random(), random()], [random(), random(), random()], [random(), random(), random()]]
# Процедура подготовки шейдера (тип шейдера, текст шейдера)
def create_shader(shader_type, source):
# Создаем пустой объект шейдера
shader = glCreateShader(shader_type)
# Привязываем текст шейдера к пустому объекту шейдера
glShaderSource(shader, source)
# Компилируем шейдер
glCompileShader(shader)
# Возвращаем созданный шейдер
return shader
# Процедура перерисовки
def draw():
glClear(GL_COLOR_BUFFER_BIT) # Очищаем экран и заливаем серым цветом
glEnableClientState(GL_VERTEX_ARRAY) # Включаем использование массива вершин
glEnableClientState(GL_COLOR_ARRAY) # Включаем использование массива цветов
# Указываем, где взять массив верши:
# Первый параметр - сколько используется координат на одну вершину
# Второй параметр - определяем тип данных для каждой координаты вершины
# Третий парметр - определяет смещение между вершинами в массиве
# Если вершины идут одна за другой, то смещение 0
# Четвертый параметр - указатель на первую координату первой вершины в массиве
glVertexPointer(3, GL_FLOAT, 0, pointdata)
# Указываем, где взять массив цветов:
# Параметры аналогичны, но указывается массив цветов
glColorPointer(3, GL_FLOAT, 0, pointcolor)
# Рисуем данные массивов за один проход:
# Первый параметр - какой тип примитивов использовать (треугольники, точки, линии и др.)
# Второй параметр - начальный индекс в указанных массивах
# Третий параметр - количество рисуемых объектов (в нашем случае это 3 вершины - 9 координат)
glDrawArrays(GL_TRIANGLES, 0, 3)
glDisableClientState(GL_VERTEX_ARRAY) # Отключаем использование массива вершин
glDisableClientState(GL_COLOR_ARRAY) # Отключаем использование массива цветов
glutSwapBuffers() # Выводим все нарисованное в памяти на экран
# Здесь начинется выполнение программы
# Использовать двойную буферезацию и цвета в формате RGB (Красный Синий Зеленый)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)
# Указываем начальный размер окна (ширина, высота)
glutInitWindowSize(300, 300)
# Указываем начальное
# положение окна относительно левого верхнего угла экрана
glutInitWindowPosition(50, 50)
# Инициализация OpenGl
glutInit(sys.argv)
# Создаем окно с заголовком "Shaders!"
glutCreateWindow(b"Shaders!")
# Определяем процедуру, отвечающую за перерисовку
glutDisplayFunc(draw)
# Определяем процедуру, выполняющуюся при "простое" программы
glutIdleFunc(draw)
# Определяем процедуру, отвечающую за обработку клавиш
glutSpecialFunc(specialkeys)
# Задаем серый цвет для очистки экрана
glClearColor(0.2, 0.2, 0.2, 1)
# Создаем вершинный шейдер:
# Положение вершин не меняется
# Цвет вершины - такой же как и в массиве цветов
vertex = create_shader(GL_VERTEX_SHADER, """
varying vec4 vertex_color;
void main(){
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vertex_color = gl_Color;
}""")
# Создаем фрагментный шейдер:
# Определяет цвет каждого фрагмента как "смешанный" цвет его вершин
fragment = create_shader(GL_FRAGMENT_SHADER, """
varying vec4 vertex_color;
void main() {
gl_FragColor = vertex_color;
}""")
# Создаем пустой объект шейдерной программы
program = glCreateProgram()
# Приcоединяем вершинный шейдер к программе
glAttachShader(program, vertex)
# Присоединяем фрагментный шейдер к программе
glAttachShader(program, fragment)
# "Собираем" шейдерную программу
glLinkProgram(program)
# Сообщаем OpenGL о необходимости использовать данную шейдерну программу при отрисовке объектов
glUseProgram(program)
# Определяем массив вершин (три вершины по три координаты)
pointdata = [[0, 0.5, 0], [-0.5, -0.5, 0], [0.5, -0.5, 0]]
# Определяем массив цветов (по одному цвету для каждой вершины)
pointcolor = [[1, 1, 0], [0, 1, 1], [1, 0, 1]]
# Запускаем основной цикл
glutMainLoop()
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.