experimental GL video widget

temporary fix for text parameter ignoring expanded option
Don't use os.EX_OK in pg.exit()
This commit is contained in:
Luke Campagnola 2013-07-10 00:02:16 -04:00
parent a20e732f65
commit 7cd3e663f9
9 changed files with 243 additions and 76 deletions

View File

@ -130,8 +130,13 @@ def update():
if ui.rawRadio.isChecked():
ui.rawImg.setImage(data[ptr%data.shape[0]], lut=useLut, levels=useScale)
ui.stack.setCurrentIndex(1)
elif ui.rawGLRadio.isChecked():
ui.rawGLImg.setImage(data[ptr%data.shape[0]], lut=useLut, levels=useScale)
ui.stack.setCurrentIndex(2)
else:
img.setImage(data[ptr%data.shape[0]], autoLevels=False, levels=useScale, lut=useLut)
ui.stack.setCurrentIndex(0)
#img.setImage(data[ptr%data.shape[0]], autoRange=False)
ptr += 1

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>985</width>
<height>674</height>
<width>695</width>
<height>798</height>
</rect>
</property>
<property name="windowTitle">
@ -17,33 +17,62 @@
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0" colspan="4">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="RawImageWidget" name="rawImg" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="GraphicsView" name="graphicsView"/>
</item>
<item row="1" column="0">
<item row="3" column="0">
<widget class="QRadioButton" name="rawRadio">
<property name="text">
<string>RawImageWidget (unscaled; faster)</string>
<string>RawImageWidget</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="0">
<widget class="QRadioButton" name="gfxRadio">
<property name="text">
<string>GraphicsView + ImageItem (scaled; slower)</string>
<string>GraphicsView + ImageItem</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QStackedWidget" name="stack">
<property name="currentIndex">
<number>2</number>
</property>
<widget class="QWidget" name="page">
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="GraphicsView" name="graphicsView"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="RawImageWidget" name="rawImg" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_3">
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="RawImageGLWidget" name="rawGLImg" native="true"/>
</item>
</layout>
</widget>
</widget>
</item>
<item row="4" column="0">
<widget class="QRadioButton" name="rawGLRadio">
<property name="text">
<string>RawGLImageWidget</string>
</property>
</widget>
</item>
@ -250,6 +279,12 @@
<extends>QDoubleSpinBox</extends>
<header>pyqtgraph</header>
</customwidget>
<customwidget>
<class>RawImageGLWidget</class>
<extends>QWidget</extends>
<header>pyqtgraph.widgets.RawImageWidget</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './examples/VideoTemplate.ui'
# Form implementation generated from reading ui file './VideoTemplate.ui'
#
# Created: Sun Nov 4 18:24:20 2012
# by: PyQt4 UI code generator 4.9.1
# Created: Tue Jul 9 23:38:17 2013
# by: PyQt4 UI code generator 4.9.3
#
# WARNING! All changes made in this file will be lost!
@ -17,31 +17,55 @@ except AttributeError:
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(985, 674)
MainWindow.resize(695, 798)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.gridLayout_2 = QtGui.QGridLayout(self.centralwidget)
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
self.gridLayout = QtGui.QGridLayout()
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.rawImg = RawImageWidget(self.centralwidget)
self.rawRadio = QtGui.QRadioButton(self.centralwidget)
self.rawRadio.setChecked(True)
self.rawRadio.setObjectName(_fromUtf8("rawRadio"))
self.gridLayout.addWidget(self.rawRadio, 3, 0, 1, 1)
self.gfxRadio = QtGui.QRadioButton(self.centralwidget)
self.gfxRadio.setObjectName(_fromUtf8("gfxRadio"))
self.gridLayout.addWidget(self.gfxRadio, 2, 0, 1, 1)
self.stack = QtGui.QStackedWidget(self.centralwidget)
self.stack.setObjectName(_fromUtf8("stack"))
self.page = QtGui.QWidget()
self.page.setObjectName(_fromUtf8("page"))
self.gridLayout_3 = QtGui.QGridLayout(self.page)
self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3"))
self.graphicsView = GraphicsView(self.page)
self.graphicsView.setObjectName(_fromUtf8("graphicsView"))
self.gridLayout_3.addWidget(self.graphicsView, 0, 0, 1, 1)
self.stack.addWidget(self.page)
self.page_2 = QtGui.QWidget()
self.page_2.setObjectName(_fromUtf8("page_2"))
self.gridLayout_4 = QtGui.QGridLayout(self.page_2)
self.gridLayout_4.setObjectName(_fromUtf8("gridLayout_4"))
self.rawImg = RawImageWidget(self.page_2)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.rawImg.sizePolicy().hasHeightForWidth())
self.rawImg.setSizePolicy(sizePolicy)
self.rawImg.setObjectName(_fromUtf8("rawImg"))
self.gridLayout.addWidget(self.rawImg, 0, 0, 1, 1)
self.graphicsView = GraphicsView(self.centralwidget)
self.graphicsView.setObjectName(_fromUtf8("graphicsView"))
self.gridLayout.addWidget(self.graphicsView, 0, 1, 1, 1)
self.rawRadio = QtGui.QRadioButton(self.centralwidget)
self.rawRadio.setChecked(True)
self.rawRadio.setObjectName(_fromUtf8("rawRadio"))
self.gridLayout.addWidget(self.rawRadio, 1, 0, 1, 1)
self.gfxRadio = QtGui.QRadioButton(self.centralwidget)
self.gfxRadio.setObjectName(_fromUtf8("gfxRadio"))
self.gridLayout.addWidget(self.gfxRadio, 1, 1, 1, 1)
self.gridLayout_4.addWidget(self.rawImg, 0, 0, 1, 1)
self.stack.addWidget(self.page_2)
self.page_3 = QtGui.QWidget()
self.page_3.setObjectName(_fromUtf8("page_3"))
self.gridLayout_5 = QtGui.QGridLayout(self.page_3)
self.gridLayout_5.setObjectName(_fromUtf8("gridLayout_5"))
self.rawGLImg = RawImageGLWidget(self.page_3)
self.rawGLImg.setObjectName(_fromUtf8("rawGLImg"))
self.gridLayout_5.addWidget(self.rawGLImg, 0, 0, 1, 1)
self.stack.addWidget(self.page_3)
self.gridLayout.addWidget(self.stack, 0, 0, 1, 1)
self.rawGLRadio = QtGui.QRadioButton(self.centralwidget)
self.rawGLRadio.setObjectName(_fromUtf8("rawGLRadio"))
self.gridLayout.addWidget(self.rawGLRadio, 4, 0, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 1, 0, 1, 4)
self.label = QtGui.QLabel(self.centralwidget)
self.label.setObjectName(_fromUtf8("label"))
@ -130,12 +154,14 @@ class Ui_MainWindow(object):
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
self.stack.setCurrentIndex(2)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
self.rawRadio.setText(QtGui.QApplication.translate("MainWindow", "RawImageWidget (unscaled; faster)", None, QtGui.QApplication.UnicodeUTF8))
self.gfxRadio.setText(QtGui.QApplication.translate("MainWindow", "GraphicsView + ImageItem (scaled; slower)", None, QtGui.QApplication.UnicodeUTF8))
self.rawRadio.setText(QtGui.QApplication.translate("MainWindow", "RawImageWidget", None, QtGui.QApplication.UnicodeUTF8))
self.gfxRadio.setText(QtGui.QApplication.translate("MainWindow", "GraphicsView + ImageItem", None, QtGui.QApplication.UnicodeUTF8))
self.rawGLRadio.setText(QtGui.QApplication.translate("MainWindow", "RawGLImageWidget", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("MainWindow", "Data type", None, QtGui.QApplication.UnicodeUTF8))
self.dtypeCombo.setItemText(0, QtGui.QApplication.translate("MainWindow", "uint8", None, QtGui.QApplication.UnicodeUTF8))
self.dtypeCombo.setItemText(1, QtGui.QApplication.translate("MainWindow", "uint16", None, QtGui.QApplication.UnicodeUTF8))
@ -150,4 +176,5 @@ class Ui_MainWindow(object):
self.fpsLabel.setText(QtGui.QApplication.translate("MainWindow", "FPS", None, QtGui.QApplication.UnicodeUTF8))
self.rgbCheck.setText(QtGui.QApplication.translate("MainWindow", "RGB", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph import SpinBox, GradientWidget, GraphicsView, RawImageWidget
from pyqtgraph.widgets.RawImageWidget import RawImageGLWidget
from pyqtgraph import GradientWidget, SpinBox, GraphicsView, RawImageWidget

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './examples/VideoTemplate.ui'
# Form implementation generated from reading ui file './VideoTemplate.ui'
#
# Created: Sun Nov 4 18:24:21 2012
# by: pyside-uic 0.2.13 running on PySide 1.1.0
# Created: Tue Jul 9 23:38:19 2013
# by: pyside-uic 0.2.13 running on PySide 1.1.2
#
# WARNING! All changes made in this file will be lost!
@ -12,31 +12,55 @@ from PySide import QtCore, QtGui
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(985, 674)
MainWindow.resize(695, 798)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout_2 = QtGui.QGridLayout(self.centralwidget)
self.gridLayout_2.setObjectName("gridLayout_2")
self.gridLayout = QtGui.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.rawImg = RawImageWidget(self.centralwidget)
self.rawRadio = QtGui.QRadioButton(self.centralwidget)
self.rawRadio.setChecked(True)
self.rawRadio.setObjectName("rawRadio")
self.gridLayout.addWidget(self.rawRadio, 3, 0, 1, 1)
self.gfxRadio = QtGui.QRadioButton(self.centralwidget)
self.gfxRadio.setObjectName("gfxRadio")
self.gridLayout.addWidget(self.gfxRadio, 2, 0, 1, 1)
self.stack = QtGui.QStackedWidget(self.centralwidget)
self.stack.setObjectName("stack")
self.page = QtGui.QWidget()
self.page.setObjectName("page")
self.gridLayout_3 = QtGui.QGridLayout(self.page)
self.gridLayout_3.setObjectName("gridLayout_3")
self.graphicsView = GraphicsView(self.page)
self.graphicsView.setObjectName("graphicsView")
self.gridLayout_3.addWidget(self.graphicsView, 0, 0, 1, 1)
self.stack.addWidget(self.page)
self.page_2 = QtGui.QWidget()
self.page_2.setObjectName("page_2")
self.gridLayout_4 = QtGui.QGridLayout(self.page_2)
self.gridLayout_4.setObjectName("gridLayout_4")
self.rawImg = RawImageWidget(self.page_2)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.rawImg.sizePolicy().hasHeightForWidth())
self.rawImg.setSizePolicy(sizePolicy)
self.rawImg.setObjectName("rawImg")
self.gridLayout.addWidget(self.rawImg, 0, 0, 1, 1)
self.graphicsView = GraphicsView(self.centralwidget)
self.graphicsView.setObjectName("graphicsView")
self.gridLayout.addWidget(self.graphicsView, 0, 1, 1, 1)
self.rawRadio = QtGui.QRadioButton(self.centralwidget)
self.rawRadio.setChecked(True)
self.rawRadio.setObjectName("rawRadio")
self.gridLayout.addWidget(self.rawRadio, 1, 0, 1, 1)
self.gfxRadio = QtGui.QRadioButton(self.centralwidget)
self.gfxRadio.setObjectName("gfxRadio")
self.gridLayout.addWidget(self.gfxRadio, 1, 1, 1, 1)
self.gridLayout_4.addWidget(self.rawImg, 0, 0, 1, 1)
self.stack.addWidget(self.page_2)
self.page_3 = QtGui.QWidget()
self.page_3.setObjectName("page_3")
self.gridLayout_5 = QtGui.QGridLayout(self.page_3)
self.gridLayout_5.setObjectName("gridLayout_5")
self.rawGLImg = RawImageGLWidget(self.page_3)
self.rawGLImg.setObjectName("rawGLImg")
self.gridLayout_5.addWidget(self.rawGLImg, 0, 0, 1, 1)
self.stack.addWidget(self.page_3)
self.gridLayout.addWidget(self.stack, 0, 0, 1, 1)
self.rawGLRadio = QtGui.QRadioButton(self.centralwidget)
self.rawGLRadio.setObjectName("rawGLRadio")
self.gridLayout.addWidget(self.rawGLRadio, 4, 0, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 1, 0, 1, 4)
self.label = QtGui.QLabel(self.centralwidget)
self.label.setObjectName("label")
@ -125,12 +149,14 @@ class Ui_MainWindow(object):
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
self.stack.setCurrentIndex(2)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
self.rawRadio.setText(QtGui.QApplication.translate("MainWindow", "RawImageWidget (unscaled; faster)", None, QtGui.QApplication.UnicodeUTF8))
self.gfxRadio.setText(QtGui.QApplication.translate("MainWindow", "GraphicsView + ImageItem (scaled; slower)", None, QtGui.QApplication.UnicodeUTF8))
self.rawRadio.setText(QtGui.QApplication.translate("MainWindow", "RawImageWidget", None, QtGui.QApplication.UnicodeUTF8))
self.gfxRadio.setText(QtGui.QApplication.translate("MainWindow", "GraphicsView + ImageItem", None, QtGui.QApplication.UnicodeUTF8))
self.rawGLRadio.setText(QtGui.QApplication.translate("MainWindow", "RawGLImageWidget", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("MainWindow", "Data type", None, QtGui.QApplication.UnicodeUTF8))
self.dtypeCombo.setItemText(0, QtGui.QApplication.translate("MainWindow", "uint8", None, QtGui.QApplication.UnicodeUTF8))
self.dtypeCombo.setItemText(1, QtGui.QApplication.translate("MainWindow", "uint16", None, QtGui.QApplication.UnicodeUTF8))
@ -145,4 +171,5 @@ class Ui_MainWindow(object):
self.fpsLabel.setText(QtGui.QApplication.translate("MainWindow", "FPS", None, QtGui.QApplication.UnicodeUTF8))
self.rgbCheck.setText(QtGui.QApplication.translate("MainWindow", "RGB", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph import SpinBox, GradientWidget, GraphicsView, RawImageWidget
from pyqtgraph.widgets.RawImageWidget import RawImageGLWidget
from pyqtgraph import GradientWidget, SpinBox, GraphicsView, RawImageWidget

View File

@ -139,14 +139,19 @@ p.param('Save/Restore functionality', 'Restore State').sigActivated.connect(rest
## Create two ParameterTree widgets, both accessing the same data
t = ParameterTree()
t.setParameters(p, showTop=False)
t.show()
t.setWindowTitle('pyqtgraph example: Parameter Tree')
t.resize(400,800)
t2 = ParameterTree()
t2.setParameters(p, showTop=False)
t2.show()
t2.resize(400,800)
win = QtGui.QWidget()
layout = QtGui.QGridLayout()
win.setLayout(layout)
layout.addWidget(QtGui.QLabel("These are two views of the same data. They should always display the same values."), 0, 0, 1, 2)
layout.addWidget(t, 1, 0, 1, 1)
layout.addWidget(t2, 1, 1, 1, 1)
win.show()
win.resize(800,800)
## test save/restore
s = p.saveState()
p.restoreState(s)

View File

@ -255,7 +255,7 @@ def exit():
## close file handles
os.closerange(3, 4096) ## just guessing on the maximum descriptor count..
os._exit(os.EX_OK)
os._exit(0)

View File

@ -49,7 +49,13 @@ class ROI(GraphicsObject):
sigRegionChanged Emitted any time the position of the ROI changes,
including while it is being dragged by the user.
sigHoverEvent Emitted when the mouse hovers over the ROI.
sigClicked Emitted when the user clicks on the ROI
sigClicked Emitted when the user clicks on the ROI.
Note that clicking is disabled by default to prevent
stealing clicks from objects behind the ROI. To
enable clicking, call
roi.setAcceptedMouseButtons(QtCore.Qt.LeftButton).
See QtGui.QGraphicsItem documentation for more
details.
sigRemoveRequested Emitted when the user selects 'remove' from the
ROI's context menu (if available).
----------------------- ----------------------------------------------------

View File

@ -619,9 +619,15 @@ class TextParameterItem(WidgetParameterItem):
self.addChild(self.subItem)
def treeWidgetChanged(self):
## TODO: fix so that superclass method can be called
## (WidgetParameter should just natively support this style)
#WidgetParameterItem.treeWidgetChanged(self)
self.treeWidget().setFirstItemColumnSpanned(self.subItem, True)
self.treeWidget().setItemWidget(self.subItem, 0, self.textBox)
self.setExpanded(True)
# for now, these are copied from ParameterItem.treeWidgetChanged
self.setHidden(not self.param.opts.get('visible', True))
self.setExpanded(self.param.opts.get('expanded', True))
def makeWidget(self):
self.textBox = QtGui.QTextEdit()

View File

@ -11,8 +11,8 @@ import numpy as np
class RawImageWidget(QtGui.QWidget):
"""
Widget optimized for very fast video display.
Generally using an ImageItem inside GraphicsView is fast enough,
but if you need even more performance, this widget is about as fast as it gets (but only in unscaled mode).
Generally using an ImageItem inside GraphicsView is fast enough.
On some systems this may provide faster video. See the VideoSpeedTest example for benchmarking.
"""
def __init__(self, parent=None, scaled=False):
"""
@ -59,26 +59,82 @@ class RawImageWidget(QtGui.QWidget):
p.end()
if HAVE_OPENGL:
from OpenGL.GL import *
class RawImageGLWidget(QtOpenGL.QGLWidget):
"""
Similar to RawImageWidget, but uses a GL widget to do all drawing.
Generally this will be about as fast as using GraphicsView + ImageItem,
but performance may vary on some platforms.
Perfomance varies between platforms; see examples/VideoSpeedTest for benchmarking.
"""
def __init__(self, parent=None, scaled=False):
QtOpenGL.QGLWidget.__init__(self, parent=None)
self.scaled = scaled
self.image = None
self.uploaded = False
self.smooth = False
self.opts = None
def setImage(self, img):
self.image = fn.makeQImage(img)
def setImage(self, img, *args, **kargs):
"""
img must be ndarray of shape (x,y), (x,y,3), or (x,y,4).
Extra arguments are sent to functions.makeARGB
"""
self.opts = (img, args, kargs)
self.image = None
self.uploaded = False
self.update()
def paintEvent(self, ev):
def initializeGL(self):
self.texture = glGenTextures(1)
def uploadTexture(self):
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, self.texture)
if self.smooth:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
else:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
#glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER)
shape = self.image.shape
### Test texture dimensions first
#glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, shape[0], shape[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, None)
#if glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH) == 0:
#raise Exception("OpenGL failed to create 2D texture (%dx%d); too large for this hardware." % shape[:2])
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, shape[0], shape[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, self.image.transpose((1,0,2)))
glDisable(GL_TEXTURE_2D)
def paintGL(self):
if self.image is None:
return
p = QtGui.QPainter(self)
p.drawImage(self.rect(), self.image)
p.end()
if self.opts is None:
return
img, args, kwds = self.opts
kwds['useRGBA'] = True
self.image, alpha = fn.makeARGB(img, *args, **kwds)
if not self.uploaded:
self.uploadTexture()
glViewport(0, 0, self.width(), self.height())
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, self.texture)
glColor4f(1,1,1,1)
glBegin(GL_QUADS)
glTexCoord2f(0,0)
glVertex3f(-1,-1,0)
glTexCoord2f(1,0)
glVertex3f(1, -1, 0)
glTexCoord2f(1,1)
glVertex3f(1, 1, 0)
glTexCoord2f(0,1)
glVertex3f(-1, 1, 0)
glEnd()
glDisable(GL_TEXTURE_3D)