Hızlı Konu Açma

Hızlı Konu Açmak için tıklayınız.

Son Mesajlar

Konulardaki Son Mesajlar

Reklam

Forumda Reklam Vermek İçin Bize Ulaşın

C#'ta OpenGL Kullanımı

YaSa22

Fahri Üye
Fahri Üye
Katılım
12 Temmuz 2014
Mesajlar
2,293
Tepkime puanı
2
Puanları
0
Konum
GTA
OpenGL Nedir ?

OpenGL, en basit anlamıyla grafik donanımına arayüz olan bir yazılımdır. Bu arayüz yüz elli ayrı fonksiyona sahiptir. Bu fonksiyonları kullanarak etkileşimli üç boyutlu (3B, 3D) uygulamalar üretme ihtiyacını giderebilir, nesne tanımlama ve benzeri işlemleri gerçekleştirebiliriz.

OpenGL donanımdan bağımsız birçok farklı donanım düzleminde uygulanabilecek şekilde tasarımlanmıştır. Bu niteliği kazanabilmek için, pencere işlemleri ve kullanıcı girişi işlemlerini yapan komutlar OpenGL’de mevcut değildir. Bunun yerine, pencere işlemleri kullanılan donanımın kontrol edildiği an içerisinde çalıştırılmalıdır. Benzer olarak, OpenGL kütüphanesi üç boyutlu nesneleri modellemede yüksek seviyede fonksiyonlara sahip değildir. Bu tip fonksiyonlarla göreceli olarak karmaşık şekiller, örneğin otomobiller, vücudun bir bölgesi, uçaklar veya moleküller tanımlanabilir. Fakat istenilen model, küçük bir takım geometrik şekillerden hareketle oluşturulabilir-noktalar, çizgiler ve poligonlar gibi-.

OpenGL Komut Dizisi

OpenGL komutları, C#’da, ’gl’ öneki ve baş harfleri büyük olarak yazılan komutu oluşturan diğer kelimelerin birleşiminden oluşmaktadır. Benzer olarak OpenGL’de sabitler ’GL’ ön eki ile başlar ve bütün harfler büyük olacak şekilde kullanılır. Ayrıca ayrı sözcüklerde alt çizgi ile birleştirilir. Aşağıda OpenGL komut örnekleri ve veri tipleri verilmiştir :

Önek
Veri Tipi C Dilinde Karşılığı
OpenGL Tanımı
B8-bit integerSigned char GLbyte
S8-bit integerShortGLshort
İ32-bit integerLongGLint, GLsize
F32-bit floating-pointFloatGLfloat, GLclampf
D64-bit dfloating pointDoubleGLdouble, GLclampf
Ub8-bit unsigned integerUnsigned charGLubyte,GL boolean
Us16-bit unsigned integerUnsigned shortGLushort
Ui32-bitunsigned integerUnsigned longGLuint, GLenum

OpenGL’de Çizim Yapmak

OpenGL’de çizim yapmak için öncelikle çizim öncesi işlemler gerçekleştirilmelidir. İlk olarak ekran temizlenmeli, ardından çizimin rengi belirlemneli, daha sonra ise geometrik şeklin ne olacağı tanımlanmalıdır.

1. Ekranın Temizlenmesi
’GLClear’ fonksiyonunun parametresi, arka planın hangi işleme göre temizleneceğini belirler. Tipik olarak öncelikle temizleme rengi seçilir, daha sonra temizlenmesi gerekli olan tamponlar temizlenir. ’glclearDepth’ fonksiyonu ise ayarlanacak derinlik tamponundaki her bir pikselin değerini belirler.

Tampon
İsmi
Renk Tamponu GL_COLOR_BUFFER_BIT
Derinlik TamponuGL_DEPTH_BUFFER_BIT
Birikim (Accumulator) TamponuGL_ACCUM_BUFFER_BIT
Kalıp (Stencil) TamponuGL_STENCIL_BUFFER_BIT

