C# OpenGL interface
voor de Windows besturingssysteem
Colin Fahey

CSGL12Control op een Form, blijkt een „fractale“ pixel shader programma en GDI+ tekening gekopieerd naar een textuur

Twee CSGL12Control gevallen op een Form, Resultaat pixel shader-programma's en texturen

Een 3D-avatar die roams de desktop en kan worden verplaatst met de cursor
1. Software
CSGL12_20090725.zip
CSGL12: C# OpenGL interface voor Windows, versie 12
4170499 bytes
MD5: 30781a6570441785ea636f2ae1cd16ef
2. Al de C# computer code in de C# OpenGL interface (CSGL12) is in het „publieke domein“
Ik schreef al het C# computer code binnen de C# OpenGL interface (CSGL12).
Ik verklaar al het C# computer code binnen de C# OpenGL interface (CSGL12) worden in het „publieke domein.“
Daarom is de computer code kan worden gebruikt voor elk doel (commercieel of prive), zonder betaling, zonder beperkingen, zonder verplichtingen en zonder erkenning van de oorspronkelijke auteur.
De code kan worden gewijzigd, of delen hergebruikt, zonder beperkingen en zonder verplichtingen en zonder erkenning van de oorspronkelijke auteur.
Het voorbeeld programma's bevatten een kleine hoeveelheid computer-code (in het bijzonder, „shader computer code) geschreven door andere mensen.“ Een dergelijke code wordt niet binnen de interface zelf en kan worden trivially verwijderd. Een dergelijke code is alleen aan te tonen dat de eenvoud van het gebruik van de interface te creëren en het gebruik „shader's.“
3. Inleiding
„CSGL12“ is een verzameling van C# computer bestanden die code implementeert een interface naar de OpenGL grafische bibliotheek (inclusief alle uitbreidingen van OpenGL tot het jaar 2007) voor de Windows besturingssysteem.
De C# computer code bestanden in de „CSGL12“ verzameling maken het eenvoudig toe te voegen OpenGL tekening aan een C# / .NET software met een „Form“ (een geval van „System.Windows.Forms.Form“).
De „CSGL12“ verzameling van computer-code-bestanden bevat een bestand met de naam „CSGL12Control.cs“, waarin een klasse genaamd „CSGL12Control“, afgeleid van „System.Windows.Forms.Control“. Elk exemplaar van „CSGL12Control“ een onafhankelijke OpenGL tekening gebied. Het is heel gemakkelijk om meerdere exemplaren van CSGL12Control naar een Form (een geval van System.Windows.Forms.Form).
4. Kenmerken en vereisten van „CSGL12“
De code is alleen voor Windows besturingssystemen die de .NET 2.0 Framework (Windows 2000, Windows XP, Windows Vista, Windows 7)
De code kan worden opgesteld op basis van „Microsoft Visual C# 2008 Express Edition“ (een gratis compiler), of soortgelijke C# compilers.
De code moet worden gebouwd met de „[X] Allow unsafe code“ bouwen optie zodat geoptimaliseerde beeld gegevens kopiëren functies kunnen worden gebruikt. Als u een expert C# programmeur kunt u eenvoudig het delen van de code die C# eisen dat de „unsafe“ optie en uitschakelen indien gewenst of vereist is. Image gegevens te kopiëren is 10 keer sneller met behulp van „unsafe“ code dan het alternatief, en dit is waarom een dergelijke code wordt gebruikt. Als u een DLL dat alle van de „unsafe“ code, dan is een project dat gebruik maakt van dat DLL vereist niet worden gebouwd met de „unsafe“ optie en dus kun je concluderen dat de afwezigheid van de „unsafe“ optie in een project houdt geen extra veiligheid (omdat vele DLL bestanden die worden gebruikt impliciet of expliciet door het programma bevat „onveilige“ code).
De code kan worden verzameld en gebruikt door een van de volgende kenmerken:
Microsoft Visual C# 2008 Express Edition
Microsoft Visual Studio 2008
Microsoft .NET 3.5 SDK
SharpDevelop
Mono Project
De code biedt de meeste OpenGL extensies (door middel van het jaar 2007), met inbegrip van „vertex shaders“ en „pixel shaders“.
De code bepaalt 1570 functies die verband houden met OpenGL:
336 GL functions
51 GLU functions
19 WGL functions
1164 extensions
De code biedt een aantal alternatieve varianten van de 1570 functies met verschillende parameter types, voor het gemak.
De code omschrijft meer dan 3244 constanten voor OpenGL.
De code maakt het mogelijk om meerdere OpenGL tekening contexten, alle animeren onafhankelijk, op elke „Form“.
Klikken op een „CSGL12Control“ geeft „input focus,“ waardoor latere toetsenbord en muis wiel ingang. Cursor klikken en bewegingen zijn ontvangen, wanneer de cursor binnen de rechthoekige ruimte van een geval van „CSGL12Control“.
De code bevat functies om te laten zien hoe een aantal gemeenschappelijke OpenGL taken in C# en .NET.
De code geeft een overzicht van alle OpenGL constanten en functies in alfabetische volgorde „class GL“ in „GL.cs“, waardoor het gemakkelijk is om te bepalen of een constante of functie ontbreekt (wat onwaarschijnlijk is, met uitzondering van de uitbreidingen die na het jaar 2007).
Het voorbeeld programma's laten zien hoe GDI+ tekening naar een Bitmap, en vervolgens hoe te kopiëren dat Bitmap aan een OpenGL textuur.
Dit maakt het mogelijk tekst en andere GDI+ tekening mogelijkheden om bij te dragen aan een OpenGL scene.
De GDI+ Bitmap kan worden bijgewerkt en ge-upload naar een OpenGL textuur zo vaak een keer per OpenGL frame.
Het voorbeeld programma's laten zien hoe te kiezen uit verschillende „pixel shader programs“ terwijl het programma draait.
Het voorbeeld laat zien hoe programma's te schrijven OpenGL buffers aan beeldbestanden (JPG, BMP, GIF, PNG).
Druk Shift + 0 (shift-nul) te schrijven OpenGL de buffer naar afbeeldingsbestanden.
Het voorbeeld laat zien hoe de code compileren „GL.cs“ in een DLL bestand en vervolgens toe te voegen dat DLL bestand naar een ander project, kunnen voorkomen dat de Microsoft code redactie (bijv. Microsoft Visual C# 2008 Express Edition, etc) met „IntelliSense“ (context-gevoelige code completion) uit steeds veelvuldig en aanhoudend reageert (herhaaldelijk onderbreken voor vele seconden, waardoor de redactie volstrekt onbruikbaar). Na het bestand „GL.cs“ direct opgenomen in een project dat wordt bewerkt door een Microsoft code editor is niet praktisch, tenzij iemand bereid is te verduren de traagheid van de uitgever. Dit probleem heeft beïnvloed Microsoft Visual Studio 2003, 2005, 2008, en zal waarschijnlijk van invloed zijn op de 2010 versie ook.
Het voorbeeld code toont het gebruik van meerdere exemplaren van „CSGL12Control“ op een „Form“.
Het voorbeeld code bevat code om een 3D „avatar“ dat roams het bureaublad van Windows.
5. Voorbeeld programma's opgenomen met „CSGL12“
5.1 „CSGL12DLL“
Het project genaamd „CSGL12DLL“ een DLL bestand met de naam „CSGL12DLL.dll“ die „class GL“ (gedefinieerd in de C# bestand „GL.cs“).
Putting „class GL“ bij een DLL bestand, en vervolgens met behulp van dat DLL in andere projecten die gebruik maken van „class GL“, helpt voorkomen dat een extreem probleem met alle Microsoft code redactie met de IntelliSense functie. Gebruik van de C# bestand GL.cs rechtstreeks in een project zou leiden tot een Microsoft code editor met de IntelliSense functie volledig reageert en onbruikbaar bijna continu te wijten aan de inefficiëntie van de IntelliSense functie (en het feit dat IntelliSense blijkbaar blokkeert de belangrijkste programma draad van de editor ).
Als u een C# code editor die niet is geproduceerd door Microsoft (bijv. „SharpDevelop“, „MonoDevelop“, etc), dan kun je simpelweg het bestand „GL.cs“ rechtstreeks in uw projecten, en je zou waarschijnlijk niet krijgen een voordeel van het gebruik van „CSGL12DLL.dll“.
5.2 „CSGL12Control“
Het project genaamd „CSGL12Control“ een DLL bestand met de naam „CSGL12Control.dll“ die „class CSGL12Control“ (gedefinieerd in de C# bestand „CSGL12Control.cs“).
Putting „class CSGL12Control“ bij een DLL bestand, maakt dat „Control“ (dwz een klasse afgeleid van „System.Windows.Forms.Control“) worden toegevoegd aan de „Toolbox“ van Microsoft Visual C# 2008 Express Edition (en soortgelijke C# redactie). Na „CSGL12Control“ in de „Toolbox“ maakt het eenvoudig voor een persoon om een geval van „CSGL12Control“ naar een „Form“ in de „Designer“ (bijvoorbeeld een persoon kan gewoon gebruik maken van de cursor te selecteren en sleept u een exemplaar van „CSGL12Control“ van de „Toolbox“ naar een „Form“).
De „CSGL12Control“ object beheert een OpenGL tekening context. Meerdere exemplaren van „CSGL12Control“ naast elkaar kunnen bestaan op een „Form“.
5.3 „CSGL12Example1“
Het project genaamd „CSGL12Example1“ produceert een uitvoerbaar programma bestand (EXE) genaamd „CSGL12Example1.exe“. Het programma maakt gebruik van „CSGL12DLL.dll“ en „CSGL12Control.dll“ om een geval van CSGL12Control en teken een kubus met OpenGL.
Het programma demonstreert het gebruik van vier verschillende „pixel shaders“ „(fractaal, baksteen, hout,“ en „cartoon).“
Het programma toont ook aan het gebruik van „GDI+“, een .NET tekening bibliotheek, om tekst en andere vormen tot een „Bitmap“ object (een „GDI+“ object), en kopieer de afbeelding gegevens van die „Bitmap“ een „texture“ in OpenGL, waardoor het beeld getrokken door „GDI+“ te verschijnen in OpenGL tekening. Dit vermogen is erg handig omdat OpenGL mist veel van de 2D tekening kenmerken gevonden in „GDI+“ en soortgelijke 2D tekening libaries.
5.4 „CSGL12Example2“
Het project genaamd „CSGL12Example2“ produceert een uitvoerbaar programma bestand (EXE) genaamd „CSGL12Example2.exe“. Het programma maakt gebruik van „CSGL12DLL.dll“ en „CSGL12Control.dll“ om twee gevallen van CSGL12Control, die elk trekt een kubus met OpenGL.
Het programma heeft een „SplitContainer“ „Control“ op de „Form“. Elk van de twee terreinen van de „SplitContainer“ bevat een geval van CSGL12Control. Zo een persoon kan de positie van de splitsing tussen de twee gevallen van CSGL12Control. Dit toont de flexibiliteit van de CSGL12Control.
Een van de gevallen van CSGL12Control stuurt evenementen tot een reeks van gebeurtenis-handlers in een geval van „CSGL12Example2Handler1.cs“, die gebruik maakt van dezelfde code als „CSGL12Example1Handler.cs“ in de „CSGL12Example1“ voorbeeld project. Daarom is een van de gevallen CSGL12Control vestigt een kubus met een geselecteerde „pixel shader“ uit vier beschikbare „pixel shaders“.
Het andere exemplaar van CSGL12Control stuurt evenementen tot een reeks van gebeurtenis-handlers in een geval van „CSGL12Example2Handler2.cs“, waarbij een kubus met een textuur afbeelding (of een „schaakbord“ patroon als een image-bestand met de naam „image.jpg“ is niet gevonden).
5.5 „CSGL12Avatar“
Het project genaamd „CSGL12Avatar“ produceert een uitvoerbaar programma bestand (EXE) genaamd „CSGL12Avatar.exe“. Het programma maakt gebruik van „CSGL12DLL.dll“ en „CSGL12Control.dll“ om een kubus met OpenGL op „Form“ zonder rand, met kleuren op basis van transparantie ingeschakeld, om een 3D „avatar“ dat roams de Windows bureaublad gebied.
De bewegende avatar kan worden geklikt en versleept naar een nieuwe locatie met behulp van de cursor. Dubbelklikken op het avatar zal het verdwijnen. Hoewel de code enkel vestigt een kubus, OpenGL kunnen worden gebruikt om andere dingen.
Meerdere exemplaren van de „avatar“ programma kan worden gestart. Zo veel onafhankelijke „avatar“ gevallen kan gelijktijdig zwerven de Windows bureaublad. Dit is grappig. Een deskundige C# programmeur kan genieten van het vinden van manieren om de coördinatie van de activiteiten van veel van dergelijke gevallen „avatar.“
Helaas, het tempo waarin de Window object met de transparantie wordt bijgewerkt op het scherm is veel langzamer dan het tempo waarin OpenGL kunnen trekken. De „avatar“ alleen updates 10 keer per seconde. Ik weet niet of dit kan worden verbeterd.
5.6 „CSGL12BuiltExecutableExamplesForReference“
De map met de naam „CSGL12BuiltExecutableExamplesForReference“ bevat DLL bestanden en bestanden EXE geproduceerd door alle van de voorbeeld projecten. Deze bestanden zijn bedoeld als referentie, zodat de bestanden kunnen meteen worden getest, zelfs als een persoon niet de mogelijkheid hebben om de diverse projecten uit de verstrekte C# code.
5.7 „CSGL12UsefulCode“
De map met de naam „CSGL12UsefulCode“ bevat C# bestanden die nuttig kan zijn voor mensen die willen doen gemeengoed tekening operaties met OpenGL. De map bevat ook de DLL bestanden „CSGL12DLL.dll“ en „CSGL12Control.dll“ voor gemak.
De code in die map definieert class verschillende soorten, zoals Color4f, Vector3f, Matrix4x4f, Triangle, Mesh, ImageData, Texture, ShaderProgram, enz. De code is redelijk efficiënt, maar de code is alleen bedoeld om mensen te inspireren om hun eigen implementaties.
6. CSGL12 bestanden
De „CSGL12“ verzameling van C# computer code bestanden bevat de bestanden weergegeven in het volgende schema:

De „CSGL12“ verzameling van C# computer code bestanden bevat de bestanden weergegeven in dit schema.
„CSGL12“ De software omvat ook projecten om de twee DLL bestanden („CSGL12DLL.dll“ en „CSGL12Control.dll“) weergegeven in het diagram. Deze twee DLL-bestanden kunnen worden gecreëerd om het gemakkelijker te maken programma's die gebruikmaken van OpenGL, maar het is ook mogelijk om programma's met alleen de C# bestanden rechtstreeks.
7. „namespace CSGL12“ en „class“ soorten
De „CSGL12“ verzameling van C# computer code bestanden definieert „namespace CSGL12“ en de „class“ soorten weergegeven in het volgende schema:

De „CSGL12“ verzameling van C# computer code bestanden definieert „namespace CSGL12“ en de „class“ soorten in dit diagram.
Een programma dat doet OpenGL tekening kan worden gemaakt met alleen „class GL“ (met behulp van de C# bestand GL.cs rechtstreeks, of via de DLL bestand CSGL12DLL.dll dat ook „class GL“). Echter, met behulp van „class CSGL12Control“ (met behulp van de C# bestand CSGL12Control.cs rechtstreeks, of via de DLL bestand CSGL12Control.dll dat ook „class CSGL12Control“) maakt het toevoegen van OpenGL tekening op een Form (System.Windows.Forms.Form) eenvoudig en handig.
De C# klassen Color4f, CSGL12Support, ImageData, ..., aan de onderzijde van het diagram worden alleen aangeboden voor het gemak. Deze klassen maken het makkelijker te maken programma's die trekken met behulp van OpenGL. Echter, je kan al klassen die de handelingen in die klassen, of je kan kiezen om soortgelijke klassen die de handelingen anders of efficiënter. Deze lessen worden aangeboden als voorbeelden van een bepaalde code ontwerp en uitvoering.
8. Met behulp van een enkele „CSGL12Control“ op een System.Windows.Forms.Form
8.1 Programma structuur
Het volgende diagram laat zien hoe een programma met een System.Windows.Forms.Form kunt een enkele „CSGL12Control“ doen tekening met OpenGL. Het diagram toont de verschillende CSGL12 bestanden gebruikt voor het bouwen van het programma.

Een programma met behulp van een enkele „CSGL12Control“ op een System.Windows.Forms.Form
8.2 Microsoft Visual C# te creëren met behulp van het programma
(1) Start Microsoft Visual C#.
(2) In het menu, selecteert u „File“ -> „New Project...“.
(3) In de „New Project“ dialoogvenster dat verschijnt, kiest u „Windows Forms Application“, en kies een naam voor het programma, en druk „OK“.
(4) Onmiddellijk „Solution“ opslaan door het selecteren van „File“ -> „Save All“. Een dialoogvenster met de titel „Save Project“ zal verschijnen, waarmee u het project naam, directory locatie, en de „oplossing“ voor het project. Vergeet niet de directory locatie, zodat u klaar bent voor de volgende instructie. Druk op de knop „Save“ te redden van het project.
(5) Kopieer alle bestanden uit de map „CSGL12UsefulCode“ in de „CSGL12“ software naar de directory met de broncode bestanden van het nieuwe project (dat wil zeggen, de map met de bestanden „Form1.cs“, „Form1.Designer.cs“, „Program.cs“, etc), zodat de bestanden „CSGL12DLL.dll“, „CSGL12Control.dll“, „Color4f.cs“ , „CSGL12Support.cs“, enz, zijn naast het nieuwe project bestanden „Form1.cs“, enz.
(6) In Microsoft Visual C#, voeg de „CSGL12“ C# bestanden aan het project. In het menu, selecteert u „Project“ -> „Add Existing Item...“, en in de „Add Existing Item“ dialoogvenster selecteer alle C# van de bestanden van de CSGL12 software („Color4f.cs“, „CSGL12Support.cs“, „ImageData.cs“, ...).
(7) In Microsoft Visual C#, voeg de „verwijzingen“ naar de DLL bestanden „CSGL12DLL.dll“ en „CSGL12Control.dll“. In het menu, selecteert u „Project“ -> „Add Reference...“, en in de „Add Reference“ dialoogvenster, selecteert u de „Browse“ tabblad en selecteer de bestanden „CSGL12DLL.dll“ en „CSGL12Control.dll“ uit het project bronbestand map, en druk „OK“.
(8) In Microsoft Visual C#, voeg de „CSGL12Control“ aan de „Toolbox“. In het menu, selecteert u „Tools“ -> „Choose Toolbox Items...“. In de „Choose Toolbox Items“ dialoogvenster dat verschijnt, drukt u op de „Browse...“ knop en ga naar het project directory met de broncode bestanden en selecteer „CSGL12Control.dll“. Druk op de knop „OK“.
(9) In Microsoft Visual C#, bekijken de „Toolbox“. In het menu, selecteert u „View“ -> „Toolbox“. In de „Toolbox“, ga naar de sectie genaamd „General“ en zoek het item „CSGL12Control“. Met behulp van de cursor, klikt u op het item „CSGL12Control“ en sleep het naar de „Form“ in „Design“ bekijken.
(10) In Microsoft Visual C#, in de „Form“ „Design“ bekijken, verplaatst u de „CSGL12Control“ bijvoorbeeld op de „Form“ en aanpassen van de breedte en hoogte. In de „Properties“ paneel, de „Anchor“ waarde op te nemen „Top, Bottom, Left, Right“ als u wilt dat de controle te veranderen grootte volgens veranderingen in het programmavenster grootte.
(11) In Microsoft Visual C#, verander het project eigenschappen, zodat zij kunnen gebruiken „unsafe“ code. In het menu, selecteert u „Project“ -> „[project] Properties...“. Selecteer het dialoogvenster dat verschijnt, kiest u het tabblad genaamd „Build“ en vink het vakje genaamd „[X] Allow unsafe code“. Sluit het project in het dialoogvenster Eigenschappen.
(12) In Microsoft Visual C#, voeg een nieuwe C# bestand aan het project. In het menu, selecteert u „Project“ -> „Add New Item...“. In het dialoogvenster genaamd „Add New Item“, kiest u de sjabloon genaamd „Class“, en kies een naam voor de nieuwe klasse, bijvoorbeeld „CSGL12MyHandler.cs“ en druk vervolgens op de knop „Add“. Kijk naar het voorbeeld project „CSGL12Example1“, op het bestand met de naam „CSGL12Example1Handler.cs“, als een voorbeeld van hoe de code van „CSGL12MyHandler.cs“ moeten worden geschreven.
(13) In Microsoft Visual C#, in de „Solution Explorer“, klikt u op „Form1“. In het menu, selecteert u „View“ -> „Code“ (of druk F7, of klik met de rechtermuisknop op „Form1“ en kies „View Code“. De code in het bestand „Form1.cs“ verschijnt in de editor. Wijzig de code in het bestand „Form1.cs“ te zijn vergelijkbaar met de code in het bestand „CSGL12Example1Form.cs“ in het project „CSGL12Example1“ opgenomen in de „CSGL12“ software. In het bijzonder, maken van een variabele voor een exemplaar van uw event handler klasse (bijv. „CSGL12MyHandler“), en voeg vervolgens de methoden van deze klasse aanleg als gebeurtenis-handlers voor de verschillende gebeurtenissen van de aanleg van „CSGL12Control“ op de „Form“.
(14) In Microsoft Visual C#, compileer het en voer het programma. Als u wilt delen van het programma, moet u de twee DLL bestanden („CSGL12DLL.dll“ en „CSGL12Control.dll“) met het uitvoerbare bestand (*.exe).
Als u een expert C# programmeur, dan kunt u voorkomen dat de noodzaak om de DLL bestanden („CSGL12DLL.dll“ en „CSGL12Control.dll“) met uw uitvoerbaar (*.exe).
Kopieer de bestanden „GL.cs“, „CSGL12Control.cs“ en „PrecisionTime.cs“ van de projecten genoemd „CSGL12DLL“ en „CSGL12Control“ in de „CSGL12“ software naar de bron van uw huidige project. Voeg de bestanden „GL.cs“, „CSGL12Control.cs“ en „PrecisionTime.cs“ aan uw project, zodat ze worden samengesteld direct in het programma. Heeft u geen verwijzingen naar „CSGL12DLL.dll“ en „CSGL12Control.dll“ in het project.
Kijk naar de „CSGL12Example1“ project in de „CSGL12“ software, en kijken naar de code in de bestanden met de naam „CSGL12Example1Form.cs“ en „CSGL12Example1Form.Designer.cs“ om te zien welke code is vereist voor het creëren en initialiseren van een geval van „CSGL12Control“ op een „Form“. Toevoegen soortgelijke code aan „Form1.cs“ en „Form1.Designer.cs“ handmatig maken en initialiseren van een geval van „CSGL12Control“ op uw „Form“.
Deze procedure is zeer lastig en vereist deskundigheid en zorgvuldige aandacht, maar de resulterende uitvoerbaar (*.exe) niet vereist „CSGL12DLL.dll“ of „CSGL12Control.dll“. Het is erg leuk om te kunnen delen van uw software in de vorm van een uitvoerbaar bestand (*.exe) zonder dat andere bestanden.
8.3 Toevoeging van „verwijzingen“ naar CSGL12DLL.dll en CSGL12Control.dll
Deze sectie omvat beelden van Microsoft Visual C# 2008 Express Edition toe te voegen met behulp van „verwijzingen“ naar de DLL bestanden CSGL12DLL.dll en CSGL12Control.dll aan het project.
In het menu, selecteert u „Project“ -> „Add Reference...“. Of klik met de rechtermuisknop op de „References“ item in de „Solution Explorer“ paneel en „Add Reference...“ kies, zoals weergegeven in de volgende afbeelding.

Contextmenu voor het „References“ item in de „Solution Explorer“, waarop de „Add Reference...“ optie
Na het selecteren van de optie „Add Reference...“, wordt een dialoogvenster genaamd „Add Reference“ zal verschijnen. In dit dialoogvenster selecteert u de „Browse“ tabblad en selecteer het DLL bestanden „CSGL12DLL.dll“ en „CSGL12Control.dll“, zoals weergegeven in de onderstaande afbeelding en druk op de knop „OK“.

De „Browse“ tabblad van de „Add Reference“ dialoogvenster met de DLL bestanden „CSGL12DLL.dll“ en „CSGL12Control.dll“ beide geselecteerd
Na het indrukken van de knop „OK“, de „Add Reference“ dialoogvenster zal verdwijnen, en de DLL bestanden „CSGL12DLL.dll“ en „CSGL12Control.dll“ zal verschijnen in de „References“ filiaal in de „Solution Explorer“, zoals weergegeven in het volgende diagram.

De DLL bestanden „CSGL12DLL.dll“ en „CSGL12Control.dll“ in de „References“ filiaal in de „Solution Explorer“
8.4 Het toevoegen van CSGL12Control aan de Toolbox in Microsoft Visual C# 2008 Express Edition
Deze sectie bevat afbeeldingen van het gebruik van Microsoft Visual C# 2008 Express Edition toe te voegen CSGL12Control aan de „Toolbox“ zodat een persoon kan gemakkelijk toevoegen instances van CSGL12Control naar een „Form“ in de „Designer“ (Shift+F7 standaard).
In het menu, selecteert u „View“ -> „Toolbox“. In de „Toolbox“, ga naar de sectie genaamd „General“, zoals weergegeven in de volgende afbeelding.

De „General“ deel van de „Toolbox“
Klik met de rechtermuisknop ergens in het „Toolbox“. Selecteer de optie „Choose Items...“ in het snelmenu dat verschijnt, zoals weergegeven in de volgende afbeelding.

De optie „Choose Items...“ in het contextmenu voor de „Toolbox“
Als alternatief, in het menu selecteren „Tools“ -> „Choose Toolbox Items...“.
De „Choose Toolbox Items“ dialoogvenster verschijnt, zoals weergegeven in de volgende afbeelding.

De „Choose Toolbox Items“ dialoogvenster
In de „Choose Toolbox Items“ dialoogvenster „Browse“ druk op de knop. In de „Open“ dialoogvenster dat verschijnt, selecteert u de DLL bestand „CSGL12Control.dll“, zoals weergegeven in de onderstaande afbeelding en druk vervolgens op de knop „OK“.

De „Open“ dialoogvenster met de DLL bestand „CSGL12Control.dll“ geselecteerd
De „CSGL12Control“ item wordt nu weergegeven in het dialoogvenster „Choose Toolbox Items“, zoals weergegeven in de volgende afbeelding. Druk op de knop „OK“.

De „CSGL12Control“ object nu weergegeven in het dialoogvenster „Choose Toolbox Items“
De „CSGL12Control“ item moet nu in het „Toolbox“, zoals weergegeven in de volgende afbeelding.

De „CSGL12Control“ object nu verschijnt in de „Toolbox“
8.5 Het toevoegen van CSGL12Control naar een „Form“ met behulp van de „Toolbox“
Deze sectie omvat beelden van Microsoft Visual C# 2008 Express Edition toe te voegen met behulp van een geval van CSGL12Control naar een „Form“ door gebruik te maken van de „Toolbox“.
In het menu, selecteert u „View“ -> „Designer“ (Shift+F7 standaard). Of dubbelklik op „Form*.cs“ een bestand in de „Solution Explorer“. Of klik met de rechtermuisknop op een bestand „Form*.cs“ in de „Solution Explorer“ en selecteer „View Designer“. Via een van deze drie methoden, de „Designer“ venster voor een „Form“ moet verschijnen.
In het menu, selecteert u „View“ -> „Toolbox“. In de „Toolbox“, ga naar de sectie genaamd „General“. Een item genaamd „CSGL12Control“ verschijnen er, zoals weergegeven in de volgende afbeelding.

De „CSGL12Control“ moet reeds in de „Toolbox“
Met behulp van de cursor, klikt u op het item „CSGL12Control“ en sleep het naar de „Form“ in „Designer“. Een geval van „CSGL12Control“ moet verschijnen op de „Form“ zoals weergegeven in de volgende afbeelding.

Een geval van „CSGL12Control“ op een „Form“ in de „Designer“
In de „Form“ „Designer“ bekijken, verplaatst u de aanleg van „CSGL12Control“ op de „Form“ en aanpassen van de breedte en hoogte.
Klik op de aanleg van „CSGL12Control“ op de „Form“ om deze te selecteren. Daarna, in de „Properties“ paneel, de „Anchor“ waarde op te nemen „Top, Bottom, Left, Right“ zodat de grootte van de „CSGL12Control“ zal veranderen als reactie op veranderingen in het programmavenster grootte. Je zou ook willen veranderen de naam van de variabele (dwz de waarde voor „(Name)“) voor de aanleg van „CSGL12Control“ van de automatische default (bijv. „csgL12Control“) om iets voor je code (bijvoorbeeld „mCSGL12Control“ of „mCSGL12Control1“, etc).
De volgende afbeelding toont de „Form“ „Designer“ bekijken en de „Properties“ paneel.

Een geval van CSGL12Control op een Form in de Designer, en de „Properties panel
9. Met behulp van twee gevallen van „CSGL12Control“ op een System.Windows.Forms.Form
Het volgende diagram toont een voorbeeld van hoe twee gevallen van „CSGL12Control“ kan worden toegevoegd aan een System.Windows.Forms.Form doen tekening met OpenGL in een programma.

Een programma met behulp van twee gevallen van „CSGL12Control“ op een System.Windows.Forms.Form
Volg de instructies in de vorige sectie om een enkel exemplaar van „CSGL12Control“ een „Form“. Vervolgens sleept u een tweede exemplaar van „CSGL12Control“ van de „Toolbox“ aan de „Form“ voor het toevoegen van een tweede „CSGL12Control“.
Elk exemplaar van „CSGL12Control“ krijgt een eigen variabele naam. Elk exemplaar van „CSGL12Control“ kan zijn eigen bijbehorende event handler klasse, of het kan gebruiken verschillende gevallen van een enkele klasse handler type.
Studie het voorbeeld project „CSGL12Example2“ om te leren hoe twee gevallen „CSGL12Control“ kunnen hun evenementen gestuurd naar twee verschillende gevallen van aangepaste gebeurtenishandler klassen met verschillende OpenGL tekening functies.
Het voorbeeld programma „CSGL12Example2“ heeft elk exemplaar van „CSGL12Control“ in een „SplitContainer“ „Control“, gewoon een manier om aan te tonen in welk geval van „CSGL12Control“ kan worden gebruikt. Echter, gevallen van „CSGL12Control“ kan plaats worden gebracht die rechtstreeks op de „Form“.
10. Voorbeeld C# code voor een „Form“ met een geval van CSGL12Control
De volgende is de complete C# code in het bestand „CSGL12Example1Form.cs“, die deel uitmaakt van het voorbeeld programma „CSGL12Example1“.
Deze code wordt hier voorgesteld als een eenvoudig voorbeeld van hoe een geval van CSGL12Control kan worden gemaakt en gebruikt door een „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);
}
}
}
Merk op dat het lid variabele „mCSGL12Example1Handler“ is verklaard om te verwijzen naar een instantie van een class vernoemd „CSGL12Example1Handler“. Deze klasse wordt beschreven in een volgend deel van dit document. Merk op dat de constructor voor „CSGL12Example1Form“ voegt de methoden van de aanleg van „CSGL12Example1Handler“ aan de „multicast delegates“ in verband met de diverse evenementen die door een instantie van „CSGL12Control“. Dit betekent dat wanneer de aanleg van „CSGL12Control“ genereert verschillende evenementen, deze evenementen zal veroorzaken verschillende methoden van de aanleg van „CSGL12Example1Handler“ (dwz „mCSGL12Example1Handler“) worden ingeroepen.
Merk op dat het lid variabele „mTimer“ is verklaard om te verwijzen naar een instantie van een class vernoemd „System.Windows.Forms.Timer“. Dit object wordt gebruikt om zich te beroepen op een functie genaamd „PrivateTimerTickEventHandler“ iedere 10 milliseconden. De functie genaamd „PrivateTimerTickEventHandler“ oproepen van een methode van de aanleg van „CSGL12Control“ (dwz „mCSGL12Control1“) dat de oorzaken die „Control“ om zelf. Dit is hoe een geval van „CSGL12Control“ kan geanimeerde op een benaderende tarief.
Slechts een deel van de definitie van „class CSGL12Example1Form“ verschijnt in het C# bestand met de naam „CSGL12Example1Form.cs“. Een ander deel van de definitie van „class CSGL12Example1Form“ verschijnt in een C# bestand met de naam „CSGL12Example1Form.Designer.cs“. Hoewel de bestanden met namen die overeenkomen met het patroon „*.Designer.cs“ zijn meestal gemaakt en bewerkt alleen door de grafische „Form Designer“ venster van een C# editor, is het ook mogelijk te maken en te wijzigen C# bestanden met behulp van een tekst editor.
De volgende is de complete C# code in het bestand „CSGL12Example1Form.Designer.cs“, die deel uitmaakt van het voorbeeld programma „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;
}
}
Merk op dat dit C# code bevat de verklaring van de variabele „mCSGL12Control1“, die verwijst naar een geval van „class CSGL12.CSGL12Control“ (dwz „class CSGL12Control“ in „namespace CSGL12“). Dit exemplaar is gemaakt en geconfigureerd in de functie „InitializeComponent“.
11. Hantering gebeurtenissen door een instantie van CSGL12Control
Uit het voorgaande blijkt C# code voor een „Form“ dat slechts een exemplaar van „CSGL12Control“. De C# code toevoegen methoden van een „class“ vernoemd „CSGL12Example1Handler“ als gebeurtenis-handlers voor diverse evenementen die door de aanleg van „CSGL12Control“.
Hier is een lijst van interessante gebeurtenissen van „CSGL12Control“, en de „delegate“ soorten in verband met deze evenementen:
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
Alleen de „OpenGLStarted“ evenement is een evenement type specifiek zijn voor de „CSGL12Control“.
Alle andere evenementen zijn standaard System.Windows.Forms evenementen, waarvan de gebeurtenis moeten omgaan met bepaalde parameters (gespecificeerd in ieder Forms documentatie).
De „OpenGLStarted“ en „Paint“ evenementen zijn de belangrijkste evenementen voor OpenGL tekening.
De „OpenGLStarted“ geval een beroep wordt gedaan voordat de eerste „Paint“ evenement wordt ingeroepen.
Daarom is de „OpenGLStarted“ event handler moeten worden toegevoegd om de controle voor de controle heeft de gelegenheid om te proberen te schilderen zelf, anders wordt de eenmalige gebeurtenis zal niet worden ontvangen.
Dit evenement is niet meer dan een gemak, en kan worden genegeerd.
Echter, het toevoegen van een handler voor dit evenement maakt het mogelijk voor de personen die code om nog even een time-initialisatie dat hangt af van OpenGL is klaar voor gebruik.
(OpenGL kan niet worden gebruikt totdat het venster bestaat en het venster is klaar voor het uitvoeren van zijn eerste verf.
Dus, het „OpenGLStarted“ geval bespaart de programmeur van het risico van een poging tot het gebruik OpenGL te snel na het programma start.
) Het is vrij eenvoudig toe te voegen in een logica „Paint“ handler te doen een eenmalige initialisatie, met behulp van de OpenGL kader van de „CSGL12Control“.
De „OpenGLStarted“ evenement wordt aangeboden voor het gemak.
De volgende is de complete C# code in het bestand „CSGL12Example1Handler.cs“, die deel uitmaakt van het voorbeeld programma „CSGL12Example1“.
Deze code wordt hier voorgesteld als een eenvoudig voorbeeld van hoe de gebeurtenissen die door een instantie van „CSGL12Control“ kunnen worden behandeld op te stellen met behulp van 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;
}
}
}
Merk op dat de functie genaamd „OpenGLStarted“ wordt gebruikt in dit voorbeeld te creëren „pixel shader programs“ en een OpenGL textuur. Voor dit programma, hebben we slechts te maken van deze middelen een keer, en het is efficiënter maken ze slechts een keer.
Merk op dat de functie genaamd „OpenGLStarted“ de code controleert of een WGL „extension“ functie genaamd „wglSwapIntervalEXT()“ bestaat, en, indien deze functie wel bestaat, is de code gebruikmaakt van die functie. Deze functie geeft een toestand die invloed heeft op de werking van het programma voor de gehele sessie, en dus moeten we alleen die functie eenmaal, dat is de reden waarom we proberen te bellen die functie in de „OpenGLStarted“ functie (die zelf slechts een keer een beroep gedaan, toen OpenGL is gestart voor een bepaalde „CSGL12Control“, in de veronderstelling dat wij nog de „OpenGLStarted“ methode om de juiste gebeurtenis delegeren).
De functie genaamd „Paint“ bevat alle van de code om een enkel „frame“ animatie met behulp van OpenGL. De „Paint“ functie zal misschien wel 60 keer per seconde, te wijten aan het feit dat de geassocieerde „CSGL12Control“ aanleg wordt „afgedaan“ (gedwongen om zich opnieuw) op dat tarief. (Kijk naar de „Form“ code voorbeeld in de vorige sectie om de timer die bepaalt het tarief van de „ongeldigverklaring“ en de werkelijke functie oproep die er voor zorgt dat de aanleg van „CSGL12Control“ te worden „afgedaan.)“
Alle OpenGL functies worden aangeroepen met behulp van een instantie van de „class GL“ (voorbeeld: gl.gl*()). De aanleg van „class GL“ wordt verkregen uit de aanleg van „CSGL12Control“, die impliciet in de eerste parameter bij de „Paint“ functie.
Alle OpenGL constanten kunnen worden aangegeven door vermelding van de „class“ naam „GL“ gevolgd door een punt en de naam van de constante, dwz „GL.GL_TRIANGLES“.
De OpenGL code in dit voorbeeld is niet geheel duidelijk en gemakkelijk te begrijpen, maar hopelijk kunt u herkennen hoe de code kan worden aangepast voor uw eigen doeleinden.
12. Controleren op de beschikbaarheid van een „verlenging“ functie van OpenGL
Gewoon controleren of de Boole vlag van dezelfde naam als de OpenGL functie is „juist“ voordat u probeert om de overeenkomstige functie.
De Boolese variabele heeft een naam die begint met „b“ gevolgd door de functie OpenGL naam.
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.
// . . .
}
Controle is alleen nodig voor „uitbreiding“ functies.
OpenGL 1.1 functies, en alle GLU functies, en de kern WGL functies, niet van een dergelijke controle. Echter, Boolese vlaggen bestaan en worden op passende wijze, voor alle taken die door „class GL“, met inbegrip van de kern OpenGL 1.1 functies. Zo is er een consistente manier te controleren van de beschikbaarheid van alle functies in deze klasse.
Weten of een functie is een „uitbreiding“ is de verantwoordelijkheid van de programmeur.
Echter, de functie naam achtervoegsels, zoals „EXT“, „ARB“, „MESA“, „NV“ (NVidia), „APPLE“, etc, helpen geven aan de uitbreiding functies.
Als een functie „gl*()“ heeft een naburig functie „gl*ARB()“ of „gl*NV(),“ dan is de functie „gl*()“ is waarschijnlijk een verlenging (voor zover de Windows OPENGL32.DLL is betrokken).
Het enige voordeel van de wetenschap al dan niet een functie is een „uitbreiding“ (met betrekking tot de Windows OPENGL32.DLL) is in staat om te voorkomen dat na te gaan of de functies beschikbaar zijn.
U kunt zoeken naar alle OpenGL functies die gebruikt worden in je code, en dan bouwen een alfabetische lijst van de verschillende functies gebruikt.
Dan, aan het begin van je programma, na de CSGL12Control vraagt de OpenGLStarted delegeren, vinkt u alle Booleaanse vlaggen voor alle functies die u wenst te gebruiken.
Als u ervoor kiest om het programma te beëindigen indien alle „vereiste“ functionaliteit ontbreekt, dan is alle controles op dergelijke functies in de code kan worden geëlimineerd.
Ook kunt u een groep van niet-essentiële functies in het controleren en eventueel de gebruiker van een kenmerk van veranderingen, en misschien laat de controles verspreid in de code.
Met meer OpenGL ervaring, krijg je een gevoel van wat uitbreidingen zijn gerelateerd (voorbeelden: beeldvorming, shaders, buffers, compressie, ...).
Daarom kunt u controleren op de aanwezigheid van een enkele kritische functie en deze informatie gebruiken om te bepalen of de hele subset wordt waarschijnlijk aanwezig zijn.
13. Snelheid
Om verschillende redenen, C# is langzamer dan non-CLR C/C++.
C# uiteindelijk gecompileerd naar native assembleertaal, net als voor C/C++, maar als gevolg van de garanties die door de C# taal en de .NET CLR, de algehele snelheid van software gebaseerd op C# en .NET is iets trager dan software gebouwd met non-CLR C/C++.
Daarom krijgt de hoogst mogelijke snelheid betekent met behulp van non-CLR C/C++ plaats van C#.
Bovendien, omdat belt elke inheemse bibliotheek van C# gaat P/Invoke, het inroepen van functies zoals de OpenGL functies zal enige tijd nodig voor het uitvoeren van werkzaamheden in de P/Invoke laag.
Toch „CSGL12“ lijkt te werken snel genoeg om te worden gebruikt voor vele real-time grafische doeleinden, zoals voor eenvoudige games, 3D-kijkers, redactie, of 3D-presentaties. Dit is vooral het geval wanneer het meeste werk wordt gedaan door de GPU in plaats van de CPU.
14. Vergelijking tussen „CSGL12“ en de „Tao Framework“
De „Tao Framework“ is een grote C# / .NET bibliotheek die een interface voor een groot aantal open source-bibliotheken, zoals OpenGL, OpenAL (audio), SDL (a gaming / simulation platform), Open Dynamics Engine (ODE) (natuurkunde), enz.
De Tao Framework is cross-platform (Windows, Linux, Mac OS X).
„CSGL12“ alleen een interface naar OpenGL en is alleen voor de Windows besturingssysteem.
De Tao Framework heeft een gemeenschap. Een persoon kan profiteren van de communicatie met collega-gebruikers van de Tao Framework.
Toch kunnen er vele doeleinden waarvoor „CSGL12“ misschien gemakkelijker te gebruiken voor Windows's.