Пример #1
0
    def setPicking(self, tf):
        """
        Controls glnames-as-color drawing mode for mouseover picking.

        There seems to be no way to access the GL name
        stack in shaders.  Instead, for mouseover, draw shader
        primitives with glnames as colors in glRenderMode(GL_RENDER),
        then read back the pixel color (glname) and depth value.

        @param tf: Boolean, draw glnames-as-color if True.
        """
        # Shader needs to be active to set uniform variables.
        wasActive = self._active
        if not wasActive:
            self.setActive(True)
            pass

        glUniform1iARB(self._uniform("draw_for_mouseover"), int(tf))

        if not wasActive:
            self.setActive(False)
            pass
        return
Пример #2
0
    def setPicking(self, tf):
        """
        Controls glnames-as-color drawing mode for mouseover picking.

        There seems to be no way to access the GL name
        stack in shaders.  Instead, for mouseover, draw shader
        primitives with glnames as colors in glRenderMode(GL_RENDER),
        then read back the pixel color (glname) and depth value.

        @param tf: Boolean, draw glnames-as-color if True. 
        """
        # Shader needs to be active to set uniform variables.
        wasActive = self._active
        if not wasActive:
            self.setActive(True)
            pass

        glUniform1iARB(self._uniform("draw_for_mouseover"), int(tf))

        if not wasActive:
            self.setActive(False)
            pass
        return
Пример #3
0
    def setupTransforms(self, transforms):
        # note: this is only called from test_drawing.py (as of before 090302)
        """
        Fill a block of transforms.

        Depending on the setting of TEXTURE_XFORMS and UNIFORM_XFORMS, the
        transforms are either in texture memory, or in a uniform array of mat4s
        ("constant memory"), or unsupported (error if we need any here).

        @param transforms: A list of transform matrices, where each transform is
            a flattened list (or Numpy array) of 16 numbers.
        """
        self.n_transforms = nTransforms = len(transforms)

        if not self.supports_transforms():
            assert not nTransforms, "%r doesn't support transforms" % self
            return
        
        self.setActive(True)                # Must activate before setting uniforms.
        
        assert self._has_uniform("n_transforms") # redundant with following
        glUniform1iARB(self._uniform("n_transforms"), self.n_transforms)

        # The shader bypasses transform logic if n_transforms is 0.
        # (Then location coordinates are in global modeling coordinates.)
        if nTransforms > 0:
            if UNIFORM_XFORMS:
                # Load into constant memory.  The GL_EXT_bindable_uniform
                # extension supports sharing this array of mat4s through a VBO.
                # XXX Need to bank-switch this data if more than N_CONST_XFORMS.
                C_transforms = numpy.array(transforms, dtype = numpy.float32)
                glUniformMatrix4fvARB(self._uniform("transforms"),
                                      # Don't over-run the array size.
                                      min(len(transforms), N_CONST_XFORMS),
                                      GL_TRUE, # Transpose.
                                      C_transforms)
            elif TEXTURE_XFORMS:
                # Generate a texture ID and bind the texture unit to it.
                self.transform_memory = glGenTextures(1)
                glBindTexture(GL_TEXTURE_2D, self.transform_memory)
                ## These seem to have no effect with a vertex shader.
                ## glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
                ## glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
                # XXX Needed? glEnable(GL_TEXTURE_2D)

                # Load the transform data into the texture.
                #
                # Problem: SIGSEGV kills Python in gleTextureImagePut under
                # glTexImage2D with more than 250 transforms (16,000 bytes.)
                # Maybe there's a 16-bit signed size calculation underthere, that's
                # overflowing the sign bit... Work around by sending transforms to
                # the texture unit in batches with glTexSubImage2D.)
                glTexImage2D(GL_TEXTURE_2D, 0, # Level zero - base image, no mipmap.
                             GL_RGBA32F_ARB,   # Internal format is floating point.
                             # Column major storage: width = N, height = 4 * RGBA.
                             nTransforms, 4 * 4, 0, # No border.
                             # Data format and type, null pointer to allocate space.
                             GL_RGBA, GL_FLOAT, None)
                # XXX Split this off into a setTransforms method.
                batchSize = 250
                nBatches = (nTransforms + batchSize-1) / batchSize
                for i in range(nBatches):
                    xStart = batchSize * i
                    xEnd = min(nTransforms, xStart + batchSize)
                    xSize = xEnd - xStart
                    glTexSubImage2D(GL_TEXTURE_2D, 0,
                                    # Subimage x and y offsets and sizes.
                                    xStart, 0, xSize, 4 * 4,
                                    # List of matrices is flattened into a sequence.
                                    GL_RGBA, GL_FLOAT, transforms[xStart:xEnd])
                    continue
                # Read back to check proper loading.
                if CHECK_TEXTURE_XFORM_LOADING:
                    mats = glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT)
                    nMats = len(mats)
                    print "setupTransforms\n[[",
                    for i in range(nMats):
                        nElts = len(mats[i])
                        perLine = 8
                        nLines = (nElts + perLine-1) / perLine
                        for line in range(nLines):
                            jStart = perLine * line
                            jEnd = min(nElts, jStart + perLine)
                            for j in range(jStart, jEnd):
                                print "%.2f" % mats[i][j],
                                continue
                            if line < nLines-1:
                                print "\n  ",
                                pass
                        if i < nMats-1:
                            print "]\n [",
                            pass
                        continue
                    print "]]"
                pass
            else:
                # should never happen if SUPPORTS_XFORMS is defined correctly
                assert 0, "can't setupTransforms unless UNIFORM_XFORMS or TEXTURE_XFORMS is set"
            pass
        self.setActive(False)                # Deactivate again.
        return