2. Renk Belirleme
Renk belirlemek için ’glColor3f’ isimli fonksiyon kullanılır. Bu komut üç parametre alır, bu parametrelerin hepsi kayan noktalı sayılardır ve 0.0 ve 1.0 aralığındadır. Parametreler, sırasıyla kırmızı, yeşil ve mavi (RGB) renk bileşenlerinden oluşur. Bu üç değeri renkleri karıştırma olarak düşünebiliriz. Örneğin 0.0 değeri o renk bileşeninden hiç kullanılmayacağı, 1.0 değeri ise o renk bileşeninin tamamen baskın kılılacağı anlamına gelmektedir. Örneğin :

glColor3f(1.0f,0.0f,0.0f);
ifadesi en parlak kırmızı renk sistemini çizim rengi olarak atar. Bu ifadede hiç yeşil veya mavi bileşen yoktur. Tüm bileşenleri sıfır atamak siyah renk, 1.0 atamak beyaz renk, 0.5 atamak ise gri renk anlamına gelir. Aşağıda sekiz renk atama ifadesi görülmektedir :

glColor3f(0.0, 0.0, 0.0); //siyah
glColor3f(1.0, 0.0, 0.0); //kırmızı
glColor3f(0.0, 1.0, 0.0); //yeşil
glColor3f(1.0, 1.0, 0.0); //sarı
glColor3f(0.0, 0.0, 1.0); //mavi
glColor3f(1.0, 0.0, 1.0); //magenta
glColor3f(0.0, 1.0, 1.0); //cyan
glColor3f(1.0, 1.0, 1.0); //beyaz
Aşağıda, renk tayfı kartezyen koordinat sisteminde gösterilmiştir :




3. OpenGL’de Geometrik Şeklin Çizimi
Daha önceden de belirttiğimiz gibi OpenGL’de modelleme, basit geometrik şekillerin çizimine dayanır. Şimdi bunun nasıl yapıldığını inceleyelim. Her bir farklı geometrik şekil ya da nesne glBegin() ve glEnd() fonksiyonları arasına yerleştirilir.

- Nokta, Çizgi ve Poligon belirleme :

OpenGL, çizim yapılırken birden çok nokta, çizgi parçası ve çokgen çizdirilebilmesi için kuvvetli ve kullanılması çok basit çizim araçlarına sahiptir. Matemetiksel olarak nokta, çizgi ve poligonun ne anlama geldiğini biliriz, fakat bu tanımlar OpenGL’de tam olarak böyle değildir. Bilgisayar tabanlı hesaplamaların sonlu duyarlı olmaları sebebiyle bir takım yuvarlama hataları oluşur. Çizgiler, noktalar ve poligonların koordinatlarında bu yuvarlama hatalarından kaynaklanan sapmalar olabilir.


- Nokta Belirleme :

Cisimlerin, yüzeylerin ve kenarların belirtebilmesi için köşe noktalarına ihtiyaç duyulur. OpenGL ve bilgisayar grafiklerinde noktanın genişliğinden söz edilebilir ve bunun için glPointSize() fonksiyonu kullanılarak farklı büyüklükte noktalar tanımlanabilir.

- Çizgiler :

OpenGL’de çizgi terimi, matematikte her iki doğrultuda sonsuz uzunlukta doğru olarak ifade edilen terimin aksine, yalnızca sonsuz uzunluktaki çizgi parçası anlamına gelmektedir.
Birleşmiş, seri halindeki çizgi parçalarını belirtmenin kolay yolları mevcuttur.




- Poligonlar :

Poligonlar tipik olarak iç kısımlarındaki pikseller ile çizilir. Fakat noktalar kümesi olarak da çizilmeleri mümkündür. OpenGL de poligonların kenarları birbirleri ile kesişmezler. Buna matematikte basit poligon adı verilir. Ayrıca OpenGL poligonları konveks yani dışbükey olmalıdır.



- Dörtgenler :

