Skip to content

Commit f6d5642

Browse files
committed
started texture and rectangle glwidgets
1 parent 105fa7f commit f6d5642

File tree

2 files changed

+248
-0
lines changed

2 files changed

+248
-0
lines changed

tutorials/02-rectangle/glrectangle.py

Whitespace-only changes.

tutorials/03-texture/gltexture.py

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
# author: Kaan Eraslan
2+
3+
import numpy as np
4+
import os
5+
import sys
6+
import ctypes
7+
8+
from PySide2 import QtWidgets, QtCore, QtGui
9+
from PySide2.QtGui import QVector3D
10+
from PySide2.QtGui import QOpenGLVertexArrayObject
11+
from PySide2.QtGui import QOpenGLBuffer
12+
from PySide2.QtGui import QOpenGLShaderProgram
13+
from PySide2.QtGui import QOpenGLShader
14+
from PySide2.QtGui import QOpenGLContext
15+
from PySide2.QtGui import QMatrix4x4
16+
from PySide2.QtGui import QVector4D
17+
from PySide2.QtGui import QColor
18+
19+
from PySide2.QtWidgets import QApplication
20+
from PySide2.QtWidgets import QMessageBox
21+
from PySide2.QtWidgets import QOpenGLWidget
22+
23+
from PySide2.QtCore import QCoreApplication
24+
25+
from PySide2.shiboken2 import VoidPtr
26+
27+
28+
try:
29+
from OpenGL import GL as pygl
30+
except ImportError:
31+
app = QApplication(sys.argv)
32+
messageBox = QMessageBox(QMessageBox.Critical, "OpenGL hellogl",
33+
"PyOpenGL must be installed to run this example.",
34+
QMessageBox.Close)
35+
messageBox.setDetailedText(
36+
"Run:\npip install PyOpenGL PyOpenGL_accelerate")
37+
messageBox.exec_()
38+
sys.exit(1)
39+
40+
41+
class TextureGL(QOpenGLWidget):
42+
"Texture loading opengl widget"
43+
44+
def __init__(self, parent=None):
45+
""
46+
QOpenGLWidget.__init__(self, parent)
47+
48+
# media and project structure
49+
projectdir = os.getcwd()
50+
projectdir = os.path.join(projectdir, "qtopengl")
51+
assetsdir = os.path.join(projectdir, "assets")
52+
self.imagesdir = os.path.join(assetsdir, 'images')
53+
self.shadersdir = os.path.join(assetsdir, 'shaders')
54+
self.availableShaders = [
55+
"basic_color",
56+
"simpleLamp",
57+
"triangle",
58+
"portableTriangle",
59+
"portableTexture"
60+
]
61+
self.shaders = {
62+
name: {"vertex": os.path.join(self.shadersdir, name + ".vert"),
63+
"fragment": os.path.join(self.shadersdir, name + ".vert")}
64+
for name in self.availableShaders
65+
}
66+
67+
self.core = "--coreprofile" in QCoreApplication.arguments()
68+
69+
# opengl data related
70+
self.context = QOpenGLContext()
71+
self.vao = QOpenGLVertexArrayObject()
72+
self.vbo = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)
73+
self.ebo = QOpenGLBuffer(QOpenGLBuffer.IndexBuffer)
74+
self.program = QOpenGLShaderProgram()
75+
76+
# shader uniform attribute related
77+
self.projectionMatrix = QMatrix4x4()
78+
self.cameraMatrix = QMatrix4x4()
79+
self.worldMatrix = QMatrix4x4()
80+
81+
# locations of the attributes and uniforms
82+
self.projectionMatrixLoc = 0
83+
self.cameraMatrixLoc = 0
84+
self.normalMatrixLoc = 0
85+
self.lightPositionLoc = 0
86+
87+
# some vertex data for corners of rectangle that would contain texture
88+
89+
self.vertexData = np.array([ # viewport position xyz | colors xyz | texture coordinates xy
90+
0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, # top right
91+
0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, # bottom right
92+
-0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, # bottom let
93+
-0.5, 0.5, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0 # top let
94+
],
95+
dtype=ctypes.c_float
96+
)
97+
98+
def loadShader(self,
99+
shaderName: str,
100+
shaderType: str):
101+
"Load shader"
102+
shader = self.shaders[shaderName]
103+
shaderpath = shader[shaderType]
104+
if shaderType == "vertex":
105+
shader = QOpenGLShader(QOpenGLShader.Vertex)
106+
else:
107+
shader = QOpenGLShader(QOpenGLShader.Fragment)
108+
#
109+
isCompiled = shader.compileSourceFile(shaderpath)
110+
111+
if isCompiled is False:
112+
print(shader.log())
113+
raise ValueError(
114+
"{0} shader {1} in {2} is not compiled".format(
115+
shaderType, shaderName, shaderpath
116+
)
117+
)
118+
return shader
119+
120+
def loadVertexShader(self, shaderName: str):
121+
"load vertex shader"
122+
return self.loadShader(shaderName, "vertex")
123+
124+
def loadFragmentShader(self, shaderName: str):
125+
"load fragment shader"
126+
return self.loadShader(shaderName, "fragment")
127+
128+
def getGlInfo(self):
129+
"Get opengl info"
130+
info = """
131+
Vendor: {0}
132+
Renderer: {1}
133+
OpenGL Version: {2}
134+
Shader Version: {3}
135+
""".format(
136+
pygl.glGetString(pygl.GL_VENDOR),
137+
pygl.glGetString(pygl.GL_RENDERER),
138+
pygl.glGetString(pygl.GL_VERSION),
139+
pygl.glGetString(pygl.GL_SHADING_LANGUAGE_VERSION)
140+
)
141+
return info
142+
143+
def initializeGL(self):
144+
print('gl initial')
145+
print(self.getGlInfo())
146+
# create context and make it current
147+
self.context.create()
148+
# surface = QSurface(QSurface.OpenGLSurface)
149+
# self.context.makeCurrent(surface)
150+
self.context.aboutToBeDestroyed.connect(self.cleanUpGl)
151+
funcs = self.context.functions()
152+
funcs.initializeOpenGLFunctions()
153+
funcs.glClearColor(1, 1, 1, 1)
154+
155+
# deal with shaders
156+
shaderName = "portableTriangle"
157+
vshader = self.loadVertexShader(shaderName)
158+
fshader = self.loadFragmentShader(shaderName)
159+
160+
# creating shader program
161+
self.program = QOpenGLShaderProgram(self.context)
162+
self.program.addShader(vshader) # adding vertex shader
163+
self.program.addShader(fshader) # adding fragment shader
164+
165+
# bind attribute to a location
166+
attrLocations = {"aPos": 0,
167+
"aColor": 1,
168+
"aTexCoord": 2}
169+
self.bindAttributes2ShaderProgram(attrLocations)
170+
171+
# link shader program
172+
isLinked = self.program.link()
173+
print("shader program is linked: ", isLinked)
174+
175+
# bind the program
176+
self.program.bind()
177+
178+
# rectangle indices
179+
indices = np.array([0, 1, 3, 1, 2, 3], dtype=ctypes.c_float)
180+
181+
# create vao, vbo and ebo
182+
# vao
183+
isVao = self.vao.create()
184+
vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao)
185+
186+
# vbo
187+
isVbo = self.vbo.create()
188+
isVboBound = self.vbo.bind()
189+
190+
# ebo
191+
isEbo = self.ebo.create()
192+
isEboBound = self.ebo.bind()
193+
194+
# check if vao, vbo, ebo are created
195+
print('vao created: ', isVao)
196+
print('vbo created: ', isVbo)
197+
print('ebo created: ', isEbo)
198+
199+
# check if they are bound
200+
print('vbo bound: ', isVboBound)
201+
print('ebo bound: ', isEboBound)
202+
203+
floatSize = ctypes.sizeof(ctypes.c_float)
204+
nullptr = VoidPtr(0)
205+
206+
# allocate space on vbo
207+
self.vbo.allocate(self.vertexData.tobytes(), # data,
208+
floatSize * self.vertexData.size)
209+
210+
# allocate space on ebo
211+
self.ebo.allocate(indices.tobytes(), indices.size * floatSize)
212+
213+
# let's specify the attributes and point them
214+
215+
# position attribute
216+
funcs.glEnableVertexAttribArray(attrLocations['aPos'])
217+
funcs.glVertexAttribPointer(attrLocations['aPos'], # location
218+
3, # size of attribute 3 for vec3
219+
int(pygl.GL_FLOAT),
220+
int(pygl.GL_FALSE),
221+
8 * floatSize,
222+
0)
223+
# color attribute
224+
funcs.glEnableVertexAttribArray(attrLocations['aColor'])
225+
funcs.glVertexAttribPointer(attrLocations['aColor'], # location
226+
3, # size of attribute 3 for vec3
227+
int(pygl.GL_FLOAT),
228+
int(pygl.GL_FALSE),
229+
8 * floatSize,
230+
3 * floatSize)
231+
# texture coordinate attribute
232+
funcs.glEnableVertexAttribArray(attrLocations['aTexCoord'])
233+
funcs.glVertexAttribPointer(attrLocations['aTexCoord'], # location
234+
2, # size of attribute 3 for vec2
235+
int(pygl.GL_FLOAT),
236+
int(pygl.GL_FALSE),
237+
8 * floatSize, # offset
238+
6 * floatSize # stride
239+
)
240+
241+
242+
243+
244+
245+
def bindAttributes2ShaderProgram(self, attrLocations: dict):
246+
"Bind attributes to shader program"
247+
for attrName, location in attrLocations.items():
248+
self.program.bindAttributeLocation(attrName, location)

0 commit comments

Comments
 (0)