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