Dörtgenler grafik uygulamalarında yaygın olarak kullanılır. OpenGL kütüphanesinde içi dolu dörtgen çizmek için kullanılan glRect isimli bir fonksiyon bulunmaktadır. Dörtgen bir poligon gibi de çizilebilir.


- Eğriler :

Herhangi bir eğri, çizgi veya yüzey kısa çizgi parçalarından meydana gelen küçük poligonsal alanlar ile oluşturulabilir. Kısa çizgilerin birleşmesi ile elde edilen şekil eğri gibi görünür.



- Köşe Nktalarının Belirlenmesi :

OpenGL’de tüm geometrik nesneler, köşe noktalarından oluşan bir dizi koordinat ile tanımlanır. Bir köşe noktasının belirlenmesi için ’glVertex’ isimli fonksiyon kullanılır. Bu fonksiyon ’glBegin’ ile ’glEnd’ fonksiyon çağrıları arasında kalan bloğa yerleştirilir.

//fonksiyonun kullanımı :
Void glVertex{boyut}{s,i,f,d}[v](koordinatlar);
//boyut 2,3,4 olabilir
//s : short, i : int, f : float, d : double
//v : vektör


glVertex2s(2,3); //2 boyutta kullanımı
glVertex(0.0,0.0,3.1415) //3 boyutlu kullanımı

glVertex3dv(dvect);
glVertex3d(doublex,doubley,doublez)
glVertex3dv(double[] )

glVertex3f(floatx,floaty,floatz)
glVertex3fv(float[]v)

glVertex3i(intx,inty,intz)
glVertex3iv(int[]v)

glVertex3s(shortx,shorty,shortz)
glVertex3sv(short[] v)

’glBegin’ fonksiyonun çağrılmasından sonra gelen ifadeler, ne tip geometrik şeklin çizileceğini belirler. Aşağıdaki tabloda ’glBegin’ fonksiyonunda kullanılan on adet veri tipi gösterilmiştir :

Veri Tipi
Anlamı
GL_POINTS Bağımsız noktalar
GL_LINESBağımsız çizgi parçaları
GL_POLYGONDışbükey poligon
GL_TRIANGLESÜçgen
GL_QUADSDört-yüzlü poligonlar
GL_LINE_STRIPÇizgi parçaları serisi
GL_LINE_LOOPİlk ve son köşeleri ile birbirine bağlı kapalı çizgi parçaları serisi
GL_TRIANGLE_STRIPÜçgen serisi
GL_TRIANGLE_FANÜçgen yelpazeleri
GL_QUAD_STRIPDörtgen serisi



Uygulama : OpenGL’de Basit Bir Ev Modeli

Şimdi uygulamaya geçelim. İlk olarak C#’ta oluşturulmuş bir Windows uygulamasının içinde bir form tanımlıyoruz. Görüntümüzü bu form üzerinde göstereceğiz.

OpenGL fonksiyonlarını kullanabilmek için OpenGL kütüphanesini referanslara eklememiz gerekmektedir. ’csgl.dll’ dosyasını referans olarak seçmek için önce Visual Studio .NET penceremizdeki proje penceresindeki referans ekle kısmından csgl.dll dosyasını bilgisayarımızdaki sabit diskte kayıtlı olduğu yerden ekliyoruz ve ’using CsGL.OpenGL’ ifadesini kaynak kod dosyamızın başıne ekleyerek bu kütüphaneyi kullanacağımızı önceden derleyiciye bildiriyoruz. Ayrıca ’csgl.native.dll’ dosyasını C:\WINDOWS\system32 dosyasına kopyalıyoruz. ’csgl.dll’ ve ’csgl.native.dll’ dosyalarını

Linkleri sadece kayıtlı üyeler görebilir. Linkleri görebilmek için Üye Girişi yapın veya ücretsiz olarak Kayıt Olun

sayfasından indirebilirsiniz.

