![](/img/trans.png)
[英]Ursina engine lit_with_shadows_shader when added to a 3d model the textures disappear
[英]OpenGL 4.2+ and shader_image_load_store for 3D textures not working?
我试图弄清楚为什么我无法使用(现在内置的)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纹理的示例(实际上没有,而且我也在看红皮书的最新版本)
有人可以启发我吗?
您的问题在您的片段着色器中:
layout(size4x32, binding=0) writeonly uniform image3D volColorVolume;
您正在通过绑定3D纹理
glBindImageTexture(0,self.texColorVolume,0,GL_FALSE,0,GL_WRITE_ONLY,GL_RGBA32F);
让我引用OpenGL 4.4规范的第8.26节“纹理图像的加载和存储”(重点是我的):
如果由纹理标识的纹理是一维阵列,二维阵列,三维,立方体贴图,立方体贴图阵列或二维多样本阵列贴图,则可以绑定整个贴图级别或单个贴图层或面的纹理级别。 如果layered为TRUE,则绑定整个级别。 如果layered为FALSE,则仅绑定由layer标识的单个层。 如果layered为FALSE,则将单个绑定层视为图像访问的不同纹理目标:
- 一维阵列纹理层被视为一维纹理;
- 二维阵列, 三维 ,立方体贴图,立方体贴图阵列纹理层被视为二维纹理 ; 和
- 二维多样本数组纹理被视为二维多样本纹理。
所以,如果你只是绑定3D纹理与一层layered
设置参数GL_FALSE
(因为你正在做的),它将作为,如果它仅仅是一个2D纹理,所以要么只使用一个image2D
与2D访问它COORDS,或与它结合layered
设置为GL_TRUE
和层的一个有效范围,你将能够写入到特定层/你的纹理的切片使用image3D
和3维图像的坐标。
您在python中有60个分号。 Python不使用分号。 实际上,我非常确定python是唯一不使用分号的编程语言。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.