Пример #4
0
    def setupDraw(self, highlighted = False, selected = False,
             patterning = True, highlight_color = None, opacity = 1.0):
        """
        Set up for hover-highlighting and selection drawing styles.
        There is similar code in CSDL.draw(), which has similar arguments.

        XXX Does Solid and halo now, need to implement patterned drawing too.
        """
        # Shader needs to be active to set uniform variables.
        wasActive = self._active
        if not wasActive:
            self.setActive(True)
            pass

        patterned_highlighting = (False and # XXX
                                  patterning and
                                  isPatternedDrawing(highlight = highlighted))
           # note: patterned_highlighting variable is not yet used here [bruce 090304 comment]
           
        halo_selection = (selected and
                          env.prefs[selectionColorStyle_prefs_key] == SS_HALO)
        halo_highlighting = (highlighted and
                             env.prefs[hoverHighlightingColorStyle_prefs_key] ==
                             HHS_HALO)

        # Halo drawing style is used for hover-highlighing and halo-selection.
        drawing_style = DS_NORMAL       # Solid drawing by default.
        if halo_highlighting or halo_selection:
            drawing_style = DS_HALO

            # Halo drawing was first implemented with wide-line drawing, which
            # extends to both sides of the polygon edge.  The halo is actually
            # half the wide-line width that is specified by the setting.
            # XXX The setting should be changed to give the halo width instead.
            halo_width = env.prefs[haloWidth_prefs_key] / 2.0

            # The halo width is specified in viewport pixels, as is the window
            # width the viewport transform maps onto.  In post-projection and
            # clipping normalized device coords (+-1), it's a fraction of the
            # window half-width of 1.0 .
            ndc_halo_width = halo_width / (self.window_width / 2.0)
            glUniform1fARB(self._uniform("ndc_halo_width"), ndc_halo_width)

        elif highlighted or selected:
            drawing_style = DS_NORMAL   # Non-halo highlighting or selection.
        glUniform1iARB(self._uniform("drawing_style"), drawing_style)

        # Color for selection or highlighted drawing.
        override_color = None
        if highlighted:
            if highlight_color is None: # Default highlight color.
                override_color = env.prefs[hoverHighlightingColor_prefs_key]
            else:                       # Highlight color passed as an argument.
                override_color = highlight_color
        elif selected:
            override_color = env.prefs[selectionColor_prefs_key]
            pass
        if override_color:
            if len(override_color) == 3:
                override_color += (opacity,)
                pass
            glUniform4fvARB(self._uniform("override_color"), 1, override_color)
            pass

        if not wasActive:
            self.setActive(False)
            pass
        return
