Issue
Title says it all. There are not many tutorials out there for this kind of thing. Can someone with some experience help me out.
I have tried a number of things. Interestingly I have been able to get OpenTK (C#) and OpenGL (C++) versions of this working, albeit outside of the Qt world (My boss wants this in Python). I know I am close but I just cant see the last issue/s.
I am only seeing a black window.
Code:
Python:
import sys
import numpy as np
import OpenGL.GL as gl
import array
from PyQt5 import QtGui
from PyQt5.QtCore import QSize, QPoint, Qt, pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QOpenGLWidget, QHBoxLayout
#from framework import *
vertexDim = 3
nVertices = 3
cubemap = np.array([-1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0], dtype='float32')
class App(QWidget):
def __init__(self):
super(App, self).__init__()
self.glWidget = GLWidget()
mainLayout = QHBoxLayout()
mainLayout.addWidget(self.glWidget)
self.setLayout(mainLayout)
self.title = 'OpenGL Window - PyQt5'
self.left = 20
self.top = 30
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
#self.setGeometry(self.left, self.top, self.width, self.height)
class GLWidget(QOpenGLWidget):
clicked = pyqtSignal()
def __init__(self, parent=None):
super(GLWidget, self).__init__(parent)
self.profile = QtGui.QOpenGLVersionProfile()
self.profile.setVersion( 2, 1 )
self.xRot = 0
self.yRot = 0
self.zRot = 0
# self.program = None
self.lastPos = QPoint()
def getOpenglInfo(self):
info = """
Vendor: {0}
Renderer: {1}
OpenGL Version: {2}
Shader Version: {3}
""".format(
gl.glGetString(gl.GL_VENDOR),
gl.glGetString(gl.GL_RENDERER),
gl.glGetString(gl.GL_VERSION),
gl.glGetString(gl.GL_SHADING_LANGUAGE_VERSION)
)
return info
def rotateBy(self, xAngle, yAngle, zAngle):
print(str(xAngle) + ", " + str(yAngle) + ", " + str(zAngle))
self.xRot += xAngle
self.yRot += yAngle
self.zRot += zAngle
self.update()
def minimumSizeHint(self):
return QSize(600, 400)
def initializeGL(self):
print(self.getOpenglInfo())
self.gl = self.context().versionFunctions( self.profile )
# Vertex Array Object
self.vao = QtGui.QOpenGLVertexArrayObject( self )
self.vao.create()
# Set up and link shaders
self.program = QtGui.QOpenGLShaderProgram( self )
self.program.addShaderFromSourceFile( QtGui.QOpenGLShader.Vertex, 'shader.vert' )
self.program.addShaderFromSourceFile( QtGui.QOpenGLShader.Fragment, 'shader.frag' )
self.program.link()
self.vao.bind()
self.vertices = np.array([ 0.0, 0.0, 0.0, # x, y, z
1.0, 0.0, 0.0,
0.5, 1.0, 0.0 ], dtype='float32')
self.vbo_vertices = self.setVertexBuffer( cubemap, 3, self.program, "position" )
self.colors = np.array([ 1.0, 0.0, 0.0, 1.0, # r, g, b, a
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0 ], dtype='float32')
self.vbo_colors = self.setVertexBuffer( self.colors, 4, self.program, "texture" )
self.vao.release()
self.program.bind()
self.program.release()
def resizeGL(self, width, height):
gl.glViewport(0, 0, width, height)
def setVertexBuffer( self, data_array, dim_vertex, program, shader_str ):
vbo = QtGui.QOpenGLBuffer( QtGui.QOpenGLBuffer.VertexBuffer )
vbo.create()
vbo.bind()
vertices = np.array( data_array, np.float32 )
vbo.allocate( vertices, vertices.shape[0] * vertices.itemsize )
attr_loc = program.attributeLocation( shader_str )
program.enableAttributeArray( attr_loc )
program.setAttributeBuffer( attr_loc, gl.GL_FLOAT, 0, dim_vertex )
vbo.release()
return vbo
def paintGL(self):
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
gl.glClearColor(0.0, 0.0, 0.2, 0.0)
self.program.bind()
self.texture = QtGui.QOpenGLTexture(QtGui.QOpenGLTexture.TargetCubeMap)
self.texture.create()
print(self.texture.isCreated())
img = QtGui.QImage("C:\\Users\\path\\to\\image.jpg")
self.texture.bind()
self.texture.setSize(1024, 1024)
self.texture.setFormat(QtGui.QOpenGLTexture.RGBAFormat)
self.texture.allocateStorage()
self.texture.setData(0, 0, QtGui.QOpenGLTexture.CubeMapNegativeX, QtGui.QOpenGLTexture.RGBA, QtGui.QOpenGLTexture.UInt16, img.bits())
self.texture.setData(0, 0, QtGui.QOpenGLTexture.CubeMapNegativeY, QtGui.QOpenGLTexture.RGBA, QtGui.QOpenGLTexture.UInt16, img.bits())
self.texture.setData(0, 0, QtGui.QOpenGLTexture.CubeMapNegativeZ, QtGui.QOpenGLTexture.RGBA, QtGui.QOpenGLTexture.UInt16, img.bits())
self.texture.setData(0, 0, QtGui.QOpenGLTexture.CubeMapPositiveX, QtGui.QOpenGLTexture.RGBA, QtGui.QOpenGLTexture.UInt16, img.bits())
self.texture.setData(0, 0, QtGui.QOpenGLTexture.CubeMapPositiveY, QtGui.QOpenGLTexture.RGBA, QtGui.QOpenGLTexture.UInt16, img.bits())
self.texture.setData(0, 0, QtGui.QOpenGLTexture.CubeMapPositiveZ, QtGui.QOpenGLTexture.RGBA, QtGui.QOpenGLTexture.UInt16, img.bits())
self.texture.setMinMagFilters(QtGui.QOpenGLTexture.Linear, QtGui.QOpenGLTexture.Linear)
self.texture.setWrapMode(QtGui.QOpenGLTexture.ClampToEdge)
# initialise Camera matrix with initial rotation
m = QtGui.QMatrix4x4()
m.ortho(-0.5, 0.5, 0.5, -0.5, 4.0, 15.0)
m.translate(0.0, 0.0, -10.0)
m.rotate(self.xRot / 16.0, 1.0, 0.0, 0.0)
m.rotate(self.yRot / 16.0, 0.0, 1.0, 0.0)
m.rotate(self.zRot / 16.0, 0.0, 0.0, 1.0)
self.program.setUniformValue('mvp', m)
self.program.setUniformValue('texture', 0)
self.vao.bind()
gl.glDrawArrays( gl.GL_TRIANGLES, 0, 36 )
self.vao.release()
self.program.release()
def mousePressEvent(self, event):
self.lastPos = event.pos()
def mouseMoveEvent(self, event):
dx = event.x() - self.lastPos.x()
dy = event.y() - self.lastPos.y()
if event.buttons() & Qt.LeftButton:
self.rotateBy(8 * dy, 8 * dx, 0)
elif event.buttons() & Qt.RightButton:
self.rotateBy(8 * dy, 0, 8 * dx)
self.lastPos = event.pos()
self.paintGL()
def mouseReleaseEvent(self, event):
self.clicked.emit()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())
Shaders:
shader.vert
#version 430 core
in vec3 position;
out vec3 texCoords;
uniform mat4 mvp;
void main(void)
{
texCoords = position;
gl_Position = mvp * vec4(position, 1.0);
}
shader.frag
#version 430 core
in vec3 texCoords;
uniform sampler2D texture;
void main(void)
{
gl_FragColor = texture2D(texture, texCoords.xy);
}
Solution
Since self.texture is a cube map (QtGui.QOpenGLTexture.TargetCubeMap
), the type of the corresponding texture sampler uniform has to be samplerCube
rather than sampler2D
.
The texture coordinates for a cube map are treated as a direction vector emanating from the center of a cube.
Since the center of the cube model is (0, 0, 0), the direction vector respectively texture coordinate is equal the model position of the fragment.
Change the fragment shader to solve the issue:
#version 430 core
in vec3 texCoords;
uniform samplerCube texture;
void main(void)
{
gl_FragColor = texture(texture, texCoords.xyz);
}
Note, texture2D
respectively textureCube
are compatibility profile functions. You've to use the function texture
which works in compatibility as in core profile.
Answered By - Rabbid76
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.