python - OpenGL 4.2+ and shader_image_load_store for 3D textures not working? -
i trying figure out why i'm not able write 3d textures using (now built-in) shader_image_load_store extension.
i created 2 simple examples (in python make easier): 1 write 2d texture, works, , 1 write 3d texture not work
the (working) 2d version following:
#! /usr/bin/env python pyqt4 import qtgui, qtcore pyqt4.qtopengl import * opengl.gl import * 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 none): self.texcolortexture = glgentextures( 1 ) if (self.fborendering 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 not none): gldeleteframebuffers(1,self.fborendering) self.fboaccumulation = none if (self.texcolortexture not none): gldeletetextures( self.texcolortexture ) self.texcolortexture = none def initcolorvolume(self): if (self.texcolorvolume 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) 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 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 volume self.fillvolume(false) #slice 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 not self.uwidth) or (heightinpixels 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_())
while non-working 3d version following:
#! /usr/bin/env python pyqt4 import qtgui, qtcore pyqt4.qtopengl import * opengl.gl import * 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 none): self.texcolortexture = glgentextures( 1 ) if (self.fborendering 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 not none): gldeleteframebuffers(1,self.fborendering) self.fboaccumulation = none if (self.texcolortexture not none): gldeletetextures( self.texcolortexture ) self.texcolortexture = none def initcolorvolume(self): if (self.texcolorvolume 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) 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 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 volume #self.fillvolume(false) #slice 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 not self.uwidth) or (heightinpixels 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 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_())
the code not neat, because copy/pasted/modified older pyopengl code had. problem values written in 3d texture make absolute no sense. ran using latest version of pyopengl (the experimental one), quadro k5000 , latest drivers (332.76), provide support opengl 4.4 .
i'm not sure might doing wrong, because haven't found many examples of writing 3d textures (actually none, , looked in latest version of red book)
can enlighten me?
your problem here in frag shader:
layout(size4x32, binding=0) writeonly uniform image3d volcolorvolume;
you binding 3d texture via
glbindimagetexture(0,self.texcolorvolume,0,gl_false,0,gl_write_only,gl_rgba32f);
let me quote opengl 4.4 spec, section 8.26 "texture image loads , stores" (emphasis mine):
if texture identified texture one-dimensional array, two-dimensional array, three-dimensional, cube map, cube map array, or two-dimensional multisample array texture, possible bind either entire texture level or single layer or face of texture level. if layered true, entire level bound. if layered false, single layer identified layer bound. when layered false, single bound layer treated different texture target image accesses:
- one-dimensional array texture layers treated one-dimensional textures;
- two-dimensional array, three-dimensional, cube map, cube map array texture layers treated two-dimensional textures; and
- two-dimensional multisample array textures treated two-dimensional multisample textures.
so, if bind 1 layer of 3d texture layered
parameter set gl_false
(as doing), act if 2d texture, either use image2d
, access 2d coords, or bind layered
set gl_true
, valid range of layers able write specific layer/slices of texture using image3d
, 3-dimensional image coordinates.
Comments
Post a Comment