Önce bir küp sınıfı tanımlıyoruz. Tüm OpenGL komutlarını, OpenGLControl sınıfından türettiğimiz Ourview isimli sınıfın içinde yapıyoruz ve her OpenGL uygulamamızda olması gereken InitGLContext() fonksiyonumuzu, bu türetilmiş sınıfta ezerek (override ederek) içindeki üye fonksiyonların parametrelerini değiştirerek istenen başlangıç koşullandırmalarını yerine getiriyoruz. Çizim işlemleri ise glDraw() fonksiyonu içerisinde tanımlanır. Burada yine glDraw() fonksiyonumuzu, türetilmiş Ourview isimli sınıfımızda ezerek fonksiyona yeni özellikler kazandırıyoruz. Çizime başlamadan önce ekran tamponunu temizliyoruz ve şeklimizi koordinat sisteminde, bize görünebilir olması için glTranslatef() fonksiyonumuz ile z ekseninde -8 birim derine öteliyoruz. Bu fonksiyonun özelliği, bir çizim başlangıç noktası oluşturmasıdır. glRotatef() ile de şeklimizi kendini sürekli yineleyen fonksiyonumuzda (ki biz bu yineleme rutinini form içindeki Main() in içinde belirteceğiz - buna daha sonra değineceğim - ) döndürerek şeklin her bir yinelemede farklı bir tarafını görme şansına sahip oluyoruz. Bu fonksiyonun tam olarak ne işe yaradığını öğrenmek için farklı parametre değerleri girerek deneyip görmek en güzel yöntemdir.

Bildiğimiz gibi, şeklimizi glBegin() ve glEnd() fonksiyonları arasında tanımlıyoruz. Eğer bir dörtgen dizisi belirleyecek isek, bunu bu fonksiyonlar arasında yapmamız gereklidir. Biz uygulamamızda parametre olarak GL_QUADS girerek dörtgen çizeceğimizi belirtiyoruz. Çizeceğimiz geometrik şeklin koordinatlarını belirtmeden önce hangi renkte olması gerektiğini bildirmemiz gereklidir. Renk belirtiminin nasıl olduğuna daha önce değinmiştik.

Modelimiz ev olduğu için, bir küp oluşturmalıyız. Evin çatısı için 4 farklı üçgen belirtmeliyiz. Her bir üçgenin sadece tek bir ortak Vertex’i vardır. Diğer köşe noktalarını evin duvarlarının üst köşelerine konumlandırıyoruz.

Öncelikle ’Küp’ isim uzayımızın kodlarını inceleyelim. Daha sonra form sınıfının kodlarına değineceğiz. Gerekli açıklamaları kodların arasında bulabilirsiniz. Daha detaylı bilgi için, OpenGL kırmızı ve mavi kitaba başvurmanızı öneririm.

using System;
using System.Drawing;
using CsGL.OpenGL;
using System.Windows.Forms;

