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