环境搭建可参考https://www.jianshu.com/p/9527c0435e9c------之前在anaconda下搭建环境一直报错,后来使用pycharm并将解释器路径设置到anaconda下就好了
代码来源于https://www.jianshu.com/p/f1d326bce955
阅读了C++板的《OpenGL编程指南(原书第9版).pdf》后,根据理解写了一些代码注释,有错误请指正,谢谢
"""
glfw_Triangle02.py
Author: dalong10
Description: Draw a Triagle, learning OPENGL
"""
import glutils #Common OpenGL utilities,see glutils.py
import sys, random, math
import OpenGL
from OpenGL.GL import *
from OpenGL.GL.shaders import *
import numpy
import numpy as np
import glfw
'''做渲染的话,现代OpenGL需要我们至少设置一个顶点和一个片段着色器'''
#Vertex Shader顶点着色器,数据流入顶点着色器,将输入的顶点位置复制到顶点着色器的输出位置gl_Position
#vec4(position.x, position.y, position.z, 1.0);------XYZW,坐标及缩放比例
strVS = """
#version 330 core
layout(location = 0) in vec3 position;
void main(){
gl_Position = vec4(position.x, position.y, position.z, 1.0);
}
"""
#Fragment Shader片段着色器,片段着色器会输出color数据
#vec4(1.0, 0.0, 0.0, 1.0);------RGBA红绿蓝及透明度
strFS1 = """
#version 330 core
out vec4 color;
void main(){
color = vec4(1.0, 0.0, 0.0, 1.0);
}
"""
strFS2 = """
#version 330 core
out vec4 color;
void main(){
color = vec4(0.0, 1.0, 0.0, 1.0);
}
"""
class FirstTriangle:
def __init__(self, side1, side2, side3):
self.side1 = side1
self.side2 = side2
self.side3 = side3
# load shaders
if side3>0:
strFS=strFS1
else:
strFS=strFS2
#读取链接顶点着色器和片元着色器的源程序字串的函数,为着色器进入GPU的操作专门实现的函数
self.program = glutils.loadShaders(strVS, strFS)
glUseProgram(self.program)
s1 = side1/1.0
s2 = side2/1.0
s3 = side3/1.0
#三角形的三个点
vertices = [
s1, -0.5, 0,#xyzz
s2, -0.5, 0,#xyzz
s3, 0.5, 0 #xyzz
]
'''着色管线装配:将应用程序的数据和着色器程序的变量关联起来'''
# set up vertex array object (VAO)建立1个顶点数组对象,并将对象名返回,类似CC语言的指针变量
self.vao = glGenVertexArrays(1)
#绑定一个顶点数组对象,opengl内部会将其作为当前对象,后面的所有操作都作用于这个对象
glBindVertexArray(self.vao)
# set up VBOs
vertexData = numpy.array(vertices, numpy.float32)
#创建1个顶点缓存对象,并将对象名称返回 与顶点对象类似。缓存对象就是opengl服务端分配和管理的一块内存区域
self.vertexBuffer = glGenBuffers(1)
#绑定到opengl环境中,opengl有多种类型,因此绑定时需要指定缓存对象的类型GL_ARRAY_BUFFER
glBindBuffer(GL_ARRAY_BUFFER, self.vertexBuffer)
#分配缓存对象空间,大小为4*len(vertexData)字节,并将vertexData数据拷贝到opengl的缓存中
glBufferData(GL_ARRAY_BUFFER, 4*len(vertexData), vertexData,
GL_STATIC_DRAW)
'''着色管线装配:将应用程序与着色器之间,以及不同着色阶段之间的数据通道连接起来'''
#enable arrays启用索引为0的顶点属性数组
self.vertIndex = 0
glEnableVertexAttribArray(self.vertIndex)
# set buffers
glBindBuffer(GL_ARRAY_BUFFER, self.vertexBuffer)
#0:设置顶点着色器中变量position对应的值 3:每个顶点有xyz3个值
# GL_FLOAT:每个元素的数据类型 GL_FALSE:不需要进行归一化
#0:每两个数据之间的偏移量为0
#将着色器中的变量position与vertexBuffer关联起来
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, None)
# unbind VAO opengl不在使用之前绑定的顶点数组
glBindVertexArray(0)
'''执行渲染工作'''
def render(self):
# 指定program作为opengl的当前着色器程序
glUseProgram(self.program)
# bind VAO指定vao作为opengl的当前顶点对象
glBindVertexArray(self.vao)
# draw
glDrawArrays(GL_TRIANGLES, 0, 3)
# unbind VAO
glBindVertexArray(0)
if __name__ == '__main__':
import sys
import glfw
import OpenGL.GL as gl
def on_key(window, key, scancode, action, mods):
if key == glfw.KEY_ESCAPE and action == glfw.PRESS:
glfw.set_window_should_close(window,1)
# Initialize the library初始化GLFW库
if not glfw.init():
sys.exit()
# Create a windowed mode window and its OpenGL context设置程序所使用的窗口类型及窗口大小,也可以先查询显示器的尺寸再设置
window = glfw.create_window(640, 480, "glfw_Triangle02", None, None)
if not window:
glfw.terminate()
sys.exit()
# Make the window's context current把创建的window窗口作为OPENGL显示的窗口
glfw.make_context_current(window)
# Install a key handler
glfw.set_key_callback(window, on_key)
# Loop until the user closes the window
while not glfw.window_should_close(window):
# Render here
width, height = glfw.get_framebuffer_size(window)
ratio = width / float(height)
gl.glViewport(0, 0, width, height)
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
gl.glClearColor(0.0,0.0,0.0,0.0)
firstTriangle0 = FirstTriangle(-0.9,-0.0,-0.45)
firstTriangle1 = FirstTriangle(0,0.9,0.45)
# render
firstTriangle0.render()
firstTriangle1.render()
# Swap front and back buffers
glfw.swap_buffers(window)
# Poll for and process events
glfw.poll_events()
glfw.terminate()