namespace Küp
{
public class Ourview : OpenGLControl
{
public bool finished = false;

public Ourview() : base() //Kurucu fonksiyonumuz
{
this.KeyDown += new KeyEventHandler(Ourview_OnKeyDown);
}


protected void Ourview_OnKeyDown(object Sender, KeyEventArgs kea)
{
//eğer escape basılırsa uygulama sona erer
if(kea.KeyCode==Keys.Q&&kea.Modifiers == Keys.Shift)
{
Application.Exit();
}
} //Köşe noktalarını bir değişkenle ifade ettik çünkü buradan değişitrerek şeklin ne kadar büyük olacağını belirleyebiliriz.
private float fEksi = -1.0f;
private float fArti = +1.0f;
private float fDondur = 0.0f;

public override void glDraw()
{
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);//Ekranı ve derinlik tamponunu siler
GL.glLoadIdentity(); //O anki model matrisini sıfırlar

GL.glTranslatef( 0.0f,0.0f,-8.0f );// viewport = 0 0 0 ve böylece derinlik 8 dır.
GL.glRotatef( fDondur, 1.0f, 1.0f, 1.0f );//modelimizi fDondur açısıyla yerleştirdiğimiz koordinat etrafında döndürürür


GL.glBegin(GL.GL_QUADS); // Geometrik şeklimizin ne olacağı. Burada dörtgen belirttik.

//üst yüz
GL.glColor3f(1.0f,1.0f,0.0f);//sarı renk
GL.glVertex3f( fArti, fArti, fArti);
GL.glVertex3f( fArti, fArti, fEksi);
GL.glVertex3f( fEksi, fArti, fEksi);
GL.glVertex3f( fEksi, fArti, fArti);

//alt yüz
GL.glColor3f(0.0f,1.0f,1.0f);//cyan renk
GL.glVertex3f( fArti, fEksi, fArti);
GL.glVertex3f( fArti, fEksi, fEksi);
GL.glVertex3f( fEksi, fEksi, fEksi);
GL.glVertex3f( fEksi, fEksi, fArti);


//arka yüz
GL.glColor3f(1.0f,0.0f,0.0f);//kırmızı renk
GL.glVertex3f(fArti,fArti,fEksi);
GL.glVertex3f(fArti,fEksi,fEksi);
GL.glVertex3f(fEksi,fEksi,fEksi);
GL.glVertex3f(fEksi,fArti,fEksi);


//ön yüz
GL.glColor3f(0.0f,0.0f,1.0f);//mavi renk
GL.glVertex3f(fArti,fArti,fArti);
GL.glVertex3f(fArti,fEksi,fArti);
GL.glVertex3f(fEksi,fEksi,fArti);
GL.glVertex3f(fEksi,fArti,fArti);
//Sağ yüz
GL.glColor3f(0.0f,1.0f,0.0f);//yeşil renk
GL.glVertex3f(fArti,fArti,fArti);
GL.glVertex3f(fArti,fEksi,fArti);
GL.glVertex3f(fArti,fEksi,fEksi);
GL.glVertex3f(fArti,fArti,fEksi);


//sol yüz
GL.glColor3f(0.5f,1.0f,0.5f);
GL.glVertex3f(fEksi,fEksi,fEksi);
GL.glVertex3f(fEksi,fArti,fEksi);
GL.glVertex3f(fEksi,fArti,fArti);
GL.glVertex3f(fEksi,fEksi,fArti);


GL.glEnd();

GL.glBegin(GL.GL_TRIANGLES);
//ön yüz için
GL.glColor3f(1.0f,0.5f,0.2f);
GL.glVertex3f(fArti,fArti,fArti);
GL.glVertex3f(fEksi,fArti,fArti);
GL.glVertex3f(0.0f,2*fArti,0.0f);

//sol yüz için
GL.glColor3f(1.0f,0.2f,0.5f);
GL.glVertex3f(fEksi,fArti,fArti);
GL.glVertex3f(fEksi,fArti,fEksi);
GL.glVertex3f(0.0f,2*fArti,0.0f);

//sağ yüz için üçgen
GL.glColor3f(1.0f,0.25f,0.75f);
GL.glVertex3f(fArti,fArti,fEksi);
GL.glVertex3f(fArti,fArti,fArti);
GL.glVertex3f(0.0f,2*fArti,0.0f);

//arka yüz için üçgen
GL.glColor3f(1.0f,0.75f,0.75f);
GL.glVertex3f(fEksi,fArti,fEksi);
GL.glVertex3f(fArti,fArti,fEksi);
GL.glVertex3f(0.0f,2*fArti,0.0f);

GL.glEnd();


fDondur += 1.25f; // Döndürme açımız
}


protected override void InitGLContext()
{
GL.glShadeModel(GL.GL_SMOOTH); // Yumuşak bir gölgelendirme sağlar
GL.glClearColor(1.0f, 1.0f, 1.0f, 0.5f); // arka plan rengi
GL.glClearDepth(1.0f); // Derinlik Tamponu kurmak için
GL.glEnable(GL.GL_DEPTH_TEST); // Derinlik testini etkin kılar
GL.glDepthFunc(GL.GL_LEQUAL); // Yapılcak derinlik testinin tipi
GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST); // Çok iyi perspektif Hesaplamaları için
}
//Form boyutu değiştiğinde neler yapmamız gerektiği burada verilmiştir.
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
Size s = Size;

