第一个 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()