Пример #5
0
    def configShader(self, glpane):
        """
        Fill in uniform variables in the shader self, before using it to draw.

        @param glpane: The current glpane, containing NE1 graphics context
            information related to the drawing environment. This is used to
            find proper values for uniform variables we set in the shader.
        """
        # Can't do anything good after an error loading the shader programs.
        if self.error:
            return

        # Shader needs to be active to set uniform variables.
        wasActive = self._active
        if not wasActive:
            self.setActive(True)
            pass

        # Debugging control.
        if self._has_uniform_debug_code:
            # review: use _has_uniform("debug_code") instead?
            glUniform1iARB(
                self._uniform("debug_code"),
                int(debug_pref("GLPane: shader debug graphics?",
                               Choice_boolean_False, prefs_key = True)))

        # Default override_opacity, multiplies the normal color alpha component.
        glUniform1fARB(self._uniform("override_opacity"), 1.0)

        # Russ 081208: Consider caching the glpane pointer.  GLPane_minimal
        # inherits from QGLWidget, which includes the OpenGL graphics context.
        # Currently we share 'display list context' and related information
        # across two kinds of OpenGL contexts, the main GLPane and the
        # ThumbViews used to select atom types, show clipboard parts, and maybe
        # more.  In the future it may be more complicated.  Then we may need to
        # be more specific about accounting for what's in particular contexts.

        # XXX Hook in full NE1 lighting scheme and material settings.
        # Material is [ambient, diffuse, specular, shininess].
        glUniform4fvARB(self._uniform("material"), 1, [0.3, 0.6, 0.5, 20.0])
        glUniform1iARB(self._uniform("perspective"), (1, 0)[glpane.ortho])

        # See GLPane._setup_projection().
        vdist = glpane.vdist
        # See GLPane_minimal.setDepthRange_Normal().
        near = vdist * (glpane.near + glpane.DEPTH_TWEAK)
        far = vdist * glpane.far
        glUniform4fvARB(self._uniform("clip"), 1,
                        [near, far, 0.5*(far + near), 1.0/(far - near)])
        # The effect of setDepthRange_Highlighting() is done as the shaders
        # set the gl_FragDepth during a highlighted drawing style.
        glUniform1fARB(self._uniform("DEPTH_TWEAK"), glpane.DEPTH_TWEAK)

        # Pixel width of window for halo drawing calculations.
        self.window_width = glpane.width

        # Single light for now.
        # XXX Get NE1 lighting environment state.
        glUniform4fvARB(self._uniform("intensity"), 1, [1.0, 0.0, 0.0, 0.0])
        light0 = A([-1.0, 1.0, 1.0])
        glUniform3fvARB(self._uniform("light0"), 1, light0)
        # Blinn shading highlight vector, halfway between the light and the eye.
        eye = A([0.0, 0.0, 1.0])
        halfway0 = norm((eye + light0) / 2.0)
        glUniform3fvARB(self._uniform("light0H"), 1, halfway0)

        if not wasActive:
            self.setActive(False)
        return