GL.glMatrixMode(GL.GL_PROJECTION);//izdüşüm matrisini seçer
GL.glLoadIdentity();//model matrisini sıfırlar
GL.gluPerspective(45.0f, (double)s.Width /(double) s.Height, 0.1f, 100.0f);//Çerçevenin en boy oranı hesaplanarak
GL.glMatrixMode(GL.GL_MODELVIEW);//model matrisini seçer
GL.glLoadIdentity();//ve daha sonra model matrisi tekrar sıfırlanır
}
}
}


Windows uygulaması oluşturduğumuz için, çizimimizi ana formumuz içerisinde göstermemiz gerekmektedir. O halde form için bazı koşullamaları gerçeklememiz gerekmektedir. Oluşturduğumuz ’küp’ isim uzayının ’Ourview’ sınıfını form sınıfımızın private değişkeni olarak tanımlamalıyız. Formumuzun kurucu fonksiyonunda da bazı belirtimler yapmalıyız. Örneğin formun tamamında çizimimizi görmek için. Main fonksiyonununda ise yeni bir referans form tanımlıyoruz ve bu formun finished ve IsDisposed değişkenleri ’false’ oldukça devam etmesini sağlıyoruz. Asıl çizim olayını glDraw() fonksiyonunu çağırarak gerçekleştiriyoruz. Ve formun kendisini sürekli tazelemesini istiyoruz. Böylece süreç içinde değişen olayları her yeni tazelemede görebilmekteyiz.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;


/*Bu çalışma Kocaeli Üniversitesi Elektronik ve Haberleşme Mühendisliğinde İşaret ve Görüntü İşleme Laboratuvarında (KULİS)
*OpenGL’de 3-B nesne tanımlama projesi kapsamında Yılmaz Ürgün tarafından yapılmıştır. */


namespace Küp
{
public class Form1 : System.Windows.Forms.Form
{
private Küp.Ourview view;
private System.ComponentModel.Container components = null;

public Form1()
{
InitializeComponent();

this.view = new Küp.Ourview(); // view sınıfı
this.view.Parent = this;
this.view.Dock = DockStyle.Fill; // Tüm formu doldurmasını sağlar
this.Show();
}


protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code

private void InitializeComponent()
{

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(552, 454);
this.Name = "Form1";
this.Text = "OpenGL - KOÜ KULİS 2006";

}
#endregion


[STAThread]
static void Main()
{
Form1 form = new Form1();// yeni bir form oluşturuyoruz.

while((!form.view.finished) && (!form.IsDisposed)) // sonlandırma false ve Dispose false ise devam et.
{
form.view.glDraw();//Çizimi yapan fonksiyon


form.Refresh();//Formu tazele
Application.DoEvents();
}
form.Dispose();

}
}
}

Projemizi çalıştırdıktan sonra aşağıdaki ekran çıktısını elde ettik.



Kaynaklar

1) OpenGL kırmızı ve mavi kitapları.
2)

Linkleri sadece kayıtlı üyeler görebilir. Linkleri görebilmek için Üye Girişi yapın veya ücretsiz olarak Kayıt Olun

.
3)

Linkleri sadece kayıtlı üyeler görebilir. Linkleri görebilmek için Üye Girişi yapın veya ücretsiz olarak Kayıt Olun


4) Hatice Günaçtı - 3 Boyutlu Model Tanımlama - KOÜ 2005, Bitirme Tezi
 

Users Who Are Viewing This Konu (Users: 0, Guests: 1)

Üst