Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Ruby: GUI > Вывод OpenGL через GTK+2 на Ruby


Автор: Camel 10.1.2009, 16:10
Пытаюсь освоится с Ruby, GTK+2 и OpenGL. Легче всего с Ruby, с GTK+2 тоже всё не сложно, благодаря http://ruby-gnome2.sourceforge.jp/, а вот с OpenGL проблема. Пытаюсь написать http://glprogramming.com/red/chapter01.html из учебника по OpenGL известного как http://glprogramming.com/red/. DrawingArea чёрным заполняется, но вот белый квадрат не рисуется. Подскажите как правильно. Может у кого-нибудь есть работающая программа выводящая OpenGL'ную графику в GTK'шном окне? 
Код

#!/usr/bin/env ruby
# main.rb

$KCODE='U'
require 'glconfig'
require 'gtkglext'
include Gl,Glu,Glut

class GLDrawingArea < Gtk::DrawingArea
  def initialize(glconfig)
    super()
    set_gl_capability(glconfig)
  end
end

window = Gtk::Window.new("OpenGL Drawing Area")

# Add VBox for placing drawing area and Quit button. 
vbox = Gtk::VBox.new(false, 0)
window.add(vbox)

# Set GL configuration.
glconfig = create_glconfig
examine_gl_config_attrib(glconfig) # Puts OpenGL configuration on the screen.

# Add drawing area. 
area = GLDrawingArea.new(glconfig)
area.set_size_request(400,400)
area.signal_connect("expose_event") do 
# GL code. 
  area.gl_drawable.gl_begin(area.gl_context) do
# Clearing the screen.
    glClearColor(0.0, 0.0, 0.0, 0.0)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0)
    glClear(GL_COLOR_BUFFER_BIT)
# Setting drawing color to white. 
    glColor(1.0, 1.0, 1.0)
    glBegin(GL_POLYGON)
# Setting 4 vertices of a square. 
      glVertex3f(0.25, 0.25, 0.0)
      glVertex3f(0.75, 0.25, 0.0)
      glVertex3f(0.75, 0.75, 0.0)
      glVertex3f(0.25, 0.75, 0.0)
    glEnd()
# Showing on the screen. 
    area.gl_drawable.swap_buffers
  end
end
vbox.pack_start(area, true, true, 0)

# Add Quit button. 
button = Gtk::Button.new("Quit")
button.signal_connect("clicked") { Gtk.main_quit }
vbox.pack_start(button, false, false, 0)

# Show window on the screen. 
window.show_all
Gtk.main

Функции скопировал из этого http://ruby-gnome2.sourceforge.jp/hiki.cgi?Logo. Да и вообще много чего там подсмотрел, но заставить отрисоваться белый квадрат не получается. 
Код

# glconfig.b
$KCODE='U'
require 'gtkglext'
  def create_glconfig

    # Try double-buffered visual

    glconfig = Gdk::GLConfig.new(Gdk::GLConfig::MODE_RGB|

                                 Gdk::GLConfig::MODE_DEPTH|

                                 Gdk::GLConfig::MODE_DOUBLE)

    

    unless glconfig

      puts "*** Cannot find the double-buffered visual."

      puts "*** Trying single-buffered visual."

      

      # Try single-buffered visual

      glconfig = Gdk::GLConfig.new(Gdk::GL::MODE_RGB|

                                   Gdk::GL::MODE_DEPTH)

      raise  "No appropriate OpenGL-capable visual found." unless 
glconfig

    end

    glconfig

  end

Вот что имею
http://img132.imageshack.us/img132/2728/squareyx9.png

Автор: kemiisto 17.1.2009, 00:27
Camel, вот возьмите рабочий шаблон:
Код

#!/usr/bin/env ruby
require 'gtkglext'

## -----------------------------------------------------------------------------
## A generic class for OpenGL application functions.
## -----------------------------------------------------------------------------
class GLRender
  attr_reader :fov

  def initialize(fov = 90.0)
    @fov = fov
  end

  ## Initialise OpenGL state for 3D rendering.
  def init()
    GL.ShadeModel(GL::SMOOTH)
    GL.Enable(GL::DEPTH_TEST)
    GL.DepthFunc(GL::LEQUAL)
    GL.ClearColor(0.0, 0.0, 0.0, 0.0)
    GL.Hint(GL::PERSPECTIVE_CORRECTION_HINT, GL::NICEST)
    true
  end

  ## Resize OpenGL viewport.
  def resize(width, height)
    GL.Viewport(0, 0, width, height)

    GL.MatrixMode(GL::PROJECTION)
    GL.LoadIdentity()
    GLU.Perspective(@fov, width.to_f() / height.to_f(), 0.1, 1024.0)
    
    GL.MatrixMode(GL::MODELVIEW)
    GL.LoadIdentity()
  end

  ## Render OpenGL scene.
  def draw()
    GL.Clear(GL::COLOR_BUFFER_BIT | GL::DEPTH_BUFFER_BIT)
    GL.LoadIdentity()

    ## Scene view translation. ---------------------------------------------->>>
    GL.Translate(0.0, 0.0, -1.0)
    GL.Rotate(0.0, 0.0, 0.0, 0.0)
    ## -------------------------------------------------------------------------

    ## Scene Rendering Code ------------------------------------------------->>>
    GL.Begin(GL::POLYGON)
      GL.Vertex3f(0.25, 0.25, 0.0)
      GL.Vertex3f(0.75, 0.25, 0.0)
      GL.Vertex3f(0.75, 0.75, 0.0)
      GL.Vertex3f(0.25, 0.75, 0.0)
    GL.End()
    ## -------------------------------------------------------------------------

    GL.Flush()
  end