Пример #6
0
    def setupTransforms(self, transforms):
        # note: this is only called from test_drawing.py (as of before 090302)
        """
        Fill a block of transforms.

        Depending on the setting of TEXTURE_XFORMS and UNIFORM_XFORMS, the
        transforms are either in texture memory, or in a uniform array of mat4s
        ("constant memory"), or unsupported (error if we need any here).

        @param transforms: A list of transform matrices, where each transform is
            a flattened list (or Numpy array) of 16 numbers.
        """
        self.n_transforms = nTransforms = len(transforms)

        if not self.supports_transforms():
            assert not nTransforms, "%r doesn't support transforms" % self
            return

        self.setActive(True)                # Must activate before setting uniforms.

        assert self._has_uniform("n_transforms") # redundant with following
        glUniform1iARB(self._uniform("n_transforms"), self.n_transforms)

        # The shader bypasses transform logic if n_transforms is 0.
        # (Then location coordinates are in global modeling coordinates.)
        if nTransforms > 0:
            if UNIFORM_XFORMS:
                # Load into constant memory.  The GL_EXT_bindable_uniform
                # extension supports sharing this array of mat4s through a VBO.
                # XXX Need to bank-switch this data if more than N_CONST_XFORMS.
                C_transforms = numpy.array(transforms, dtype = numpy.float32)
                glUniformMatrix4fvARB(self._uniform("transforms"),
                                      # Don't over-run the array size.
                                      min(len(transforms), N_CONST_XFORMS),
                                      GL_TRUE, # Transpose.
                                      C_transforms)
            elif TEXTURE_XFORMS:
                # Generate a texture ID and bind the texture unit to it.
                self.transform_memory = glGenTextures(1)
                glBindTexture(GL_TEXTURE_2D, self.transform_memory)
                ## These seem to have no effect with a vertex shader.
                ## glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
                ## glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
                # XXX Needed? glEnable(GL_TEXTURE_2D)

                # Load the transform data into the texture.
                #
                # Problem: SIGSEGV kills Python in gleTextureImagePut under
                # glTexImage2D with more than 250 transforms (16,000 bytes.)
                # Maybe there's a 16-bit signed size calculation underthere, that's
                # overflowing the sign bit... Work around by sending transforms to
                # the texture unit in batches with glTexSubImage2D.)
                glTexImage2D(GL_TEXTURE_2D, 0, # Level zero - base image, no mipmap.
                             GL_RGBA32F_ARB,   # Internal format is floating point.
                             # Column major storage: width = N, height = 4 * RGBA.
                             nTransforms, 4 * 4, 0, # No border.
                             # Data format and type, null pointer to allocate space.
                             GL_RGBA, GL_FLOAT, None)
                # XXX Split this off into a setTransforms method.
                batchSize = 250
                nBatches = (nTransforms + batchSize-1) / batchSize
                for i in range(nBatches):
                    xStart = batchSize * i
                    xEnd = min(nTransforms, xStart + batchSize)
                    xSize = xEnd - xStart
                    glTexSubImage2D(GL_TEXTURE_2D, 0,
                                    # Subimage x and y offsets and sizes.
                                    xStart, 0, xSize, 4 * 4,
                                    # List of matrices is flattened into a sequence.
                                    GL_RGBA, GL_FLOAT, transforms[xStart:xEnd])
                    continue
                # Read back to check proper loading.
                if CHECK_TEXTURE_XFORM_LOADING:
                    mats = glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT)
                    nMats = len(mats)
                    print "setupTransforms\n[[",
                    for i in range(nMats):
                        nElts = len(mats[i])
                        perLine = 8
                        nLines = (nElts + perLine-1) / perLine
                        for line in range(nLines):
                            jStart = perLine * line
                            jEnd = min(nElts, jStart + perLine)
                            for j in range(jStart, jEnd):
                                print "%.2f" % mats[i][j],
                                continue
                            if line < nLines-1:
                                print "\n  ",
                                pass
                        if i < nMats-1:
                            print "]\n [",
                            pass
                        continue
                    print "]]"
                pass
            else:
                # should never happen if SUPPORTS_XFORMS is defined correctly
                assert 0, "can't setupTransforms unless UNIFORM_XFORMS or TEXTURE_XFORMS is set"
            pass
        self.setActive(False)                # Deactivate again.
        return
Пример #7
0
    def setupDraw(self, highlighted = False, selected = False,
             patterning = True, highlight_color = None, opacity = 1.0):
        """
        Set up for hover-highlighting and selection drawing styles.
        There is similar code in CSDL.draw(), which has similar arguments.

        XXX Does Solid and halo now, need to implement patterned drawing too.
        """
        # Shader needs to be active to set uniform variables.
        wasActive = self._active
        if not wasActive:
            self.setActive(True)
            pass

        patterned_highlighting = (False and # XXX
                                  patterning and
                                  isPatternedDrawing(highlight = highlighted))
           # note: patterned_highlighting variable is not yet used here [bruce 090304 comment]

        halo_selection = (selected and
                          env.prefs[selectionColorStyle_prefs_key] == SS_HALO)
        halo_highlighting = (highlighted and
                             env.prefs[hoverHighlightingColorStyle_prefs_key] ==
                             HHS_HALO)

        # Halo drawing style is used for hover-highlighing and halo-selection.
        drawing_style = DS_NORMAL       # Solid drawing by default.
        if halo_highlighting or halo_selection:
            drawing_style = DS_HALO

            # Halo drawing was first implemented with wide-line drawing, which
            # extends to both sides of the polygon edge.  The halo is actually
            # half the wide-line width that is specified by the setting.
            # XXX The setting should be changed to give the halo width instead.
            halo_width = env.prefs[haloWidth_prefs_key] / 2.0

            # The halo width is specified in viewport pixels, as is the window
            # width the viewport transform maps onto.  In post-projection and
            # clipping normalized device coords (+-1), it's a fraction of the
            # window half-width of 1.0 .
            ndc_halo_width = halo_width / (self.window_width / 2.0)
            glUniform1fARB(self._uniform("ndc_halo_width"), ndc_halo_width)

        elif highlighted or selected:
            drawing_style = DS_NORMAL   # Non-halo highlighting or selection.
        glUniform1iARB(self._uniform("drawing_style"), drawing_style)

        # Color for selection or highlighted drawing.
        override_color = None
        if highlighted:
            if highlight_color is None: # Default highlight color.
                override_color = env.prefs[hoverHighlightingColor_prefs_key]
            else:                       # Highlight color passed as an argument.
                override_color = highlight_color
        elif selected:
            override_color = env.prefs[selectionColor_prefs_key]
            pass
        if override_color:
            if len(override_color) == 3:
                override_color += (opacity,)
                pass
            glUniform4fvARB(self._uniform("override_color"), 1, override_color)
            pass

        if not wasActive:
            self.setActive(False)
            pass
        return
