我想弄清楚爲什麼我無法使用(現在內置的)shader_image_load_store擴展名寫入3D紋理。OpenGL 4.2+和shader_image_load_store不適用於3D紋理?
我創建了兩個簡單的例子(在python,使其更容易):一個寫入到一個2D紋理,這樣的作品,和一個寫入到3D紋理不起作用
的(工作)2D版本如下:
#! /usr/bin/env python
from PyQt4 import QtGui, QtCore
from PyQt4.QtOpenGL import *
from OpenGL.GL import *
from OpenGL.GLU import *
import sys
iTexSize = 256
_vsClearSource = """
#version 440 compatibility
void main() {
gl_Position = ftransform();
gl_FrontColor = gl_Color;
}
"""
_fsClearSource = """
#version 440 compatibility
uniform int iPrimitiveCount;
uniform int iSliceIndex;
layout(size4x32, binding=0) coherent uniform image2D volColorVolume;
const int iMaxTexSize = 255;
void main() {
ivec2 ivecVolumeCoordinate = ivec2(gl_FragCoord.x, gl_FragCoord.y); //, iSliceIndex);
vec4 vecVolumeValue = vec4(0,1,0,1); // vec4( float(iSlabIndex)/float(iPrimitiveCount)); //,0.0,0.0,0.0);
imageStore(volColorVolume, ivecVolumeCoordinate, vecVolumeValue);
gl_FragData[0] = vec4(1,0,1,1);
}
"""
_fsFillSource = """
#version 440 compatibility
uniform int iPrimitiveCount;
uniform int iSliceIndex;
layout(size4x32, binding=0) coherent uniform image2D volColorVolume;
const int iMaxTexSize = 255;
void main() {
ivec2 ivecVolumeCoordinate = ivec2(gl_FragCoord.x, gl_FragCoord.y);
vec4 vecVolumeValue = vec4(float(gl_FragCoord.x)/float(iMaxTexSize) , float(gl_FragCoord.y)/float(iMaxTexSize) , 0 , 1 );
imageStore(volColorVolume, ivecVolumeCoordinate, vecVolumeValue);
gl_FragData[0] = vec4(1,0,1,1);
}
"""
class Viewer3DWidget(QGLWidget):
def __init__(self, parent):
QGLWidget.__init__(self, parent)
self.uWidth = 0
self.uHeight = 0
self.texColorTexture = None
self.fboRendering = None
self.texColorVolume = None
self.vecBackgroundColor = (1.,1.,1.)
self.vecDrawBuffers = [ GL_COLOR_ATTACHMENT0 , GL_COLOR_ATTACHMENT1 , GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5 ]
self.fSurfacesSpacing = 1.0
self.fSurfacesTransparency = 1.0
def initializeGL(self):
self.shaShaderFill = QGLShaderProgram(self.context())
self.shaShaderFill.addShaderFromSourceCode(QGLShader.Vertex, _vsClearSource)
self.shaShaderFill.addShaderFromSourceCode(QGLShader.Fragment, _fsFillSource)
self.shaShaderFill.link()
self.shaShaderClear = QGLShaderProgram(self.context())
self.shaShaderClear.addShaderFromSourceCode(QGLShader.Vertex, _vsClearSource)
self.shaShaderClear.addShaderFromSourceCode(QGLShader.Fragment, _fsClearSource)
self.shaShaderClear.link()
glClearColor(1.0, 1.0, 1.0, 1.0)
glClearDepth(1.0)
def initRenderTargets(self):
global iTexSize
if (self.texColorTexture is None):
self.texColorTexture = glGenTextures(1)
if (self.fboRendering is None):
self.fboRendering = glGenFramebuffers(1)
glBindTexture(GL_TEXTURE_RECTANGLE, self.texColorTexture)
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA32F, iTexSize, iTexSize, 0, GL_RGBA, GL_FLOAT, None)
glBindTexture(GL_TEXTURE_RECTANGLE, 0);
glBindFramebuffer(GL_FRAMEBUFFER, self.fboRendering)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, self.texColorTexture, 0)
glBindFramebuffer(GL_FRAMEBUFFER, 0)
def deleteRenderTargets(self):
if (self.fboAccumulation is not None):
glDeleteFramebuffers(1,self.fboRendering)
self.fboAccumulation = None
if (self.texColorTexture is not None):
glDeleteTextures(self.texColorTexture)
self.texColorTexture = None
def initColorVolume(self):
if (self.texColorVolume is None):
self.texColorVolume = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, self.texColorVolume)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
#glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, iTexSize, iTexSize, 0, GL_RGBA, GL_FLOAT, None);
glBindTexture(GL_TEXTURE_2D, 0);
def fillVolume(self, bClear):
global iTexSize
shaShader = self.shaShaderClear
if(not bClear):
shaShader = self.shaShaderFill
if (not self.fboRendering):
self.initRenderTargets()
if (not self.texColorVolume):
self.initColorVolume()
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBindImageTexture(0,self.texColorVolume,0,GL_FALSE,0,GL_READ_WRITE,GL_RGBA32F);
glBindFramebuffer(GL_FRAMEBUFFER, self.fboRendering);
glDrawBuffers(1, self.vecDrawBuffers);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
shaShader.bind()
shaShader.setUniformValue("iPrimitiveCount", iTexSize)
shaShader.setUniformValue("volColorVolume", 0)
for i in range(iTexSize):
shaShader.setUniformValue("iSliceIndex", i)
glBegin(GL_QUADS);
glVertex2f(-1.0, -1.0);
glVertex2f(1.0, -1.0);
glVertex2f(1.0, 1.0);
glVertex2f(-1.0, 1.0);
glEnd();
#sync
glMemoryBarrier(GL_ALL_BARRIER_BITS);
glBindImageTexture(0,0,0,GL_FALSE,0,GL_READ_WRITE,GL_RGBA32F);
shaShader.release()
glBindFramebuffer(GL_FRAMEBUFFER, 0);
def paintGL(self):
if (self.uWidth is 0):
return
if (not self.fboRendering):
self.initRenderTargets()
self.initColorVolume()
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
self.fillVolume(True)
#draw into the volume
self.fillVolume(False)
#slice the volume
self.displayTexture()
glFlush()
def displayTexture(self): #essentially not useable here
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_BLEND)
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glColor(1.0, 1.0,1.0)
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, self.texColorVolume)
glBegin(GL_QUADS);
glTexCoord2f(0,0) #,0.5)
glVertex2f(-1.0, -1.0);
glTexCoord2f(1,0) #,0.5)
glVertex2f(1.0, -1.0);
glTexCoord2f(1,1) #,0.5)
glVertex2f(1.0, 1.0);
glTexCoord2f(0,1) #,0.5)
glVertex2f(-1.0, 1.0);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0)
def resizeGL(self, widthInPixels, heightInPixels):
if ((widthInPixels is not self.uWidth) or (heightInPixels is not self.uHeight)):
self.uWidth = widthInPixels
self.uHeight = heightInPixels
glViewport(0, 0, widthInPixels, heightInPixels)
self.update()
class TestImageLoadStore2D(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setWindowTitle('TestImageLoadStore2D')
self.statusBar().showMessage("Hello there")
exit = QtGui.QAction("Exit", self)
exit.setShortcut("Ctrl+Q")
exit.setStatusTip('Exit application')
self.connect(exit, QtCore.SIGNAL('triggered()'), QtCore.SLOT('close()'))
self.viewer3D = Viewer3DWidget(self)
self.setCentralWidget(self.viewer3D)
self.resize(500,500)
def closeEvent(self, event):
event.accept()
if __name__ == '__main__':
# app = QtGui.QApplication(['Python Qt OpenGL Demo'])
app = QtGui.QApplication(sys.argv)
window = TestImageLoadStore2D()
window.show()
sys.exit(app.exec_())
而對非工作的3D版本如下:
#! /usr/bin/env python
from PyQt4 import QtGui, QtCore
from PyQt4.QtOpenGL import *
from OpenGL.GL import *
from OpenGL.GLU import *
import sys
iTexSize = 256
_vsClearSource = """
#version 440 compatibility
void main() {
gl_Position = ftransform();
gl_FrontColor = gl_Color;
}
"""
_fsClearSource = """
#version 440 compatibility
uniform int iPrimitiveCount;
uniform int iSliceIndex;
layout(size4x32, binding=0) writeonly uniform image3D volColorVolume;
//layout(rgba32f, binding=0) writeonly uniform image3D volColorVolume;
const int iMaxTexSize = 255;
void main() {
ivec3 ivecVolumeCoordinate = ivec3(gl_FragCoord.x, gl_FragCoord.y, 0); //iSliceIndex);
vec4 vecVolumeValue = vec4(0,1,0,1); // vec4( float(iSlabIndex)/float(iPrimitiveCount)); //,0.0,0.0,0.0);
imageStore(volColorVolume, ivecVolumeCoordinate, vecVolumeValue);
memoryBarrier();
gl_FragData[0] = vec4(1,0,1,1);
}
"""
_fsFillSource = """
#version 440 compatibility
uniform int iPrimitiveCount;
uniform int iSliceIndex;
layout(size4x32, binding=0) writeonly uniform image3D volColorVolume;
const int iMaxTexSize = 255;
void main() {
ivec3 ivecVolumeCoordinate = ivec3(gl_FragCoord.x, gl_FragCoord.y, 0); //iSliceIndex);
vec4 vecVolumeValue = vec4(float(gl_FragCoord.x)/float(iMaxTexSize) , float(gl_FragCoord.y)/float(iMaxTexSize) , float(iSliceIndex)/float(iPrimitiveCount) , 1 );
imageStore(volColorVolume, ivecVolumeCoordinate, vecVolumeValue);
memoryBarrier();
gl_FragData[0] = vec4(1,0,1,1);
}
"""
class Viewer3DWidget(QGLWidget):
def __init__(self, parent):
QGLWidget.__init__(self, parent)
self.uWidth = 0
self.uHeight = 0
self.texColorTexture = None
self.fboRendering = None
self.texColorVolume = None
self.vecBackgroundColor = (1.,1.,1.)
self.vecDrawBuffers = [ GL_COLOR_ATTACHMENT0 , GL_COLOR_ATTACHMENT1 , GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5 ]
self.fSurfacesSpacing = 1.0
self.fSurfacesTransparency = 1.0
self.fZCoord = 0.0
def setZCoordinate(self, fZCoordinate):
self.fZCoord = fZCoordinate
self.update()
def initializeGL(self):
self.shaShaderFill = QGLShaderProgram(self.context())
self.shaShaderFill.addShaderFromSourceCode(QGLShader.Vertex, _vsClearSource)
self.shaShaderFill.addShaderFromSourceCode(QGLShader.Fragment, _fsFillSource)
self.shaShaderFill.link()
self.shaShaderClear = QGLShaderProgram(self.context())
self.shaShaderClear.addShaderFromSourceCode(QGLShader.Vertex, _vsClearSource)
self.shaShaderClear.addShaderFromSourceCode(QGLShader.Fragment, _fsClearSource)
self.shaShaderClear.link()
glClearColor(1.0, 1.0, 1.0, 1.0)
glClearDepth(1.0)
def initRenderTargets(self):
global iTexSize
if (self.texColorTexture is None):
self.texColorTexture = glGenTextures(1)
if (self.fboRendering is None):
self.fboRendering = glGenFramebuffers(1)
glBindTexture(GL_TEXTURE_RECTANGLE, self.texColorTexture)
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA32F, iTexSize, iTexSize, 0, GL_RGBA, GL_FLOAT, None)
glBindTexture(GL_TEXTURE_RECTANGLE, 0);
glBindFramebuffer(GL_FRAMEBUFFER, self.fboRendering)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, self.texColorTexture, 0)
glBindFramebuffer(GL_FRAMEBUFFER, 0)
def deleteRenderTargets(self):
if (self.fboAccumulation is not None):
glDeleteFramebuffers(1,self.fboRendering)
self.fboAccumulation = None
if (self.texColorTexture is not None):
glDeleteTextures(self.texColorTexture)
self.texColorTexture = None
def initColorVolume(self):
if (self.texColorVolume is None):
self.texColorVolume = glGenTextures(1)
glBindTexture(GL_TEXTURE_3D, self.texColorVolume)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F, iTexSize, iTexSize, iTexSize, 0, GL_RGBA, GL_FLOAT, None);
glBindTexture(GL_TEXTURE_3D, 0);
def fillVolume(self, bClear):
global iTexSize
shaShader = self.shaShaderClear
if(not bClear):
shaShader = self.shaShaderFill
if (not self.fboRendering):
self.initRenderTargets()
if (not self.texColorVolume):
self.initColorVolume()
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBindImageTexture(0,self.texColorVolume,0,GL_FALSE,0,GL_WRITE_ONLY,GL_RGBA32F);
glBindFramebuffer(GL_FRAMEBUFFER, self.fboRendering);
glDrawBuffers(1, self.vecDrawBuffers);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
shaShader.bind()
shaShader.setUniformValue("iPrimitiveCount", iTexSize)
shaShader.setUniformValue("volColorVolume", 0)
for i in range(iTexSize):
shaShader.setUniformValue("iSliceIndex", i)
glBegin(GL_QUADS);
glVertex2f(-1.0, -1.0);
glVertex2f(1.0, -1.0);
glVertex2f(1.0, 1.0);
glVertex2f(-1.0, 1.0);
glEnd();
#sync
glMemoryBarrier(GL_ALL_BARRIER_BITS);
glMemoryBarrier(GL_ALL_BARRIER_BITS);
glBindImageTexture(0,0,0,GL_FALSE,0,GL_WRITE_ONLY,GL_RGBA32F);
shaShader.release()
glBindFramebuffer(GL_FRAMEBUFFER, 0);
def paintGL(self):
if (self.uWidth is 0):
return
if (not self.fboRendering):
self.initRenderTargets()
self.initColorVolume()
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
self.fillVolume(True)
#draw into the volume
#self.fillVolume(False)
#slice the volume
self.displayTexture()
glFlush()
def displayTexture(self): #essentially not useable here
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_BLEND)
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glColor(1.0, 1.0,1.0)
glEnable(GL_TEXTURE_3D);
glBindTexture(GL_TEXTURE_3D, self.texColorVolume)
fZCoord = self.fZCoord
glBegin(GL_QUADS);
glTexCoord3f(0,0,fZCoord)
glVertex2f(-1.0, -1.0);
glTexCoord3f(1,0,fZCoord)
glVertex2f(1.0, -1.0);
glTexCoord3f(1,1,fZCoord)
glVertex2f(1.0, 1.0);
glTexCoord3f(0,1,fZCoord)
glVertex2f(-1.0, 1.0);
glEnd();
glBindTexture(GL_TEXTURE_3D, 0)
def resizeGL(self, widthInPixels, heightInPixels):
if ((widthInPixels is not self.uWidth) or (heightInPixels is not self.uHeight)):
self.uWidth = widthInPixels
self.uHeight = heightInPixels
glViewport(0, 0, widthInPixels, heightInPixels)
self.update()
class TestImageLoadStore3D(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setWindowTitle('TestImageLoadStore3D')
self.statusBar().showMessage("Hello there")
exit = QtGui.QAction("Exit", self)
exit.setShortcut("Ctrl+Q")
exit.setStatusTip('Exit application')
self.connect(exit, QtCore.SIGNAL('triggered()'), QtCore.SLOT('close()'))
self.setToolTip('This is a window, or <b>something</b>')
self.viewer3D = Viewer3DWidget(self)
parentWidget = QtGui.QWidget()
slider1 = QtGui.QSlider(QtCore.Qt.Horizontal, None)
slider1.setRange(0,10000)
slider1.setValue(5000)
slider1.setMaximumWidth(120)
slider1.valueChanged.connect(self.slider1Handler)
vbox = QtGui.QVBoxLayout()
vbox.addWidget(slider1)
vbox.addStretch(1)
self.viewer3D.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
hbox = QtGui.QHBoxLayout()
hbox.addLayout(vbox)
hbox.addWidget(self.viewer3D)
parentWidget.setLayout(hbox)
self.setCentralWidget(parentWidget)
self.resize(500,500)
def closeEvent(self, event):
event.accept()
def slider1Handler(self, iVal):
fVal = iVal/10000.0
#print "zcoord: ",fVal
self.viewer3D.setZCoordinate(fVal)
if __name__ == '__main__':
# app = QtGui.QApplication(['Python Qt OpenGL Demo'])
app = QtGui.QApplication(sys.argv)
window = TestImageLoadStore3D()
window.show()
sys.exit(app.exec_())
代碼沒有多餘的整潔,還因爲我複製/粘貼/修改的一些老pyopengl代碼我有。 問題是,寫在3D紋理中的值絕對沒有意義。 我使用最新版本的PyOpenGL(實驗版本),Quadro K5000和最新的驅動程序(332.76)來運行它,它們也提供了對OpenGL 4.4的支持。
我不知道我可能是做錯了,也因爲我還沒有發現寫入3D紋理的例子很多(實際上沒有,我也看了紅皮書的最新版本)
有人可以啓發我嗎?
非常感謝!由於我對文檔的誤解,這確實是錯誤的。現在它完美的作品:) –