end

## -----------------------------------------------------------------------------
## A GtkDrawingArea widget with OpenGL rendering capabilities.
## -----------------------------------------------------------------------------
class GLDrawingArea < Gtk::DrawingArea
  def initialize(width, height, fov, gl_config)
    super()
    set_size_request(width, height)
    set_gl_capability(gl_config)

    ## Create an OpenGL renderer instance.
    @render = GLRender.new(fov)

    ## Signal handler for drawing area initialisation.
    signal_connect_after("realize") do
      gl_begin() { @render.init() }
    end

    ## Signal handler for drawing area reshapes.
    signal_connect_after("configure_event") do
      gl_begin() { @render.resize(allocation.width, allocation.height) }
    end

    ## Signal handler for drawing area expose events.
    signal_connect_after("expose_event") do
      gl_begin() do
        @render.draw()
      end

      gl_drawable.swap_buffers() if gl_drawable.double_buffered?
    end

    ## Add mouse button press/release signal event handlers
    add_events(Gdk::Event::BUTTON_PRESS_MASK |
               Gdk::Event::BUTTON_RELEASE_MASK)

    signal_connect_after("button_press_event") { button_press_event() }
    signal_connect_after("button_release_event") { button_release_event() }
  end

  def gl_begin()
    gl_drawable.gl_begin(gl_context) { yield }
  end

  def button_press_event()
    puts "button_press_event"
    true
  end

  def button_release_event()
    puts "button_release_event"
    true
  end
end

## -----------------------------------------------------------------------------
## Application GUI Main Window Class
## -----------------------------------------------------------------------------
class AppWindow < Gtk::Window
  attr_reader :gl_area

  def initialize(title, width, height, fov, gl_config)
    super(title)

    ## Connect signals to handle keyboard user input.
    signal_connect_after("key_press_event") { key_press_event() }
    signal_connect_after("key_release_event") { key_release_event() }

    ## Create our GL drawing area widget.
    @gl_area = GLDrawingArea.new(width, height, fov, gl_config)

    add(@gl_area)
    show_all()
  end

  def key_press_event()
    puts "key_press_event"
    true
  end

  def key_release_event()
    puts "key_release_event"
    true
  end
end

## -----------------------------------------------------------------------------
## Application Class
## -----------------------------------------------------------------------------
class GtkGLApp
  attr_reader :window

  def initialize(title, width, height, bpp)
    ## Initialise Gtk[GLExt] library.
    Gtk.init()
    Gtk::GL.init()

    ## Obtain a valid OpenGL context configuration.
    gl_config = Gdk::GLConfig.new(Gdk::GLConfig::MODE_DEPTH |
                                  Gdk::GLConfig::MODE_DOUBLE |
                                  Gdk::GLConfig::MODE_RGBA)

    ## Create application main interface window.
    @window = AppWindow.new(title, width, height, 90.0, gl_config)

    @window.signal_connect_after("delete_event") do
      puts "Closing application."
      @window.destroy()
      Gtk.main_quit()
    end
  end

  def main()
    Gtk.main()  ## Enter into Gtk's main event processing loop.
    true
  end
end

## -----------------------------------------------------------------------------
## Application Entry Point
## -----------------------------------------------------------------------------
if $0 == __FILE__
  ## Create new application context.
  context = GtkGLApp.new("Gtk GL Application", 256, 256, 16)
  context.main()  ## Enter into the main execution loop.
end


Собственно сцена отрисовывается вот тут:
Код

    ## Scene Rendering Code ------------------------------------------------->>>
    GL.Begin(GL::POLYGON)
      GL.Vertex3f(0.25, 0.25, 0.0)
      GL.Vertex3f(0.75, 0.25, 0.0)
      GL.Vertex3f(0.75, 0.75, 0.0)
      GL.Vertex3f(0.25, 0.75, 0.0)
    GL.End()
    ## -------------------------------------------------------------------------

Автор: Camel 17.1.2009, 10:50
Я, кстати, ещё нашёл рабочий код в проекте http://rubymars.googlecode.com/. Но пока не причесал его, не выкинул лишнее, поэтому вместо большого белого квадрата посередине рисуется маленький в уголке. Наверное это можно исправить удалив "ненужные" (непонятные мне пока) функции (ну, то есть методы, конечно, но эти методы нужны только для вызова OpenGL'ных функций). 

За шаблон вам, kemiisto, глубокое мерси. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)