Пример #8
0
    def configShader(self, glpane):
        """
        Fill in uniform variables in the shader self, before using it to draw.

        @param glpane: The current glpane, containing NE1 graphics context
            information related to the drawing environment. This is used to
            find proper values for uniform variables we set in the shader.
        """
        # Can't do anything good after an error loading the shader programs.
        if self.error:
            return

        # Shader needs to be active to set uniform variables.
        wasActive = self._active
        if not wasActive:
            self.setActive(True)
            pass

        # Debugging control.
        if self._has_uniform_debug_code:
            # review: use _has_uniform("debug_code") instead?
            glUniform1iARB(
                self._uniform("debug_code"),
                int(debug_pref("GLPane: shader debug graphics?",
                               Choice_boolean_False, prefs_key = True)))

        # Default override_opacity, multiplies the normal color alpha component.
        glUniform1fARB(self._uniform("override_opacity"), 1.0)

        # Russ 081208: Consider caching the glpane pointer.  GLPane_minimal
        # inherits from QGLWidget, which includes the OpenGL graphics context.
        # Currently we share 'display list context' and related information
        # across two kinds of OpenGL contexts, the main GLPane and the
        # ThumbViews used to select atom types, show clipboard parts, and maybe
        # more.  In the future it may be more complicated.  Then we may need to
        # be more specific about accounting for what's in particular contexts.

        # XXX Hook in full NE1 lighting scheme and material settings.
        # Material is [ambient, diffuse, specular, shininess].
        glUniform4fvARB(self._uniform("material"), 1, [0.3, 0.6, 0.5, 20.0])
        glUniform1iARB(self._uniform("perspective"), (1, 0)[glpane.ortho])

        # See GLPane._setup_projection().
        vdist = glpane.vdist
        # See GLPane_minimal.setDepthRange_Normal().
        near = vdist * (glpane.near + glpane.DEPTH_TWEAK)
        far = vdist * glpane.far
        glUniform4fvARB(self._uniform("clip"), 1,
                        [near, far, 0.5*(far + near), 1.0/(far - near)])
        # The effect of setDepthRange_Highlighting() is done as the shaders
        # set the gl_FragDepth during a highlighted drawing style.
        glUniform1fARB(self._uniform("DEPTH_TWEAK"), glpane.DEPTH_TWEAK)

        # Pixel width of window for halo drawing calculations.
        self.window_width = glpane.width

        # Single light for now.
        # XXX Get NE1 lighting environment state.
        glUniform4fvARB(self._uniform("intensity"), 1, [1.0, 0.0, 0.0, 0.0])
        light0 = A([-1.0, 1.0, 1.0])
        glUniform3fvARB(self._uniform("light0"), 1, light0)
        # Blinn shading highlight vector, halfway between the light and the eye.
        eye = A([0.0, 0.0, 1.0])
        halfway0 = norm((eye + light0) / 2.0)
        glUniform3fvARB(self._uniform("light0H"), 1, halfway0)

        if not wasActive:
            self.setActive(False)
        return