OpenGL 4.2+和shader峎image_load_store for 3D纹理不工作?

2024-09-30 22:12:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我想弄清楚为什么我不能用(现在内置的)shader_image_load_store扩展写入3D纹理。在

我创建了两个简单的示例(用python编写),一个用于写入2D纹理,可以使用;另一个用于写入不起作用的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) 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版本时:

^{pr2}$

代码并不特别整洁,这也是因为我复制/粘贴/修改了一些旧的pyopengl代码。 问题是在3D纹理中写入的值完全没有意义。 我使用最新版本的PyOpenGL(实验版)、quadrok5000和最新的驱动程序(332.76)运行它,这些驱动程序也提供了对opengl4.4的支持。在

我不确定我可能做错了什么,也因为我没有发现很多写入3D纹理的例子(实际上没有,我还查阅了最新版本的红皮书)

有人能开导我吗?在


Tags: selfnoneifisdefnotcolorgl
2条回答

你的问题在你的frag着色器中:

layout(size4x32, binding=0) writeonly uniform   image3D volColorVolume;

您正在通过绑定3D纹理

^{pr2}$

让我引用OpenGL 4.4规范第8.26节“纹理图像加载和存储”(emphasis mine):

If the texture identified by texture is a one-dimensional array, two-dimensional array, three-dimensional, cube map, cube map array, or two-dimensional multisample array texture, it is possible to bind either the entire texture level or a single layer or face of the texture level. If layered is TRUE, the entire level is bound. If layered is FALSE, only the single layer identified by layer will be bound. When layered is FALSE, the single bound layer is treated as a different texture target for image accesses:

  • one-dimensional array texture layers are treated as one-dimensional textures;
  • two-dimensional array, three-dimensional, cube map, cube map array texture layers are treated as two-dimensional textures; and
  • two-dimensional multisample array textures are treated as two-dimensional multisample textures.

所以,如果你只是绑定了一个3D纹理层,并将layered参数设置为GL_FALSE(就像你现在所做的那样),它的作用就好像它只是一个2D纹理,所以要么使用image2D并使用2D坐标访问它,或者使用layered设置为GL_TRUE和一个有效的层范围来绑定它,您可以使用image3D和三维图像坐标将其写入纹理的特定层/片中。在

在python中有60个分号。Python不使用分号。事实上,我很确定python是唯一一种不使用分号的编程语言。在

相关问题 更多 >