【问题标题】:glx opengl gtk python and alpha channels / blendingglx opengl gtk python和alpha通道/混合
【发布时间】:2013-09-19 11:55:59
【问题描述】:

我有下面的示例代码,是从一个更大的项目中简化而来的。我一直在尝试使 alpha 通道工作我启用了混合并使用 pygame 编写了一个类似的示例。如何设置 opengl 以使用 glx 上下文似乎停止混合工作,我觉得我需要为 gl 上下文设置启用一些参数,但无法找出该参数是什么。

关于为什么这不起作用的任何建议,我已经尝试过两台不同的机器,一台使用高端 radeon,另一台使用英特尔显卡,但是两者都做同样的事情。

#blending is not working any ideas why ? 
import sys
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL import GLX
from OpenGL.raw._GLX import struct__XDisplay
from OpenGL import GL
from ctypes import *

import Xlib
from Xlib.display import Display
from gi.repository import Gtk, GdkX11, Gdk


class gtkgl:
    """ these method do not seem to exist in python x11 library lets exploit the c methods """
    xlib = cdll.LoadLibrary('libX11.so')
    xlib.XOpenDisplay.argtypes = [c_char_p]
    xlib.XOpenDisplay.restype = POINTER(struct__XDisplay)
    xdisplay = xlib.XOpenDisplay("")
    display = Xlib.display.Display()
    attrs = []

    xwindow_id = None
    width = height = 200

    def __init__(self):
        """ lets setup are opengl settings and create the context for our window """
        self.add_attribute(GLX.GLX_RGBA, True)
        self.add_attribute(GLX.GLX_RED_SIZE, 1)
        self.add_attribute(GLX.GLX_GREEN_SIZE, 1)
        self.add_attribute(GLX.GLX_BLUE_SIZE, 1)
        self.add_attribute(GLX.GLX_ALPHA_SIZE, 1)
        self.add_attribute(GLX.GLX_DOUBLEBUFFER, 0)


        glClearDepth(1.0)
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glShadeModel(GL_SMOOTH)
        glDepthFunc(GL_LEQUAL)
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
        glEnable(GL_COLOR_MATERIAL)
        glEnable(GL_LIGHTING)
        glEnable(GL_LIGHT0)        
        glLight(GL_LIGHT0, GL_POSITION,  (0, 1, 1, 0)) 


        xvinfo = GLX.glXChooseVisual(self.xdisplay, self.display.get_default_screen(), self.get_attributes())
        configs = GLX.glXChooseFBConfig(self.xdisplay, 0, None, byref(c_int()))
        self.context = GLX.glXCreateContext(self.xdisplay, xvinfo, None, True)

    def add_attribute(self, setting, value):
        """just to nicely add opengl parameters"""
        self.attrs.append(setting)
        self.attrs.append(value)

    def get_attributes(self):
        """ return our parameters in the expected structure"""
        attrs = self.attrs + [0, 0]
        return (c_int * len(attrs))(*attrs)

    def configure(self, wid):
        """  """
        self.xwindow_id = GdkX11.X11Window.get_xid(wid)
        if(not GLX.glXMakeCurrent(self.xdisplay, self.xwindow_id, self.context)):
            print 'failed'
        glViewport(0, 0, self.width, self.height)

    def draw_start(self):
        """make cairo context current for drawing"""
        if(not GLX.glXMakeCurrent(self.xdisplay, self.xwindow_id, self.context)):
            print "failed"

    def draw_finish(self):
        """swap buffer when we have finished drawing"""
        GLX.glXSwapBuffers(self.xdisplay, self.xwindow_id)

    def test(self):
        """Test method to draw something so we can make sure opengl is working and we can see something"""
        self.draw_start()

        glClearColor(0.0, 0.0, 0.0, 0.0)
        glClear(GL_COLOR_BUFFER_BIT)
        glBegin(GL_TRIANGLES)
        glIndexi(0)
        glColor4f(1.0, 0.0, 0.0, 0.2)
        glVertex2i(0, 1)
        glIndexi(0)
        glColor4f(0.0, 1.0, 0.0, 0.2)
        glVertex2i(-1, -1)
        glIndexi(0)
        glColor4f(0.0, 0.0, 1.0, 1.0)
        glVertex2i(1, -1)
        glEnd()

        self.draw_finish()


class gui():
    glwrap = gtkgl()

    def __init__(self):
        self.window = Gtk.Window()
        self.window.realize()
        self.window.resize(self.glwrap.width, self.glwrap.height)
        self.window.set_resizable(True)
        self.window.set_reallocate_redraws(True)
        self.window.set_title("GTK3 with opengl")
        self.window.connect('delete_event', Gtk.main_quit)
        self.window.connect('destroy', lambda quit: Gtk.main_quit())

        self.drawing_area = Gtk.DrawingArea()
        self.drawing_area.connect('configure_event', self.on_configure_event)
        self.drawing_area.connect('draw', self.on_draw)
        self.drawing_area.set_double_buffered(False)
        self.drawing_area.set_size_request(self.glwrap.width, self.glwrap.height)

        self.window.add(self.drawing_area)
        self.window.show_all()

    def on_configure_event(self, widget, event):
        self.glwrap.configure(widget.get_window())
        return True

    def on_draw(self, widget, context):
        self.glwrap.test()


def main():
    g = gui()
    Gtk.main()

if __name__ == '__main__':
    main()

【问题讨论】:

    标签: python opengl gtk alpha glx


    【解决方案1】:

    这不是 OpenGL 上下文缺少某些东西(我的意思是在创建时)。您根本没有启用混合。您需要在绘制需要混合的图元之前添加glEnable(GL_BLEND);

    顺便说一句:使用 1 位作为 RGB 通道的最低要求可能会产生不希望的结果。使用至少 5 位(用于 16 位显示器)或更好的 8 位。此外,您不需要主帧缓冲区上的 alpha 通道来进行混合。因此,除非您想在合成器上创建透明窗口,否则您应该在窗口的帧缓冲区上使用 0 alpha 位。

    【讨论】:

    • 有用的信息@datenwolf 谢谢。以上如何在初始化中有 glEnable(GL_BLEND) 但代码不起作用,与 pygame 相同的代码设置确实起作用,这让我相信它是帧缓冲区。但有趣的是我不需要帧缓冲区的 alpha 通道。但这确实让我现在想知道原因可能是什么。我用几个值尝试了 rgb 通道,但是这清除了一些负载 :)
    • @Oly:您在没有 OpenGL 上下文的情况下进行 OpenGL 调用。这就是为什么。只有在您调用 glXMakeCurrent 之后,OpenGL 调用才会生效。此外,您应该将 OpenGL 操作(包括 glEnable 调用)仅放在绘图代码中,而不要放在其他地方。 (例外:纹理和 VBO 的加载)。
    • 您在配置方法中移动调用非常正确,非常感谢@datenwolf
    猜你喜欢
    • 2015-03-30
    • 2011-12-14
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 2015-07-25
    • 2012-12-15
    • 1970-01-01
    相关资源
    最近更新 更多