第一个 OGL 4.0 GLSL 着色器程序
一个简单的 OGL 4.0 GLSL 着色器程序,具有顶点位置和颜色属性。该程序使用 phyton 脚本执行。要运行该脚本,必须安装 PyOpenGL。
着色器程序至少包含顶点着色器和碎片着色器(计算机着色器除外)。第一个着色器阶段是顶点着色器,最后一个着色器阶段是片段着色器(在它们之间,可选的其他阶段是可能的,这里不再进一步描述)。
顶点着色器
first.vet
顶点着色器处理绘图命令指定的顶点和关联属性。顶点着色器处理来自输入流的顶点,并可以以任何所需的方式对其进行操作。顶点着色器从输入流接收单个顶点,并为输出顶点流生成一个单独的顶点。
在我们的示例中,我们绘制一个三角形,因此顶点着色器执行 3 次,对于三角形的每个角点执行一次。在这种情况下,顶点着色器的输入是顶点位置 in vec3 inPos
和颜色属性 in vec3 inCol
。颜色属性将传递到下一个着色器阶段(out vec3 vertCol
)。
#version 400
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inCol;
out vec3 vertCol;
void main()
{
vertCol = inCol;
gl_Position = vec4( inPos, 1.0 );
}
片段着色器
first.frag
在此示例中,片段着色器紧跟在顶点着色器之后。对于每个片段,在每个面内插入顶点位置和属性。片段着色器对整个三角形上的每个片段执行一次,并从片段着色器接收颜色属性。由于绘制了三角形,因此基于绘制的三角形,根据片段的重心坐标对颜色属性进行插值。
#version 400
in vec3 vertCol;
out vec4 fragColor;
void main()
{
fragColor = vec4( vertCol, 1.0 );
}
Phyton 剧本
python 脚本只是用于编译,链接和执行着色器程序以及绘制几何体。它可以用 C 或其他任何东西重写。本文档中不应该引起最大的注意。
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from sys import *
from array import array
# draw event
def OnDraw():
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
glUseProgram( shaderProgram )
glBindVertexArray( vaObj )
glDrawArrays( GL_TRIANGLES, 0, 3 )
glutSwapBuffers()
# read vertex shader program
with open( 'first.vert', 'r' ) as vertFile:
vertCode = vertFile.read()
print( '\nvertex shader code:' )
print( vertCode )
# read fragment shader program
with open( 'first.frag', 'r' ) as fragFile:
fragCode = fragFile.read()
print( '\nfragment shader code:' )
print( fragCode )
# initialize glut
glutInit()
# create window
wndW = 800
wndH = 600
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)
glutInitWindowPosition(0, 0)
glutInitWindowSize(wndW, wndH)
wndID = glutCreateWindow(b'OGL window')
glutDisplayFunc(OnDraw)
glutIdleFunc(OnDraw)
# define triangle data
posData = [ -0.636, -0.45, 0.0, 0.636, -0.45, 0.0, 0.0, 0.9, 0.0 ]
colData = [ 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0 ]
posAr = array( "f", posData )
colAr = array( "f", colData )
# create buffers
posBuffer = glGenBuffers(1)
glBindBuffer( GL_ARRAY_BUFFER, posBuffer )
glBufferData( GL_ARRAY_BUFFER, posAr.tostring(), GL_STATIC_DRAW )
colBuffer = glGenBuffers(1)
glBindBuffer( GL_ARRAY_BUFFER, colBuffer )
glBufferData( GL_ARRAY_BUFFER, colAr.tostring(), GL_STATIC_DRAW )
# create vertex array opject
vaObj = glGenVertexArrays( 1 )
glBindVertexArray( vaObj )
glEnableVertexAttribArray( 0 )
glEnableVertexAttribArray( 1 )
glBindBuffer( GL_ARRAY_BUFFER, posBuffer )
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, None )
glBindBuffer( GL_ARRAY_BUFFER, colBuffer )
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 0, None )
# compile vertex shader
vertShader = glCreateShader( GL_VERTEX_SHADER )
glShaderSource( vertShader, vertCode )
glCompileShader( vertShader )
result = glGetShaderiv( vertShader, GL_COMPILE_STATUS )
if not (result):
print( glGetShaderInfoLog( vertShader ) )
sys.exit()
# compile fragment shader
fragShader = glCreateShader( GL_FRAGMENT_SHADER )
glShaderSource( fragShader, fragCode )
glCompileShader( fragShader )
result = glGetShaderiv( fragShader, GL_COMPILE_STATUS )
if not (result):
print( glGetShaderInfoLog( fragShader ) )
sys.exit()
# link shader program
shaderProgram = glCreateProgram()
glAttachShader( shaderProgram, vertShader )
glAttachShader( shaderProgram, fragShader )
glLinkProgram( shaderProgram )
result = glGetProgramiv( shaderProgram, GL_LINK_STATUS )
if not (result):
print( 'link error:' )
print( glGetProgramInfoLog( shaderProgram ) )
sys.exit()
# start main loop
glutMainLoop()