C# OpenGL rozhraní
pro Windows operační systém
Colin Fahey

CSGL12Control na Form zobrazující "fraktálových" pixel shader program a GDI+ kresba zkopírovány do textury

Dva CSGL12Control případech na Form, zobrazeno pixel shader programy a textur

A 3D avatar, že roams ploše a mohou být přesunuty s kurzorem
1. Software
CSGL12_20090725.zip
CSGL12: C# OpenGL rozhraní pro Windows, verze 12
4170499 bytes
MD5: 30781a6570441785ea636f2ae1cd16ef
2. Vše o C# počítačového kódu v C# OpenGL rozhraní (CSGL12) je ve "veřejné doméně"
Napsal jsem všechny z C# počítačového kódu v C# OpenGL interface (CSGL12).
Prohlašuji, že všechny C# počítačového kódu v C# OpenGL interface (CSGL12), které mají být ve "veřejné doméně."
Proto se počítačového kódu je možné použít pro jakýkoliv účel (komerční nebo soukromé), a to bez placení, bez omezení, bez závazků a bez uznávajících původní autor.
Kód může být změněn, nebo jejich části znovu použity, a to bez omezení a bez povinností a bez uznávajících původního autora.
Příklad programy obsahují malé množství počítačového kódu (konkrétně "shader počítačový kód) písemné jinými lidmi." Takové číslo není v samotné rozhraní a lze triviálně odstraněny. Takové číslo je pouze demonstrovat jednoduchost použití rozhraní pro vytváření a používání "shader" programů.
3. Úvod
"CSGL12" je kolekce C# počítačového kódu souborů, které se provádí na rozhraní OpenGL grafické knihovny (včetně všech rozšíření OpenGL až do roku 2007) pro Windows operačního systému.
V C# počítačového kódu souborů v "CSGL12" kolekci snadno přidat OpenGL kreslení na jakýkoli software C# / .NET s "Form" (instancí "System.Windows.Forms.Form").
V "CSGL12" kolekce počítačového kódu souborů obsahuje soubor "CSGL12Control.cs", který definuje třídy pojmenované "CSGL12Control", odvozený od "System.Windows.Forms.Control". Každá instance "CSGL12Control" představuje nezávislý OpenGL kreslení oblasti. Je velmi snadné přidat více instancí CSGL12Control na Form (instancí System.Windows.Forms.Form).
4. Vlastnosti a požadavky "CSGL12"
Tento kód je pouze Windows pro operační systémy, které podporují .NET 2.0 Framework (Windows 2000, Windows XP, Windows Vista, Windows 7)
Tento kód je možné sestavit pomocí "Microsoft Visual C# 2008 Express Edition" (bezplatná kompilátor), nebo podobných C# překladače.
Kód vyžaduje staví se "[X] Allow unsafe code" postavit opce vybrány tak, aby optimalizovány obrazových dat kopírování funkce mohou být použity. Pokud jste znalec C# programátor budete moci snadno identifikovat částí C# kódu, které vyžadují "unsafe" a možnost zakázat jim v případě potřeby, nebo požaduje. Obrazových dat kopírování je 10 krát rychlejší než pomocí "unsafe" kód alternativní, a to je důvod, proč takový kód je použit. Pokud si vybudovat DLL, že obsahuje všechny ze "unsafe" kód, pak projekt, který využívá, že DLL nevyľaduje staví se "unsafe" volby, a tak lze usuzovat, že pokud by nedošlo ke "unsafe" možnost v rámci projektu však neznamená žádnou extra bezpečnost (kvůli četným DLL soubory, které se používají implicitně či explicitně, které program obsahuje "nebezpečné" kód).
Tento kód je možné sestavit a používají některý z následujících:
Microsoft Visual C# 2008 Express Edition
Microsoft Visual Studio 2008
Microsoft .NET 3.5 SDK
SharpDevelop
Mono Project
Kód nabízí většina OpenGL rozšíření (až do roku 2007), včetně "vertex shaders" a "pixel shaders".
Kód 1570 poskytuje funkce související s OpenGL:
336 GL functions
51 GLU functions
19 WGL functions
1164 extensions
Kód nabízí několik alternativních variant se 1570 funkcí s různými typy parametrů, pro pohodlí.
Kód definuje více než 3244 konstanty pro OpenGL.
Tento kód je možné mít více OpenGL čerpání kontextech, všechna oživení nezávisle na jakýchkoli "Form".
Kliknutím na "CSGL12Control" jí "vstupní zaměření," což umožňuje následné klávesnice a myš kola vstupu. Cursor kliknutí a pohybů jsou přijaté, pokud je kurzor v obdélníkové oblasti instancí "CSGL12Control".
Tento kód obsahuje funkce, které ukazují, jak udělat některé společné OpenGL úkoly C# a .NET.
Kód seznam všech OpenGL konstanty a funkce v abecedním pořadí v "class GL" v "GL.cs", takže je snadné zjistit, existuje-li konstantní nebo funkce chybí (což je nepravděpodobné, kromě rozšíření přijatých po roce 2007).
Příklad programy ukazují, jak udělat GDI+ kreslení na Bitmap, a pak jak kopírovat že Bitmap na OpenGL texturu.
To umožňuje textu a dalších GDI+ čerpání schopnosti přispívat k OpenGL scéně.
Na GDI+ Bitmap mohou být aktualizovány a nahráli na OpenGL textury tak často, jako kdysi za OpenGL rámu.
Příklad programy ukazují, jak si vybrat z několika různých "pixel shader programs", zatímco je program spuštěn.
Příklad programy ukazují jak napsat OpenGL buffery pro obrazové soubory (JPG, BMP, GIF, PNG).
Tisk Shift + 0 (posunu-nulové) psát OpenGL pufru do obrazu.
Tento příklad ukazuje, jak kód "GL.cs" v kompilaci do DLL souboru, a pak dodává, že DLL souboru na jiném projektu, můžete zabránit Microsoft kód editory (např. Microsoft Visual C# 2008 Express Edition, atd.) s "IntelliSense" (kontext-citlivé kód dokončení) z stává často a vytrvale nevstřícný (opakovaně pauzy pro mnoho sekund, což je zcela nepoužitelný textový editor). S soubor "GL.cs" přímo obsaženy v každém projektu editujeme pomocí Microsoft kód editor není praktické, pokud osoba, která je ochotna vydržet pomalost v editoru. Tento problém je ovlivněna Microsoft Visual Studio 2003, 2005, 2008 a pravděpodobně budou mít vliv na 2010 verze taky.
Příklad kódu demonstruje použití více instancí "CSGL12Control" na "Form".
Příklad číslo obsahuje kód, aby 3D "avatar," že roams plochu Windows.
5. Příklad programy součástí "CSGL12"
5.1 "CSGL12DLL"
Projekt s názvem "CSGL12DLL" dává DLL soubor "CSGL12DLL.dll" který obsahuje "class GL" (definované v C# soubor "GL.cs").
Uvádění "class GL" ke DLL souboru, a pak pomocí DLL, že v dalších projektech, které používají "class GL", pomáhá vyhnout extrémní problém s Microsoft kód editory s IntelliSense funkce. Pomocí C# soubor GL.cs přímo v projektu by způsobovat žádné Microsoft kód editor s IntelliSense funkce, aby se stala zcela nepoužitelnou téměř nereagují a průběžně vzhledem k neefektivnosti v IntelliSense funkci (a skutečnost, že IntelliSense zřejmě blokuje hlavní program vlákno v editoru ).
Pokud používáte editor C# kód, který není vyráběný Microsoft (např. "SharpDevelop", "MonoDevelop", atd.), pak můžete jednoduše zahrnout soubor "GL.cs" přímo ve vašich projektů, a ty by pravděpodobně získat nějaké výhody z použití "CSGL12DLL.dll".
5.2 "CSGL12Control"
Projekt s názvem "CSGL12Control" dává DLL soubor "CSGL12Control.dll" který obsahuje "class CSGL12Control" (definované v C# soubor "CSGL12Control.cs").
Uvádění "class CSGL12Control" ke DLL soubor, který umožňuje "Control" (tj. třídy odvozené od "System.Windows.Forms.Control"), které mají být přidány do "Toolbox" z Microsoft Visual C# 2008 Express Edition (a podobné C# editory). S "CSGL12Control" v "Toolbox" je snadné pro osobu přidat instancí "CSGL12Control" na "Form" v "Designer" (např. osoby, můžete jednoduše použít kurzorem vybrat a přetáhnout instancí "CSGL12Control" z "Toolbox" na "Form").
V "CSGL12Control" objekt spravuje OpenGL kreslení kontextu. Více instancí "CSGL12Control" mohou koexistovat na "Form".
5.3 "CSGL12Example1"
Projekt s názvem "CSGL12Example1" vytváří spustitelný soubor programu (EXE) s názvem "CSGL12Example1.exe". Program využívá "CSGL12DLL.dll" a "CSGL12Control.dll" zobrazuje případ CSGL12Control a nakreslit krychli pomocí OpenGL.
Program demonstruje použití čtyř různých "pixel shaders" "(fraktál, cihel, dřeva" a "karikatura)."
Program také demonstruje použití "GDI+", a .NET kreslení knihovnu, k tomu textu a dalších tvarů k "Bitmap" objekt (a "GDI+" object) a pak zkopírovat data z tohoto "Bitmap" na "texture" v OpenGL, což umožňuje vyvodit obrázek "GDI+" by se objevit v OpenGL výkresu. Tato schopnost je velmi užitečná, protože OpenGL postrádá mnoho z 2D kreslení funkce najít v "GDI+" a podobné 2D kreslení libaries.
5.4 "CSGL12Example2"
Projekt s názvem "CSGL12Example2" vytváří spustitelný soubor programu (EXE) s názvem "CSGL12Example2.exe". Program využívá "CSGL12DLL.dll" a "CSGL12Control.dll" se zobrazí dvě instance CSGL12Control, z nichž každá čerpá kostka pomocí OpenGL.
Program má "SplitContainer" "Control" na "Form". Každá z těchto dvou oblastí na "SplitContainer" obsahuje instance CSGL12Control. Což znamená, že osoba může upravit polohu rozdělení na dva případy CSGL12Control. To ukazuje na flexibilitu CSGL12Control.
Jedním z příkladů CSGL12Control vysílá událostí na řadu v případě, manipulují instancí "CSGL12Example2Handler1.cs", která používá stejný kód jako "CSGL12Example1Handler.cs" v "CSGL12Example1" příklad projektu. Proto jedním z případů CSGL12Control čerpá kostka s jedním z vybraných "pixel shader" mezi čtyři dostupné "pixel shaders".
Druhé instanci CSGL12Control posílá události na řadu v případě, manipulují instancí "CSGL12Example2Handler2.cs", která čerpá kostka pomocí textury obrazu (nebo "šachovnicovým" vzorem, jestliže obraz "image.jpg" soubor není nalezen).
5.5 "CSGL12Avatar"
Projekt s názvem "CSGL12Avatar" vytváří spustitelný soubor programu (EXE) s názvem "CSGL12Avatar.exe". Program využívá "CSGL12DLL.dll" a "CSGL12Control.dll" čerpat kostka pomocí OpenGL na "Form" bez hranic, s barevnými založena transparentnosti povolena, k tažení 3D "avatar," že roams se Windows desktopové oblasti.
Pohybující se avatar lze kliknul a přetáhnout do nového umístění pomocí kurzoru. Double-kliknutím na avatar jej zmizet. Přestože kód pouze čerpá kostka, OpenGL lze čerpat dalších věcí.
Více instancí v "avatar" program lze spustit. Proto mnoho nezávislých "avatar" případech může současně toulat se Windows desktop. To je legrační. Expert C# programátor mohli těšit najít způsoby, jak koordinovat činnost mnoha takových případech "avatar."
Bohužel, sazba, za kterou se Window objektu s transparentnosti je aktualizován na obrazovce, je mnohem pomalejší, než rychlost, kterou může čerpat OpenGL. V "avatar" pouze aktualizace 10 krát za sekundu. Nevím, jestli to může být lepší.
5.6 "CSGL12BuiltExecutableExamplesForReference"
Adresář pojmenovaný "CSGL12BuiltExecutableExamplesForReference" obsahuje DLL soubory a soubory EXE vyrobené všem příkladem projektů. Tyto soubory jsou poskytovány jako odkaz, takže soubory mohou být testovány okamžitě, a to iv případě, že osoba nemá schopnost sestavit různé projekty z předpokladu C# kód.
5.7 "CSGL12UsefulCode"
Adresář pojmenovaný "CSGL12UsefulCode" obsahuje C# souborů, které by mohly být užitečné pro lidi, kteří chtějí dělat běžné operace s čerpáním OpenGL. Adresář obsahuje také DLL soubory "CSGL12DLL.dll" a "CSGL12Control.dll" pro pohodlí.
Kód do adresáře, který je určen class různých typů, jako jsou Color4f, Vector3f, Matrix4x4f, Triangle, Mesh, ImageData, Texture, ShaderProgram, atd. Kód je dostatečně efektivní, ale kód je určena pouze k inspirovat lidi k rozvoji jejich vlastní realizací.
6. CSGL12 soubory
V "CSGL12" kolekce C# počítačového kódu souborů obsahuje soubory, uvedené v následujícím schématu:

V "CSGL12" kolekce C# počítačového kódu souborů obsahuje soubory, uvedené v tomto diagramu.
V "CSGL12" software zahrnuje rovněž projekty zaměřené na vytvoření dvou DLL soubory ("CSGL12DLL.dll" a "CSGL12Control.dll") je znázorněno na obrázku. Tyto dvě DLL souborů mohou být vytvořeny, aby bylo výhodnější vytvářet programy, které používají OpenGL, ale je také možné vytvářet programy využívající pouze C# soubory přímo.
7. "namespace CSGL12" a "class" typy
V "CSGL12" kolekce C# počítačového kódu souborů definuje "namespace CSGL12" a "class" druhů je uvedeno v následujícím schématu:

V "CSGL12" kolekce C# počítačového kódu souborů definuje "namespace CSGL12" a "class" druhy uvedené v tomto diagramu.
Program, který se OpenGL výkresu lze vytvořit pouze pomocí "class GL" (pomocí C# soubor GL.cs přímo, nebo pomocí DLL soubor CSGL12DLL.dll, která obsahuje také "class GL"). Nicméně pomocí "class CSGL12Control" (pomocí C# soubor CSGL12Control.cs přímo, nebo pomocí DLL soubor CSGL12Control.dll, který také obsahuje "class CSGL12Control") umožňuje přidání OpenGL kreslení na Form (System.Windows.Forms.Form) snadné a pohodlné.
V C# tříd Color4f, CSGL12Support, ImageData, ..., v dolní části obrázku jsou nabízeny pouze pro pohodlí. Těchto tříd je usnadnit vytvoření programů, které používáte OpenGL čerpat. Pravděpodobně byste se však již tříd, které vykonávají činnosti v těchto třídách, nebo můžete vytvořit podobné třídy, které provádějí operace odlišně nebo efektivněji. Tyto kurzy jsou nabízeny jako příklad určitého kódu design a provedení.
8. Pomocí jediného "CSGL12Control" na System.Windows.Forms.Form
8.1 Program struktura
Následující graf ukazuje, jak program s System.Windows.Forms.Form mohou používat jediný "CSGL12Control" udělat výkres s OpenGL. Diagram ukazuje různé CSGL12 soubory použita na výstavbu programu.

Program, pomocí jediného "CSGL12Control" na System.Windows.Forms.Form
8.2 Použití Microsoft Visual C# vytvořit program
(1) Start Microsoft Visual C#.
(2) V menu vyberte "File" -> "New Project...".
(3) V "New Project" dialogovém okně, které se objeví, zvolte "Windows Forms Application", a vybrat si název programu a stiskněte "OK".
(4) Ihned uložte "Solution" výběrem "File" -> "Save All". Zobrazí se dialogové okno s názvem "Save Project" objeví, vám umožní nastavit název projektu, adresář umístění a název pro "řešení" projektu. Pamatujte na umístění adresáře, takže jste připraveni na další instrukce. Stiskněte tlačítko pro uložení "Save" projektu.
(5) Zkopírujte všechny soubory z adresáře "CSGL12UsefulCode" v "CSGL12" software do adresáře obsahujícího zdrojový kód soubory nového projektu (tj. adresáře, které obsahují soubory "Form1.cs", "Form1.Designer.cs", "Program.cs", atd.) tak, že soubory "CSGL12DLL.dll", "CSGL12Control.dll", "Color4f.cs" , "CSGL12Support.cs" atd., jsou spolu s novým projektem "Form1.cs" soubory, atd.
(6) V Microsoft Visual C#, přidejte "CSGL12" C# souborů do projektu. V menu vyberte "Project" -> "Add Existing Item..." av "Add Existing Item" dialogové okno, vyberte je C# soubory z CSGL12 software ("Color4f.cs", "CSGL12Support.cs", "ImageData.cs", ...).
(7) V Microsoft Visual C#, přidávat "odkazy" na DLL soubory "CSGL12DLL.dll" a "CSGL12Control.dll". V menu vyberte "Project" -> "Add Reference..." a "Add Reference" v dialogovém okně vyberte záložku "Browse" a vyberte soubory "CSGL12DLL.dll" a "CSGL12Control.dll" z projektu zdrojového souboru, adresáře a stiskněte "OK".
(8) V Microsoft Visual C#, přidejte "CSGL12Control" na "Toolbox". V menu vyberte "Tools" -> "Choose Toolbox Items...". V "Choose Toolbox Items" zobrazeném dialogovém okně stiskněte tlačítko "Browse...", a jít do projektu adresáře se zdrojovými soubory kód a zvolte "CSGL12Control.dll". Stiskněte tlačítko "OK".
(9) V Microsoft Visual C#, zobrazit "Toolbox". V menu vyberte "View" -> "Toolbox". V "Toolbox", přejděte do sekce s názvem "General" a najděte položku s názvem "CSGL12Control". Pomocí kurzoru klepněte na položku s názvem "CSGL12Control" a přetáhněte jej do "Form" v "Design" názor.
(10) V Microsoft Visual C# v "Form" "Design" zobrazení, přesuňte "CSGL12Control" například na "Form" a upravit její šířku a výšku. V "Properties" panel, nastavení "Anchor" hodnoty patří "Top, Bottom, Left, Right" chcete-li změnit velikost kontrole v souladu se změnami v programu, velikost okna.
(11) V Microsoft Visual C#, změna projektu nemovitostí tak, aby bylo možné použít "unsafe" kód. V menu vyberte "Project" -> "[project] Properties...". Vyberte dialogové okno, které se zobrazí, vyberte záložku s názvem "Build" a zkontrolovat políčko s názvem "[X] Allow unsafe code". Zavřít projektu vlastnosti okna.
(12) V Microsoft Visual C#, přidat nový C# souboru do projektu. V menu vyberte "Project" -> "Add New Item...". V dialogovém okně s názvem "Add New Item", vybrat šablonu s názvem "Class" a zvolit název nové třídy typu, jako je "CSGL12MyHandler.cs" a stiskněte tlačítko "Add". Podívejte se na příklad projektu s názvem "CSGL12Example1", na soubor s názvem "CSGL12Example1Handler.cs", jako příklad, jak se kód "CSGL12MyHandler.cs" by měl být v písemné formě.
(13) V Microsoft Visual C# v "Solution Explorer", klikněte na "Form1". V menu vyberte "View" -> "Code" (nebo stiskněte F7 nebo právo-klikněte na "Form1" a vybrat "View Code". Kódu v souboru "Form1.cs" bude zobrazen v editoru. Upravte kód v souboru "Form1.cs" to být podobné jako v kódu v souboru "CSGL12Example1Form.cs" v rámci projektu "CSGL12Example1" zahrnuty v "CSGL12" software. Zejména vytvoření proměnné pro instancí svého zpracování události třídy (např. "CSGL12MyHandler"), a potom přidejte metod této třídy jako je např. případ handlery pro různé události z instance "CSGL12Control" na "Form".
(14) V Microsoft Visual C#, zkompilovat a spustit program. Pokud budete chtít podělit se o program, musíte se o dvě DLL soubory ("CSGL12DLL.dll" i "CSGL12Control.dll") s spustitelný soubor (*.exe).
Pokud jste znalec C# programátor, poté se můžete vyhnout, že je třeba šířit DLL soubory ("CSGL12DLL.dll" a "CSGL12Control.dll") se svým executable (*.exe).
Kopírovat soubory "GL.cs", "CSGL12Control.cs" a "PrecisionTime.cs" z projektu s názvem "CSGL12DLL" a "CSGL12Control" v "CSGL12" software ke zdrojovému adresáři aktuálního projektu. Přidat soubory "GL.cs", "CSGL12Control.cs" a "PrecisionTime.cs" na svůj projekt tak, aby byly sestavovány přímo do programu. Nemáte odkazy na "CSGL12DLL.dll" a "CSGL12Control.dll" v projektu.
Podívejte se na "CSGL12Example1" projektu v "CSGL12" software, a podívejte se na kód do souborů s názvem "CSGL12Example1Form.cs" a "CSGL12Example1Form.Designer.cs" vidět kód, co je zapotřebí k vytvoření a inicializaci instance "CSGL12Control" na "Form". Přidejte podobného kódu na "Form1.cs" a "Form1.Designer.cs" ručně vytvořit a inicializovat instancí "CSGL12Control" na vašem "Form".
Tento postup je velmi nevhodné, a vyžaduje odborné znalosti a pečlivou pozornost, ale výsledný spustitelný (*.exe) nebude vyžadovat "CSGL12DLL.dll" nebo "CSGL12Control.dll". Je velmi příjemné mít možnost sdílet své softwaru ve formě jediného spustitelného souboru (*.exe), aniž by vyžadoval další soubory.
8.3 Přidání "odkazů" na CSGL12DLL.dll a CSGL12Control.dll
Tato sekce obsahuje obrázky pomocí Microsoft Visual C# 2008 Express Edition přidat "odkazy" na DLL soubory CSGL12DLL.dll a CSGL12Control.dll do projektu.
V menu vyberte "Project" -> "Add Reference...". Nebo právo-klikněte na položku "References" v "Solution Explorer" panel a zvolte "Add Reference...", jak ukazuje následující obrázek.

Kontextové menu pro "References" položku v "Solution Explorer", zobrazující "Add Reference..." volby
Po výběru volby "Add Reference...", dialogové okno s názvem "Add Reference" se objeví. V tomto dialogovém okně zvolte kartu "Browse" a vyberte DLL soubory "CSGL12DLL.dll" a "CSGL12Control.dll", jak ukazuje následující obrázek, a stiskněte tlačítko "OK".

V "Browse" kartu z "Add Reference" dialogové okno s DLL souborů "CSGL12DLL.dll" a "CSGL12Control.dll" obou vybraných
Po stisknutí tlačítka označená "OK", v dialogovém okně "Add Reference" bude zmizelo, a DLL soubory "CSGL12DLL.dll" a "CSGL12Control.dll" se objeví v "References" pobočku v "Solution Explorer", jak je znázorněno v následujícím grafu.

V DLL soubory "CSGL12DLL.dll" a "CSGL12Control.dll" v "References" pobočku v "Solution Explorer"
8.4 Přidání CSGL12Control na Toolbox v Microsoft Visual C# 2008 Express Edition
Tato sekce obsahuje obrázky pomocí Microsoft Visual C# 2008 Express Edition přidat CSGL12Control na "Toolbox" tak, že osoba může snadno přidat instance CSGL12Control na "Form" v "Designer" (Shift+F7 ve výchozím nastavení).
V menu vyberte "View" -> "Toolbox". V "Toolbox", přejděte do sekce s názvem "General", jak ukazuje následující obrázek.

V "General" část "Toolbox"
Právo-klikněte kamkoliv do "Toolbox". Vyberte volbu "Choose Items..." v kontextovém menu, které se objeví, jak ukazuje následující obrázek.

Možnost "Choose Items..." v kontextovém menu pro "Toolbox"
Případně, v menu zvolte zvolte "Tools" -> "Choose Toolbox Items...".
V "Choose Toolbox Items" dialogovém okně by se měl objevit, jak ukazuje následující obrázek.

V dialogovém okně "Choose Toolbox Items"
V "Choose Toolbox Items" dialogovém okně stiskněte tlačítko "Browse". V "Open" dialogové okno, které se objeví, vyberte DLL soubor "CSGL12Control.dll", jak ukazuje následující obrázek, a stiskněte tlačítko "OK".

"Open" se dialogové okno s DLL soubor "CSGL12Control.dll" vybraných
V "CSGL12Control" položky by se nyní měla objevit v "Choose Toolbox Items" okna, jak ukazuje následující obrázek. Stiskněte tlačítko "OK".

V "CSGL12Control" položek se nyní zobrazí v dialogovém okně "Choose Toolbox Items"
V "CSGL12Control" položky by se nyní měla objevit v "Toolbox", jak ukazuje následující obrázek.

V "CSGL12Control" položky se nyní objeví v "Toolbox"
8.5 Přidání CSGL12Control na "Form" pomocí "Toolbox"
Tato sekce obsahuje obrázky pomocí Microsoft Visual C# 2008 Express Edition přidat instancí CSGL12Control na "Form" pomocí "Toolbox".
V menu vyberte "View" -> "Designer" (Shift+F7 ve výchozím nastavení). A double-click "Form*.cs" jeden soubor v "Solution Explorer". Nebo právo-klikněte na obrázek "Form*.cs" v "Solution Explorer" a zvolte "View Designer". Použití jedné z těchto tří metod je "Designer" okno pro "Form" by se měl objevit.
V menu vyberte "View" -> "Toolbox". V "Toolbox", přejděte do sekce s názvem "General". Položku s názvem "CSGL12Control" by se tam, jak ukazuje následující obrázek.

V "CSGL12Control" by již měla být v "Toolbox"
Pomocí kurzoru klepněte na položku s názvem "CSGL12Control" a přetáhněte jej do "Form" v "Designer". Instancí "CSGL12Control" by se měla objevit na "Form", jak ukazuje následující obrázek.

Instancí "CSGL12Control" na "Form" v "Designer"
V "Form" "Designer" zobrazení přesunout instanci "CSGL12Control" na "Form" a upravit její šířku a výšku.
Klikněte na instanci "CSGL12Control" na "Form" jej vyberte. Tehdy, v "Properties" panel, nastavení "Anchor" hodnoty patří "Top, Bottom, Left, Right" tak, že na velikosti dané "CSGL12Control" se bude měnit v reakci na změny v programu, velikost okna. Můžete také chtít změnit název proměnné (tj. hodnota "(Name)") pro instanci "CSGL12Control" z automatických výchozí (např. "csgL12Control"), aby něco pro svůj kód (např. "mCSGL12Control" nebo "mCSGL12Control1" atd.).
Následující obrázek ukazuje "Form" "Designer" názor a "Properties" panel.

Instancí CSGL12Control na Form v Designer a "Properties panel
9. Pomocí dvou instancí "CSGL12Control" na System.Windows.Forms.Form
Následující graf ukazuje příklad toho, jak dvě instance "CSGL12Control" může být přidána do System.Windows.Forms.Form udělat výkres s OpenGL v programu.

A program pomocí dvou instancí "CSGL12Control" na System.Windows.Forms.Form
Postupujte podle pokynů v předchozí části přidat jedinou instanci "CSGL12Control" na "Form". Pak jednoduše přetáhněte druhá instance "CSGL12Control" z "Toolbox" na "Form" přidat druhý "CSGL12Control".
Každá instance "CSGL12Control" bude mít svůj vlastní název proměnné. Každá instance "CSGL12Control" můžete mít svůj vlastní handler události spojené třídy, nebo ji můžete použít odlišné případy jediný ovladač třídy typu.
Studium je například projekt "CSGL12Example2" naučit "CSGL12Control" dvou případech může mít jejich akcí poslal na dva odlišné případy vlastní handler případě tříd s odlišným OpenGL výkresu funkcí.
Příklad programu "CSGL12Example2" má každý případ "CSGL12Control" v "SplitContainer" "Control", jednoduše prokázat jednu cestu, ve které instance "CSGL12Control" lze použít. Nicméně případy "CSGL12Control" může být umístěna přímo na "Form".
10. Příklad C# kód k "Form" s instancí CSGL12Control
Následuje kompletní C# kód obsažený v souboru "CSGL12Example1Form.cs", která je součástí je například program "CSGL12Example1".
Tento kód je zde prezentovány jako jednoduchý příklad, jak instancí CSGL12Control lze vytvořit a používat i "Form".
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CSGL12;
namespace CSGL12Example1
{
public partial class CSGL12Example1Form : Form
{
public CSGL12Example1Handler mCSGL12Example1Handler;
private System.Windows.Forms.Timer mTimer;
public CSGL12Example1Form()
{
InitializeComponent();
mCSGL12Example1Handler = new CSGL12Example1Handler();
mCSGL12Control1.OpenGLStarted += new CSGL12Control.DelegateOpenGLStarted( mCSGL12Example1Handler.OpenGLStarted );
mCSGL12Control1.KeyDown += new KeyEventHandler(mCSGL12Example1Handler.KeyDown);
mCSGL12Control1.KeyUp += new KeyEventHandler(mCSGL12Example1Handler.KeyUp);
mCSGL12Control1.MouseDown += new MouseEventHandler(mCSGL12Example1Handler.MouseDown);
mCSGL12Control1.MouseUp += new MouseEventHandler(mCSGL12Example1Handler.MouseUp);
mCSGL12Control1.MouseMove += new MouseEventHandler(mCSGL12Example1Handler.MouseMove);
mCSGL12Control1.MouseWheel += new MouseEventHandler(mCSGL12Example1Handler.MouseWheel);
mCSGL12Control1.Paint += new PaintEventHandler(mCSGL12Example1Handler.Paint);
// Use a timer to trigger drawing at the desired frame rate.
//
// Windows timers are not very precise. Also, if we call wglSwapIntervalEXT(1)
// and we specify in the global OpenGL control panel that OpenGL drawing
// should wait for vertical sync (vsync) of the display, then the frame
// rate would be limited to 60 frames/second or 75 frames/second, for example,
// and our program would have to draw each frame in less than 1/60 seconds
// (16.6 milliseconds) or less than 1/75 seconds (13.3 milliseconds),
// otherwise the drawn frame would be forced to wait one or more full
// frame durations before appearing on the screen. Therefore, it would
// be best to have the timer interval somewhat shorter than a full frame
// interval, to ensure that even if there is a slight delay in responding
// to the timer event we will have at least one timer event per display
// frame interval.
//
// Theoretically, a timer interval of 16 milliseconds would be short enough
// to sustain a frame rate of 62.5 frames/second, and would seemingly have
// a corresponding rate sufficient to sustain 60 frames/second in the case
// of a vertical-sync limited drawing rate for OpenGL. However, in simple
// experiments on a system with a 2.5 GHz Core 2 Duo CPU with an nVidia
// GeForce 8600M GS with 512 MB, I found that a 16-millisecond Windows
// timer interval results in a 33 frames/second OpenGL frame rate (where
// vertical-sync locking is enabled, and the display refresh rate is
// 60 frames/second). So, despite theoretically being slightly more rapid
// than necessary to maintain a 60 frames/second drawing rate, a Windows
// timer with an interval of 16-milliseconds isn't quite rapid enough to
// ensure drawing soon enough to be ready for each display refresh; hence
// the rather significantly lower than desired frame rate of 33 frames/second.
//
// Here are the OpenGL drawing frame rates (limited to 60 Hz vertical sync)
// I observed on a particular computer for particular Windows timer intervals:
//
// 18-millisecond timer interval --> 31 frames/second OpenGL drawing
// 17-millisecond timer interval --> 31 frames/second OpenGL drawing
// 16-millisecond timer interval --> 33 frames/second OpenGL drawing
// 15-millisecond timer interval --> 60 frames/second OpenGL drawing
// 14-millisecond timer interval --> 60 frames/second OpenGL drawing
//
// So, it seems like choosing a Windows timer interval only a couple of
// milliseconds shorter than the theoretical 16.6 millisecond interval
// corresponding to a 60 frames/second rate is enough for this program to
// submit each new frame in time for the next display refresh.
//
// However, computers with slower CPUs or slower GPUs might benefit from
// an even shorter Windows timer interval, to ensure that drawing will
// happen soon enough for the next display refresh.
//
// Some displays are set to refresh at 75 frames/second, which corresponds
// to a frame duration of 13.3 milliseconds. We will aim for this drawing
// rate, and we will subtract a few milliseconds from the Windows timer
// interval to ensure that we receive and process the timer event soon
// enough to submit the frame in time for the next display refresh.
// Meanwhile, we will choose the Windows timer interval such that it isn't
// absurdly short, lest future faster computers actually manage to draw
// at that wasteful rate.
//
// Choosing a Windows timer interval of 10 milliseconds seems like it will
// reliably be able to trigger OpenGL frame drawing in time to keep up with
// a 75 frames/second display (13.3 millisecond frame duration), while
// only causing the OpenGL drawing to happen at a maximum rate of
// 100 frames/second in the unlikely scenario of a very fast computer
// actually being able to draw frames at that rate (given the overhead of
// C#, etc).
mTimer = new System.Windows.Forms.Timer();
mTimer.Interval = 10; // 10-millisecond interval
mTimer.Tick += new EventHandler(PrivateTimerTickEventHandler);
mTimer.Start();
// Set focus to a control so that it can immediately accept input
mCSGL12Control1.Focus();
// Also, whenever the form becomes activated, set focus to the main
// control on the form. The following sets up an event handler for
// that purpose.
this.Activated += new EventHandler(PrivateActivatedEventHandler);
// We want to preview dialog keys (most importantly, the cursor
// keys: up, down, right, left) so we can forward such events to
// the appropriate child control.
this.KeyPreview = true;
}
void PrivateTimerTickEventHandler(object sender, EventArgs e)
{
if (false == DesignMode)
{
mCSGL12Control1.Invalidate();
}
}
private void PrivateActivatedEventHandler(object sender, EventArgs e)
{
// When this form becomes activated, after some time of not
// being active, set input focus to a GL control on the form.
if (false == mCSGL12Control1.Focused)
{
mCSGL12Control1.Focus();
}
}
// Cursor keys (up,down,left,right) need to be specially captured
// and forwarded to the control.
// CAUTION: The KeyPreview property of this Form must be set to 'true'
// for the following method to be called.
protected override bool ProcessDialogKey(Keys keyData)
{
if
(
(keyData == Keys.Up)
|| (keyData == Keys.Down)
|| (keyData == Keys.Left)
|| (keyData == Keys.Right)
)
{
KeyEventArgs e = new KeyEventArgs(keyData);
if (true == mCSGL12Control1.Focused)
{
mCSGL12Example1Handler.KeyDown(mCSGL12Control1, e);
}
else
{
// The CSGL12Control does not have focus.
// Let's simply drop the dialog key event. The user
// may have focus on a different control.
}
return (true);
}
return base.ProcessDialogKey(keyData);
}
}
}
Všimněte si, že je členem "mCSGL12Example1Handler" proměnná je prohlášen odkazovat na instanci a class názvem "CSGL12Example1Handler". Tato třída bude popsáno v další části tohoto dokumentu. Všimněte si, že konstruktor pro "CSGL12Example1Form" přidává metody instance "CSGL12Example1Handler" do "multicast delegates" spojené s různými událostmi generovaných instancí "CSGL12Control". To znamená, že v okamžiku, kdy instance "CSGL12Control" různé události, tyto události způsobí různé metody instance "CSGL12Example1Handler" (tj. "mCSGL12Example1Handler"), které mají být uplatněny.
Všimněte si, že je členem "mTimer" proměnná je prohlášen odkazovat na instanci a class názvem "System.Windows.Forms.Timer". Tento objekt slouží k vyvoláte funkci s názvem "PrivateTimerTickEventHandler" každých 10 milisekund. Funkce s názvem "PrivateTimerTickEventHandler" volání metody instance "CSGL12Control" (tj. "mCSGL12Control1"), která způsobuje, že "Control" k tomu sám. To je, jak instancí "CSGL12Control" může na animované přibližný kurz.
Pouze část definice "class CSGL12Example1Form" se objevuje v C# soubor "CSGL12Example1Form.cs". Další částí definice "class CSGL12Example1Form" objeví v C# soubor "CSGL12Example1Form.Designer.cs". Přestože se soubory s názvy vyhovující vzoru "*.Designer.cs" jsou obecně vytvořeny a měnit pouze grafické "Form Designer" okna a C# editoru je také možné vytvářet a upravovat tyto C# souborů pomocí textového editoru.
Následuje kompletní C# kód obsažený v souboru "CSGL12Example1Form.Designer.cs", která je součástí je například program "CSGL12Example1".
namespace CSGL12Example1
{
partial class CSGL12Example1Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.mCSGL12Control1 = new CSGL12.CSGL12Control();
this.SuspendLayout();
//
// mCSGL12Control1
//
this.mCSGL12Control1.Anchor = ((System.Windows.Forms.AnchorStyles)
((((System.Windows.Forms.AnchorStyles.Top
| System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.mCSGL12Control1.BackColor = System.Drawing.SystemColors.Control;
this.mCSGL12Control1.Location = new System.Drawing.Point(12, 12);
this.mCSGL12Control1.Name = "mCSGL12Control1";
this.mCSGL12Control1.Size = new System.Drawing.Size(640, 480);
this.mCSGL12Control1.TabIndex = 0;
this.mCSGL12Control1.Text = "CSGL12Control1";
//
// CSGL12Example1Form
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(664, 504);
this.Controls.Add(this.mCSGL12Control1);
this.Name = "CSGL12Example1Form";
this.Text = "CSGL12Example1";
this.ResumeLayout(false);
}
#endregion
private CSGL12.CSGL12Control mCSGL12Control1;
}
}
Všimněte si, že tento kód C# obsahuje prohlášení o variabilní "mCSGL12Control1", která odkazuje na instanci "class CSGL12.CSGL12Control" (tj. "class CSGL12Control" v "namespace CSGL12"). Tato instance je vytvořena a nastavit funkci "InitializeComponent".
11. Manipulace s událostmi, na které instancí CSGL12Control
Předchozí část ukázala C# kód k "Form" která obsahovala jedinou instancí "CSGL12Control". V C# kód přidat metod a "class" názvem "CSGL12Example1Handler" jako událost handlery pro různé události, které vznikají při instance "CSGL12Control".
Zde je seznam zajímavých událostí "CSGL12Control" a "delegate" typy spojené s těmito událostmi:
OpenGLStarted CSGL12Control.DelegateOpenGLStarted
KeyDown System.Windows.Forms.KeyEventHandler
KeyUp System.Windows.Forms.KeyEventHandler
MouseDown System.Windows.Forms.MouseEventHandler
MouseUp System.Windows.Forms.MouseEventHandler
MouseMove System.Windows.Forms.MouseEventHandler
MouseWheel System.Windows.Forms.MouseEventHandler
Paint System.Windows.Forms.PaintEventHandler
Pouze "OpenGLStarted" událost je událost typu specifické pro "CSGL12Control".
Všechny ostatní události jsou standardní System.Windows.Forms akcí, jejichž událostí, musí mít určité parametry (specifikovány v každém Forms dokumentace).
V "OpenGLStarted" a "Paint" akce jsou nejdůležitější události OpenGL pro kreslení.
Na "OpenGLStarted" případě je uplatněn před první "Paint" případě je uplatněn.
Proto se "OpenGLStarted" zpracování události musí být přidána ke kontrole před kontrola má nyní příležitost, aby se pokoušel malovat sama, jinak se jedna-time případě nebudou přijaty.
Tato událost je jen pohodlí a lze je ignorovat.
Nicméně, přidání ovladač pro tuto událost je možné ovladač kód dělat někdo-time inicializace, že záleží na OpenGL je připraven k použití.
(OpenGL nemůže být používána do okna existuje a je připravena plnit své první barvy.
Tak se "OpenGLStarted" událost šetří programátora od riziko pokusu o použití OpenGL příliš brzy po spuštění programu.
) Je poměrně snadné přidat logiku v "Paint" handler udělat jednodenní-time inicializace pomocí OpenGL souvislosti s "CSGL12Control".
Na "OpenGLStarted" případě je nabízena jako služba.
Následuje kompletní C# kód obsažený v souboru "CSGL12Example1Handler.cs", která je součástí je například program "CSGL12Example1".
Tento kód je zde prezentovány jako jednoduchý příklad, jak se události vytvořené instancí "CSGL12Control" lze manipulovat čerpat pomocí OpenGL.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
// This program requires "references" to the following:
//
// CSGL12DLL.dll (defines CSGL12.GL)
// CSGL12Control.dll (defines CSGL12.CSGL12Control)
using CSGL12;
namespace CSGL12Example1
{
public class CSGL12Example1Handler
{
private Mesh mMesh;
private ShaderProgram mShaderProgram1;
private ShaderProgram mShaderProgram2;
private ShaderProgram mShaderProgram3;
private ShaderProgram mShaderProgram4;
private ShaderProgram mShaderProgramSelected;
private Bitmap mHUDBitmap;
private Texture mHUDTexture;
private Font mFont1;
private Font mFont2;
private Font mFont3;
private Font mFont4;
private Pen mPen1;
private Brush mBrush1;
private double mViewDistance = 800.0;
private double mViewAzimuthDegrees = 0.0;
private double mViewAltitudeDegrees = 0.0;
private double mViewAzimuthDegreesVelocity = 9.0;
private double mViewAltitudeDegreesVelocity = 5.0;
private Point mMouseClientPositionStart;
private double mViewAzimuthDegreesStart = 0.0;
private double mViewAltitudeDegreesStart = 0.0;
public CSGL12Example1Handler()
{
mMesh = new Mesh();
mShaderProgram1 = new ShaderProgramMandelbrotSet();
mShaderProgram2 = new ShaderProgramWood();
mShaderProgram3 = new ShaderProgramBrick();
mShaderProgram4 = new ShaderProgramCartoon();
mShaderProgramSelected = mShaderProgram1;
mHUDBitmap = new Bitmap(512, 512, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
mHUDTexture = new Texture();
mFont1 = new Font("Verdana", 36.0f);
mFont2 = new Font("Verdana", 24.0f);
mFont3 = new Font("Courier New", 16.0f);
mFont4 = new Font("Courier New", 10.0f);
mPen1 = new Pen(Color.Red, 3.0f);
mBrush1 = new SolidBrush(Color.FromArgb(64, 128, 128, 140));
}
public void OpenGLStarted( CSGL12Control csgl12Control )
{
GL gl = csgl12Control.GetGL();
if (null == gl) { return; }
// Load shaders and set variables
if (true == gl.bglCreateProgramObjectARB)
{
if (null != mShaderProgram1)
{
mShaderProgram1.ShaderProgramCreate(gl);
}
if (null != mShaderProgram2)
{
mShaderProgram2.ShaderProgramCreate(gl);
}
if (null != mShaderProgram3)
{
mShaderProgram3.ShaderProgramCreate(gl);
}
if (null != mShaderProgram4)
{
mShaderProgram4.ShaderProgramCreate(gl);
}
}
// Create cube mesh
mMesh = new Mesh();
mMesh.BuildCube(400.0f);
// Create a texture
mHUDTexture.CreateTextureFromBitmap(gl, mHUDBitmap, true);
// To prevent "tearing" (irregular streaks) due to swapping buffers at
// arbitrary times relative to the vsync times, we indicate that we wish
// to wait for vsync before swapping buffers.
// This request applies when the display driver control panel -- in the
// OpenGL settings area -- is set to let the application decide whether or
// not to wait for vsync. Otherwise, the driver control panel overrides
// any request made here.
if (true == gl.bwglSwapIntervalEXT)
{
gl.wglSwapIntervalEXT(1);
}
}
public void Paint(object sender, PaintEventArgs e)
{
if (null == sender) { return; }
if (false == (sender is CSGL12Control)) { return; }
CSGL12Control csgl12Control = (sender as CSGL12Control);
GL gl = csgl12Control.GetGL();
int clientWidth = csgl12Control.ClientRectangle.Width;
int clientHeight = csgl12Control.ClientRectangle.Height;
if (clientWidth <= 0)
{
clientWidth = 1;
}
if (clientHeight <= 0)
{
clientHeight = 1;
}
// Set the viewport
gl.glViewport(0, 0, clientWidth, clientHeight);
// Clear the viewport
gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
// Basic drawing conditions
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL.GL_LEQUAL);
gl.glEnable(GL.GL_CULL_FACE);
gl.glCullFace(GL.GL_BACK);
gl.glFrontFace(GL.GL_CCW);
// PROJECTION matrix, typically for perspective correction or orthographic projection
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
double aspectRatio = 1.0;
if (0 != clientHeight)
{
aspectRatio = ((double)(clientWidth) / (double)(clientHeight));
}
double verticalFieldOfViewAngle = 60.0;
gl.gluPerspective
(
verticalFieldOfViewAngle, // Field of view angle (Y angle; degrees)
aspectRatio, // width/height
0.1, // distance to near clipping plane
64000.0 // distance to far clipping plane
);
// MODELVIEW matrix, typically used to transform individual models
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
// Preserve current matrix for the active matrix stack (in this case the MODELVIEW matrix)
gl.glPushMatrix();
if (mViewAltitudeDegreesVelocity != 0.0)
{
if (mViewAltitudeDegrees > 70.0)
{
mViewAltitudeDegrees = 70.0;
mViewAltitudeDegreesVelocity *= -1.0;
}
else if (mViewAltitudeDegrees < -70.0)
{
mViewAltitudeDegrees = -70.0;
mViewAltitudeDegreesVelocity *= -1.0;
}
mViewAzimuthDegrees += mViewAzimuthDegreesVelocity * csgl12Control.GetPreviousFrameDurationSeconds();
mViewAltitudeDegrees += mViewAltitudeDegreesVelocity * csgl12Control.GetPreviousFrameDurationSeconds();
}
Vector3f from =
new Vector3f
(
(float)(mViewDistance * Math.Cos(mViewAltitudeDegrees * (Math.PI / 180.0)) * Math.Sin(mViewAzimuthDegrees * (Math.PI / 180.0))),
(float)(mViewDistance * Math.Sin(mViewAltitudeDegrees * (Math.PI / 180.0))),
(float)(mViewDistance * Math.Cos(mViewAltitudeDegrees * (Math.PI / 180.0)) * Math.Cos(mViewAzimuthDegrees * (Math.PI / 180.0)))
);
Vector3f to = new Vector3f(0.0f, 0.0f, 0.0f);
Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
Matrix4x4f camera = Matrix4x4f.LookAt(from, to, up);
float[] matrix = new float[16];
matrix[0] = camera.m11;
matrix[1] = camera.m21;
matrix[2] = camera.m31;
matrix[3] = 0.0f;
matrix[4] = camera.m12;
matrix[5] = camera.m22;
matrix[6] = camera.m32;
matrix[7] = 0.0f;
matrix[8] = camera.m13;
matrix[9] = camera.m23;
matrix[10] = camera.m33;
matrix[11] = 0.0f;
matrix[12] = camera.m14;
matrix[13] = camera.m24;
matrix[14] = camera.m34;
matrix[15] = 1.0f;
gl.glMultMatrixf(matrix);
if (mShaderProgramSelected != null)
{
mShaderProgramSelected.DemonstrateModificationOfVariables(gl, csgl12Control.GetPreviousFrameStartTimeSeconds(), csgl12Control.GetPreviousFrameDurationSeconds());
mShaderProgramSelected.Select(gl);
}
// Draw model(s), using active texture or shader
mMesh.Draw(gl);
// If we used a shader, disable it now...
if (true == gl.bglUseProgramObjectARB)
{
ShaderProgram.ShaderProgram_Select(gl, 0);
}
// Restore the previously-preserved matrix for the active matrix stack (in this case the MODELVIEW matrix)
gl.glPopMatrix();
// Demonstrate drawing text to a GDI+ Bitmap and then copying to
// an OpenGL texture.
DemonstrateDrawingTextToAGDIBitmapAndCopyingToAnOpenGLTexture(csgl12Control, gl);
// Flush all the current rendering and flip the back buffer to the front.
gl.wglSwapBuffers(csgl12Control.GetHDC());
}
public void DemonstrateDrawingTextToAGDIBitmapAndCopyingToAnOpenGLTexture(CSGL12Control csgl12Control, GL gl)
{
bool updateOverlayImage = false;
// The following code only enables an update of the Bitmap
// and OpenGL texture every 64 frames, thus avoiding the
// slowdown of performing updates every single frame.
// HOWEVER, updating the Bitmap and OpenGL texture can be
// done EVERY frame with acceptable speed.
// Updates should be limited to once per frame, but the
// logic to trigger updates can be based on when the relevant
// text changes.
if ((csgl12Control.GetTotalFramesDrawn() % 64) == 0)
{
updateOverlayImage = true;
}
bool showOverlayImage = true;
if (true == updateOverlayImage)
{
using (Graphics g = Graphics.FromImage(mHUDBitmap))
{
g.Clear(Color.FromArgb(0, Color.White));
g.FillEllipse(mBrush1, new Rectangle(0, 0, 256, 256));
g.FillEllipse(mBrush1, new Rectangle(256, 256, 256, 256));
PointF center = new PointF(0.5f * (256.0f + 0.0f), 0.5f * (256.0f + 0.0f));
PointF displacement = new PointF();
double fraction = csgl12Control.GetTotalElapsedTimeSeconds() * 0.1;
displacement.X = 128.0f * (float)Math.Cos(2.0 * Math.PI * fraction);
displacement.Y = 128.0f * (float)Math.Sin(2.0 * Math.PI * fraction);
g.DrawLine(mPen1, center, new PointF(center.X + displacement.X, center.Y + displacement.Y));
PointF carat = new PointF(0.0f, 0.0f);
String text = "";
text = "C# OpenGL (CSGL)";
g.DrawString(text, mFont1, Brushes.Black, carat);
carat.Y += mFont1.GetHeight();
text = "Здравствуйте";
g.DrawString(text, mFont2, Brushes.Black, carat);
carat.Y += mFont2.GetHeight();
text = "γεια σου";
g.DrawString(text, mFont2, Brushes.Black, carat);
carat.Y += mFont2.GetHeight();
text = "مرحبا";
g.DrawString(text, mFont2, Brushes.Black, carat);
carat.Y += mFont2.GetHeight();
text = "שלום";
g.DrawString(text, mFont2, Brushes.Black, carat);
carat.Y += mFont2.GetHeight();
carat.Y += 64.0f;
text = "Shift + 0: Save BMP,PNG,JPG,GIF";
g.DrawString(text, mFont4, Brushes.Black, carat);
carat.Y += mFont4.GetHeight();
text = "1,2,3,4 : Switch shader program";
g.DrawString(text, mFont4, Brushes.Black, carat);
carat.Y += mFont4.GetHeight();
carat.Y += 12.0f;
text = "Text : GDI+ on 512*512 Bitmap.";
g.DrawString(text, mFont4, Brushes.Black, carat);
carat.Y += mFont4.GetHeight();
text = "Bitmap copied to OpenGL texture.";
g.DrawString(text, mFont4, Brushes.Black, carat);
carat.Y += mFont4.GetHeight();
text = "Texture update once per 64 frames,";
g.DrawString(text, mFont4, Brushes.Black, carat);
carat.Y += mFont4.GetHeight();
text = "but more often would be OK.";
g.DrawString(text, this.mFont4, Brushes.Black, carat);
carat.Y += this.mFont4.GetHeight();
carat.Y += 12.0f;
text = String.Format("Frame:{0}", csgl12Control.GetTotalFramesDrawn());
text += " ";
text += String.Format("Time:{0:f2}", csgl12Control.GetTotalElapsedTimeSeconds());
double previousFrameDurationSeconds =
csgl12Control.GetPreviousFrameDurationSeconds();
if (previousFrameDurationSeconds > 1.0e-10)
{
double framesPerSecondOverall =
1.0 / previousFrameDurationSeconds;
text += " ";
text += String.Format("FPS:{0:f2}", framesPerSecondOverall );
}
g.DrawString(text, mFont3, Brushes.Black, carat);
carat.Y += mFont3.GetHeight();
}
mHUDTexture.UpdateTextureWithBitmapData(gl, mHUDBitmap);
}
if (true == showOverlayImage)
{
CSGL12Support.SupportDrawTextureImageUnrotatedAndOrthographically
(
gl,
csgl12Control.ClientSize.Width,
csgl12Control.ClientSize.Height,
mHUDTexture,
0,
0, // i.e., 0 == draw TOP of image at TOP of viewport, Y-axis points DOWN
mHUDTexture.GetWidth(), // glControl.ClientSize.Width, // mHUDTexture.GetWidth(),
mHUDTexture.GetHeight() // glControl.ClientSize.Height // mHUDTexture.GetHeight()
);
}
}
public void KeyDown(object sender, KeyEventArgs e)
{
if (null == sender) { return; }
if (false == (sender is CSGL12Control)) { return; }
CSGL12Control csgl12Control = (sender as CSGL12Control);
GL gl = csgl12Control.GetGL();
if (e.KeyCode == Keys.A)
{
}
if (e.KeyCode == Keys.Z)
{
}
if (e.KeyCode == Keys.D1)
{
mShaderProgramSelected = mShaderProgram1;
}
if (e.KeyCode == Keys.D2)
{
mShaderProgramSelected = mShaderProgram2;
}
if (e.KeyCode == Keys.D3)
{
mShaderProgramSelected = mShaderProgram3;
}
if (e.KeyCode == Keys.D4)
{
mShaderProgramSelected = mShaderProgram4;
}
// NOTE: The only way for cursor key events (up,down,left,right)
// to make it to this function is for the main form to implement
// the following:
//
// protected override bool ProcessDialogKey ( Keys keyData )
//
// and explicitly invoke this KeyDown() method with the
// an appropriately formed KeyEventArgs instance.
if (e.KeyCode == Keys.Up)
{
mViewDistance -= 10.0;
}
if (e.KeyCode == Keys.Down)
{
mViewDistance += 10.0;
}
if (e.KeyCode == Keys.Left)
{
mViewAzimuthDegrees += 1.0;
}
if (e.KeyCode == Keys.Right)
{
mViewAzimuthDegrees -= 1.0;
}
// Save an image of the viewport (press Shift-0 (zero)). The following
// code writes out the viewport in the following image formats: BMP, PNG, GIF, JPG.
// If you only want a single format, comment out the other file write commands.
// BMP has no compression artifacts, but the file can be quite large.
// PNG looks good, and supports 8-bit transparancy (good for textures, etc).
// GIF looks bad unless you build the color table intelligently (there is a
// neural network color table builder for GIF, in C#/.NET, that you can
// find on the Internet; perhaps Paint.NET uses that code); but GIF files
// can be quite small, and supports animation.
// JPG looks good under most circumstances, and the file size can be quite small,
// but transparency is not supported.
// So, for pixel-perfect images, where file size is not important, BMP might be appropriate.
// For textures with transparency, PNG might be appropriate.
// For good-looking images, and small file size, and use in Web pages, JPG might be appropriate.
// For some purposes, with small file sizes, and use in Web pages, GIF might be appropriate.
if ((e.KeyCode == Keys.D0) && (e.Shift == true))
{
DateTime now = DateTime.Now;
String dateTimeString = String.Format("{0:d4}{1:d2}{2:d2}{3:d2}{4:d2}{5:d2}{6:d3}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Millisecond);
String frameIndexString = String.Format("{0:d6}", csgl12Control.GetTotalFramesDrawn());
String fileNameWithoutExtension = "screen" + "_" + dateTimeString + "_" + frameIndexString;
CSGL12Support.SupportWriteViewportToImageFile(gl, fileNameWithoutExtension + ".bmp", System.Drawing.Imaging.ImageFormat.Bmp);
CSGL12Support.SupportWriteViewportToImageFile(gl, fileNameWithoutExtension + ".png", System.Drawing.Imaging.ImageFormat.Png);
CSGL12Support.SupportWriteViewportToImageFile(gl, fileNameWithoutExtension + ".gif", System.Drawing.Imaging.ImageFormat.Gif);
CSGL12Support.SupportWriteViewportToImageFile(gl, fileNameWithoutExtension + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
public void KeyUp(object sender, KeyEventArgs e)
{
}
public void MouseDown(object sender, MouseEventArgs e)
{
if (null == sender) { return; }
if (false == (sender is CSGL12Control)) { return; }
CSGL12Control csgl12Control = (sender as CSGL12Control);
mMouseClientPositionStart = csgl12Control.PointToClient(Cursor.Position);
mViewAzimuthDegreesStart = mViewAzimuthDegrees;
mViewAltitudeDegreesStart = mViewAltitudeDegrees;
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
mViewAzimuthDegreesVelocity = 0.0;
mViewAltitudeDegreesVelocity = 0.0;
}
if ((e.Button & MouseButtons.Right) == MouseButtons.Right)
{
mViewAzimuthDegreesVelocity = 9.0;
mViewAltitudeDegreesVelocity = 5.0;
}
}
public void MouseUp(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Right) == MouseButtons.Right)
{
}
}
public void MouseMove(object sender, MouseEventArgs e)
{
if (null == sender) { return; }
if (false == (sender is CSGL12Control)) { return; }
CSGL12Control csgl12Control = (sender as CSGL12Control);
Point mouseClientPositionCurrent = csgl12Control.PointToClient(Cursor.Position);
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
double azimuth =
mViewAzimuthDegreesStart
- (360.0 / (double)(csgl12Control.Width + 1))
* (double)(mouseClientPositionCurrent.X - mMouseClientPositionStart.X);
double altitude =
mViewAltitudeDegreesStart
+ (180.0 / (double)(csgl12Control.Height + 1))
* (double)(mouseClientPositionCurrent.Y - mMouseClientPositionStart.Y);
double epsilon = 0.05;
if (azimuth < (-180 + epsilon)) { azimuth = (-180 + epsilon); }
if (azimuth > (180 - epsilon)) { azimuth = (180 - epsilon); }
if (altitude < (-90 + epsilon)) { altitude = (-90 + epsilon); }
if (altitude > (90 - epsilon)) { altitude = (90 - epsilon); }
mViewAzimuthDegrees = azimuth;
mViewAltitudeDegrees = altitude;
}
}
public void MouseWheel(object sender, MouseEventArgs e)
{
mViewDistance -= 0.1 * (double)e.Delta;
}
}
}
Všimněte si, že se funkce jmenoval "OpenGLStarted" jsou použity v tomto příkladě vytvořit "pixel shader programs" a OpenGL texturu. Pro tento program je pouze nutnost vytvoření těchto zdrojů jednou, a to je efektivnější vytvořit pouze jednou.
Všimněte si, že se funkce jmenoval "OpenGLStarted" kód kontrol, pokud WGL "extension" funkci s názvem "wglSwapIntervalEXT()" existuje, a pokud tato funkce existuje, je kód, který vyvolá funkci. Že funkce nastavuje stav, který ovlivňuje fungování programu pro celé zasedání, a tak musíme jen zavolat, že funkce jednou, což je důvod, proč jsme se, že pokus o volání funkce v "OpenGLStarted" funkce (což samo o sobě je uplatněn pouze jednou, když OpenGL se začala pro konkrétní "CSGL12Control" předpokládá se, že jsme přidali "OpenGLStarted" metoda vhodná pro případ delegáta).
Funkce s názvem "Paint" obsahuje veškeré kód vyvodit jediný "snímek" animace pomocí OpenGL. V "Paint" funkce se bude nazývat snad 60 krát za sekundu, a to kvůli tomu, že jsou spojena "CSGL12Control" instance je "neoverená" (nucena čerpat sám opět) v tomto kurzu. (Podívejte se na "Form" kód příkladu v předchozí části vidět měřič, který určuje rychlost "neplatnost" a skutečné volání funkce, která způsobí, že instance "CSGL12Control" stane "neplatné.)"
Všechny OpenGL funkce odvolávat pomocí instancí z "class GL" (příklad: gl.gl*()). Instanci "class GL" vzniká z instance "CSGL12Control", která je implicitně uložen v první parametr na "Paint" funkce.
Všechny OpenGL konstanty mohou být upřesněny uvedením "class" jméno "GL" po němž následuje tečka a jméno je konstantní, tj. "GL.GL_TRIANGLES".
V OpenGL kód v tomto případě není zcela zřejmé a snadno pochopitelné, ale doufejme, že si můžete uvědomit, jak je kód lze upravit pro své vlastní účely.
12. Kontrola dostupnosti "rozšíření" funkcí OpenGL
Jednoduše zjistit, jestli boolovských vlajkou stejný název jako OpenGL funkce je "pravda," než začnete používat odpovídající funkce.
V Logická proměnná má název, který začíná "b", po němž následuje název funkce OpenGL.
if (true == gl.bglCreateProgramObjectARB)
{
// glCreateProgramObjectARB() exists and can be invoked.
// Also, because that function is related to pixel shaders, it is very
// likely that other functions that are required for the use of pixel
// shaders also exist and can be invoked.
// . . .
}
Kontrola je nutná pouze pro "rozšíření" funkcí.
OpenGL 1.1 funkce, a všechny GLU funkcí, a základní funkce WGL, nevyžadují takovou kontrolu. Nicméně boolovských flagů existují a jsou stanoveny vhodně, pro všechny tyto funkce poskytuje "class GL", včetně základních funkcí OpenGL 1.1. Proto se důsledně zkontrolovat dostupnost všech funkcí v dané třídě.
Vědět, zda funkce je "rozšíření" je v kompetenci programátora.
Nicméně, funkci název přípony, například "EXT", "ARB", "MESA", "NV" (NVidia), "APPLE", atd., pomůže uvést rozšíření funkcí.
Je-li funkce "gl*()" má sousední funkci "gl*ARB()" nebo "gl*NV()," pak je funkce "gl*()" je pravděpodobně příponu (pokud jde o Windows OPENGL32.DLL se obává).
Jedinou výhodou je známo, zda funkce je "rozšíření" (s ohledem na Windows OPENGL32.DLL) je schopno vyhnout se kontrole, pokud funkce jsou k dispozici.
Můžete hledat všechny OpenGL funkcí používaných v kódu, a poté vybudovat abecední seznam různých funkcí použít.
Tehdy, na počátku svého programu, po CSGL12Control volá OpenGLStarted delegáta, jednoduše kontrolovat všechny boolovských vlajek pro všechny funkce, které hodlají používat.
Pokud se rozhodnete ukončit program, je-li všechny "potřebné" funkce chybí, pak veškeré kontroly na těchto funkcí v kódu může být odstraněn.
Také si můžete vytvořit skupinu non-základních funkcí v kontrole a případně informovat uživatele o veškerých změnách funkce, a případně opustit kontroly rozptýlené kolem v kódu.
S více OpenGL zkušenosti, můžete si stáhnout i smysl toho, co se týkají rozšíření (příklady: zobrazování, shadery, nárazníky, komprese, ...).
Proto si můžete zkontrolovat na přítomnost jediné kritické funkce a používání těchto informací se rozhodnout, zda celou podskupinu je pravděpodobné, že budou přítomni.
13. Speed
Z různých důvodů, C# je pomalejší než non-CLR C/C++.
C# nakonec sestavují na rodný jazyk montáž, stejně jako pro C/C++, ale vzhledem k zárukám, které C# jazyka a .NET CLR, celková rychlost software postavený na C# a .NET je poněkud pomalejší, než se software postavený pomocí non-CLR C/C++.
Proto, jak se na nejvyšší možnou rychlost znamená použití non-CLR C/C++ místo C#.
Navíc, protože jakékoli volání nativní knihovny z C# zahrnuje P/Invoke, připomínali takové funkce, jako je OpenGL funkcí bude vyžadovat určitou dobu na provedení práce ve P/Invoke vrstvy.
Přesto se zdá "CSGL12" pracovat rychle, aby mohly být použity pro mnoho real-time grafické účely, například pro jednoduché hry, 3D prohlížeče, editory, nebo 3D prezentací. To platí zejména v případě, většina práce se provádí v GPU místo na CPU.
14. Srovnání "CSGL12" a "Tao Framework"
V "Tao Framework" je velká C# / .NET knihovna, která poskytuje rozhraní pro mnoho open-source knihovny, jako OpenGL, OpenAL (audio), SDL (a hraní / simulační platformu), Open Dynamics Engine (ODE) (fyzika), atd.
V Tao Framework je kříž-platforma (Windows, Linux, Mac OS X).
"CSGL12" pouze poskytuje rozhraní pro OpenGL a je určen pouze pro operační systém Windows.
V Tao Framework má obec. Člověk by mohl těžit z komunikace s ostatními uživateli o Tao Framework.
Přesto se zdá, že by mohlo být mnoho účelů, pro které "CSGL12" by mohlo být jednodušší použít pro Windows programy.