Vala プログラミング

GNUstep プログラミング

おなが@京都先端科学大

Camlkit & GNUstep OpenGLView

OCamlOpenGL用のライブラリ gles3 を利用して、GNUstep の NSOpenGLView に triangle を描画してみました。shader を使って描画します。
gles3 https://github.com/craff/gles3

[実行結果]

プロジェクト構成

/bin
    /Resources
        MainMenu.gorm
        Info-gnustep.plist
    dune
    app_delegate.ml
    main.ml
    main_window.ml
dune-project
(プロジェクト名).opam


dune

(executable
 (public_name gnustepAppTemplate2)
 (name main)
 (flags -ccopt -L/usr/local/GNUstep/System/Library/Libraries  -cclib -lgnustep-base -cclib -lgnustep-gui)
 (libraries 
    gles3
    camlkitGS.Foundation
    camlkitGS.AppKit
    camlkitGS.camlkit))

(subdir GSApp.app
 (rule
  (deps ../main.exe)
  (targets GSApp)
  (action (copy ../main.exe GSApp))))

(subdir GSApp.app/Resources
  (rule
    (deps ../../Resources/Info-gnustep.plist)
    (targets Info-gnustep.plist)
    (action (progn
      (copy ../../Resources/Info-gnustep.plist Info-gnustep.plist))))
)

(subdir GSApp.app/Resources/MainMenu.gorm
  (rule
    (deps ../../../Resources/MainMenu.gorm/objects.gorm ../../../Resources/MainMenu.gorm/data.classes ../../../Resources/MainMenu.gorm/data.info)
    (targets objects.gorm data.classes data.info)
    (action (progn
       (copy ../../../Resources/MainMenu.gorm/objects.gorm objects.gorm)
       (copy ../../../Resources/MainMenu.gorm/data.classes data.classes)
       (copy ../../../Resources/MainMenu.gorm/data.info data.info))))
)


main.ml

open Foundation
open AppKit
open Camlkit
open Runtime

module Delegate = Appkit_AppDelegate.Create (App_delegate)

let main () =
	let _ = new_object "NSAutoreleasePool"
    and app = NSApplication.self |> NSApplicationClass.sharedApplication
    and argc = Array.length Sys.argv
    and argv =
       Sys.argv
       |> Array.to_list
       |> Objc.(CArray.of_list string)
       |> Objc.CArray.start
    in
    app |> NSApplication.setDelegate (_new_ Delegate._class_);
    app |> NSApplication.activateIgnoringOtherApps true;
     
    _NSApplicationMain argc argv |> exit

let () = main ()


app_delegate.ml

open Foundation
open Runtime
open AppKit

let app_name = "gnustep-app"
let class_name = "MyAppDelegate"

let on_before_start _ = ()

let on_started notification =
   let app = NSNotification.object_ notification in
   let win = Main_window.create app in
   win |> NSWindow.setTitle (new_string app_name);
;;

let on_before_terminate _ = ()

let terminate_on_windows_closed _ = true


main_window.ml

(* NSOpenGLView Triangle *)
open Foundation
open AppKit
open Runtime

open Egl
open Gles3
open Gles3.Type
open Shaders
open Buffers

let w = 400. and h = 400.
let gwidth = ref 400 and gheight = ref 350

let make_glView ~frame =
    let glView =
    _new_ NSOpenGLView.self in
    glView |> NSView.setFrame frame;
    glView

let light_shader =
    ("light_shader",
    [{ name = "vertex_main";
        ty   = gl_vertex_shader;
        src  = "
        in vec3  in_position;
      
        void main()
        {
            gl_Position = vec4(in_position, 1.0);
         }"};
         { name = "fragment_main";
           ty   = gl_fragment_shader;
           src  = "
        out vec4 FragColor;
      
        void main()
        {
            FragColor = vec4(0.0, 0.0, 1.0, 1.0);
          }"};
        ])

let vertices : Gles3.float_bigarray = Buffers.to_float_bigarray
    [| -0.5;-0.5;0.0; 0.0; 0.5;0.0; 0.5;-0.5;0.0; |]

let create app =
    let win =
    alloc NSWindow.self
    |> NSWindow.initWithContentRect
        (CGRect.make ~x: 0. ~y: 0. ~width: w ~height: h)
        ~styleMask: Bitmask.(
            _NSWindowStyleMaskTitled +
            _NSWindowStyleMaskClosable +
            _NSWindowStyleMaskResizable)
        ~backing: _NSBackingStoreBuffered
        ~defer: false
    and glView =
        make_glView
        ~frame: (CGRect.make ~x: 0. ~y: 50. ~width: w ~height: (h -. 50.))
    in
    win
    |> NSWindow.cascadeTopLeftFromPoint (CGPoint.init ~x: 200. ~y: 800.)
    |> ignore;
    win |> NSWindow.makeKeyAndOrderFront nil;

    win |> NSWindow.contentView |> NSView.addSubview glView;
    let glcontext = glView |> NSOpenGLView.openGLContext
    in
        glcontext|> NSOpenGLContext.makeCurrentContext;

        clear_color { r = 0.7; g = 0.7; b = 0.7; a = 1.0 };
        clear [ gl_color_buffer];

        let prg : unit program = compile light_shader in
        let prg = Shaders.float_cst_attr prg "in_position" vertices in
        Shaders.draw_arrays prg gl_triangles 3;

        glcontext |> NSOpenGLContext.flushBuffer;

    win
;;

Resources については、以前の記事参照。