C# OpenGL interface
for Windows operativsystem
Colin Fahey

CSGL12Control på en Form, viser en "fraktale" Pixel Shader program og GDI+ tegning kopieres til en tekstur

To CSGL12Control forekomster på en Form, der viser, Pixel Shader programmer og teksturer

En 3D avatar, at roams skrivebordet og kan flyttes med cursoren
1. Software
CSGL12_20090725.zip
CSGL12: C# OpenGL interface til Windows, version 12
4170499 bytes
MD5: 30781a6570441785ea636f2ae1cd16ef
2. Alle de C# computer-kode i C# OpenGL Interface (CSGL12) er i det "offentlige rum"
Jeg skrev alle de C# computer-kode inden for C# OpenGL Interface (CSGL12).
Jeg erklærer alle de C# computer-kode inden for C# OpenGL Interface (CSGL12) for at være i det "offentlige rum."
Derfor computeren koden kan anvendes til ethvert formål (kommercielle eller private), uden betaling, uden begrænsninger, uden pligter, og uden at anerkende den oprindelige ophavsmand.
Koden kan ændres eller dele genbruges, uden begrænsninger, og uden forpligtelser, og uden at anerkende den oprindelige ophavsmand.
Eksemplet programmer omfatter en lille mængde af computer-kode (specifikt "shader computer code) er skrevet af andre mennesker." En sådan kode er ikke inden for den grænseflade selv og kan trivially fjernet. En sådan kode er blot at demonstrere enkelhed med interfacekablet til at oprette og anvende "shader" programmer.
3. Indledning
"CSGL12" er en samling af C# computer kode filer, der implementerer en grænseflade til OpenGL grafik bibliotek (inklusive alle udvidelser af OpenGL frem til år 2007) for Windows operativsystemet.
Den C# computer koder filer i "CSGL12" indsamling gør det nemt at tilføje OpenGL tegning til enhver C# / .NET software med en "Form" (et tilfælde af "System.Windows.Forms.Form").
Den "CSGL12" indsamling af computer-kode filer indeholder en fil med navnet "CSGL12Control.cs", der definerer en klasse ved navn "CSGL12Control", stammer fra "System.Windows.Forms.Control". Hver forekomst af "CSGL12Control" repræsenterer en uafhængig OpenGL tegning område. Det er meget nemt at tilføje flere forekomster af CSGL12Control til en Form (et tilfælde af System.Windows.Forms.Form).
4. Karakteristik og krav i "CSGL12"
Koden er kun for Windows operativsystemer, som understøtter .NET 2.0 Framework (Windows 2000, Windows XP, Windows Vista, Windows 7)
Koden kan udarbejdes ved hjælp "Microsoft Visual C# 2008 Express Edition" (en gratis compiler), eller lignende C# compilers.
Koden kræver at blive bygget med "[X] Allow unsafe code" opbygge valgt så optimeret billeddata kopiering funktioner kan bruges. Hvis du er en ekspert C# programmør vil du være i stand til nemt at identificere de dele af C# kode, der kræver "unsafe" mulighed, og slå dem, hvis ønsket eller påkrævet. Image data kopiering er 10 gange hurtigere med "unsafe" kode end alternativet, og dette er grunden til disse koder anvendes. Hvis du bygge en DLL, der indeholder alle de "unsafe"-kode, så et projekt, der bruger den pågældende DLL kræver ikke bliver bygget med "unsafe" mulighed, og så du kan udlede, at fraværet af den "unsafe" mulighed i et projekt, er ikke ensbetydende med nogen ekstra sikkerhed (fordi talrige DLL filer, der anvendes implicit eller eksplicit af programmet indeholder "usikre" code).
Koden kan udarbejdes og benyttes af en eller flere af følgende:
Microsoft Visual C# 2008 Express Edition
Microsoft Visual Studio 2008
Microsoft .NET 3.5 SDK
SharpDevelop
Mono Project
Koden giver mest OpenGL extensions (gennem året 2007), herunder "vertex shaders" og "pixel shaders".
Koden giver 1570 funktioner i forbindelse med OpenGL:
336 GL functions
51 GLU functions
19 WGL functions
1164 extensions
Koden tilbyder nogle alternative varianter af 1570 funktioner med forskellige parameter typer, for nemheds skyld.
Koden definerer mere end 3244 konstanterne for OpenGL.
Koden gør det muligt at have flere OpenGL tegning sammenhænge, alle agere uafhængigt, om alle "Form".
Hvis du klikker på en "CSGL12Control" giver det "input fokus," der gør det muligt efterfølgende tastatur og mus hjulet input. Markør klik og bevægelser har modtaget, når markøren er i det rektangulære område med et tilfælde af "CSGL12Control".
Koden omfatter funktioner til at demonstrere, hvordan du kan gøre nogle fælles OpenGL opgaver i C# og .NET.
De kodelister alle OpenGL konstanter og funktioner i alfabetisk rækkefølge i "class GL" i "GL.cs", hvilket gør det let at afgøre, om nogen konstant eller en funktion der mangler (hvilket ikke er sandsynligt, undtagen for udvidelser vedtaget efter år 2007).
Eksemplet programmer viser, hvordan du gør GDI+ tegning til en Bitmap og derefter, hvordan du kopierer Bitmap til en OpenGL tekstur.
Dette gør det muligt tekst og andre GDI+ tegning kapacitet til at bidrage til en OpenGL scene.
De GDI+ Bitmap kan opdateres og overført til en OpenGL texture så ofte som en gang pr OpenGL rammen.
Eksemplet programmer viser, hvordan man kan vælge mellem flere forskellige "pixel shader programs" mens programmet kører.
Eksemplet programmer viser, hvordan man skriver OpenGL buffere til billedfiler (JPG, BMP, GIF, PNG).
Tryk Shift + 0 (Shift-nul) for at skrive den OpenGL buffer til billedfiler.
Eksemplet kode viser, hvordan udarbejdelsen "GL.cs" i en DLL fil og derefter tilføjer, at DLL filen til et andet projekt, kan forhindre Microsoft kode redaktører (f.eks Microsoft Visual C# 2008 Express Edition osv.) med "IntelliSense" (kontekst-følsomme kode afslutningen) bliver hyppigt og vedvarende unresponsive (gentagne gange pauser i mange sekunder, hvilket gør redaktøren helt ubrugelig). Under filen "GL.cs" direkte indgår i et projekt, der redigeres af en Microsoft code editor ikke er praktisk muligt, medmindre en person er villig til at udholde de langsommelige editoren. Dette problem har ramt Microsoft Visual Studio 2003, 2005, 2008, og vil sandsynligvis påvirke 2010 version også.
Eksemplet kode viser brugen af flere forekomster af "CSGL12Control" på en "Form".
Eksemplet kode omfatter kode for at foretage et 3D "avatar" at roams skrivebordet af Windows.
5. Eksempel programmer, der følger med "CSGL12"
5.1 "CSGL12DLL"
Projektet opkaldt "CSGL12DLL" producerer en DLL fil med navnet "CSGL12DLL.dll" som indeholder "class GL" (defineret i C# fil "GL.cs").
Sætte "class GL" på en DLL fil og derefter ved hjælp at DLL i andre projekter, der bruger "class GL", hjælper undgå en ekstrem problem med alle Microsoft kode redaktører med IntelliSense funktion. Brug af C# fil GL.cs direkte i et projekt ville forårsage nogen Microsoft code editor med IntelliSense funktion til at blive helt afvisende og ubrugelige næsten kontinuerligt på grund af ineffektivitet i IntelliSense funktion (og det faktum, at IntelliSense åbenbart blokke de vigtigste program tråd af editor ).
Hvis du bruger en C# kode editor, som ikke er produceret af Microsoft (f.eks "SharpDevelop", "MonoDevelop" osv.), så kan du blot medtage filen "GL.cs" direkte i dine projekter, og du vil være usandsynligt at få nogen fordel i at anvende "CSGL12DLL.dll".
5.2 "CSGL12Control"
Projektet opkaldt "CSGL12Control" producerer en DLL fil med navnet "CSGL12Control.dll" som indeholder "class CSGL12Control" (defineret i C# fil "CSGL12Control.cs").
Sætte "class CSGL12Control" på en DLL fil, gør det muligt at "Control" (dvs. en klasse afledt "System.Windows.Forms.Control"), der skal føjes til "Toolbox" af Microsoft Visual C# 2008 Express Edition (og lignende C# redaktører). Under "CSGL12Control" i "Toolbox" gør det nemt for en person for at tilføje et tilfælde af "CSGL12Control" til en "Form" i "Designer" (f.eks, en person kan blot bruge markøren for at vælge og trække et tilfælde af "CSGL12Control" fra "Toolbox" til en "Form").
Den "CSGL12Control" objekt forvalter en OpenGL tegning sammenhæng. Flere forekomster af "CSGL12Control" kan eksistere side om side på en "Form".
5.3 "CSGL12Example1"
Projektet opkaldt "CSGL12Example1" producerer en eksekverbar programfil (EXE) opkaldt "CSGL12Example1.exe". Programmet bruger "CSGL12DLL.dll" og "CSGL12Control.dll" at vise et eksempel på CSGL12Control og udsteder en terning ved hjælp OpenGL.
Programmet viser, at brug af fire forskellige "pixel shaders" "(fraktale, mursten, træ," og "tegneserie)."
Programmet viser også brugen af "GDI+" en .NET tegning biblioteket, til at trække tekst og andre udformninger til en "Bitmap" objekt (en "GDI+" objekt), og derefter kopiere billedet fra det pågældende "Bitmap" en "texture" i OpenGL, således at billedet drages ved "GDI+" at dukke op i OpenGL tegning. Denne evne er meget nyttig, fordi OpenGL mangler mange af de 2D tegning funktioner, der findes i "GDI+" og lignende 2D tegning libaries.
5.4 "CSGL12Example2"
Projektet opkaldt "CSGL12Example2" producerer en eksekverbar programfil (EXE) opkaldt "CSGL12Example2.exe". Programmet bruger "CSGL12DLL.dll" og "CSGL12Control.dll" at vise to eksempler på CSGL12Control, som hver især trækker en terning ved hjælp OpenGL.
Programmet har en "SplitContainer" "Control" om "Form". Hver af de to områder af "SplitContainer" indeholder et tilfælde af CSGL12Control. Således kan en person kan justere placeringen af delt mellem de to forekomster af CSGL12Control. Dette viser fleksibiliteten i CSGL12Control.
Et af de eksempler på CSGL12Control sender arrangementer til en række tilfælde håndterer i et tilfælde af "CSGL12Example2Handler1.cs", som bruger den samme kode som "CSGL12Example1Handler.cs" i "CSGL12Example1" eksempel projektet. Derfor er et af de tilfælde, CSGL12Control trækker en terning med en udvalgt "pixel shader" blandt fire tilgængelige "pixel shaders".
Det andet eksempel på CSGL12Control sender arrangementer til en række tilfælde håndterer i et tilfælde af "CSGL12Example2Handler2.cs", som trækker en terning ved hjælp af en tekstur billede (eller en "checkerboard" mønster hvis en billedfil opkaldt "image.jpg" er ikke fundet).
5.5 "CSGL12Avatar"
Projektet opkaldt "CSGL12Avatar" producerer en eksekverbar programfil (EXE) opkaldt "CSGL12Avatar.exe". Programmet bruger "CSGL12DLL.dll" og "CSGL12Control.dll" at drage en terning ved hjælp OpenGL om at "Form" uden en grænse, med farver baseret gennemsigtighed aktiveret, for at trække en 3D "avatar" at roams de Windows desktop område.
De bevægelige avatar, kan klikkede og slæbt til en ny placering ved hjælp af markøren. Dobbeltklikke på avatar vil gøre det forsvinde. Selv om koden blot trækker en terning, OpenGL kan bruges til at trække andre ting.
Flere forekomster af "avatar" program kan startes. Således er mange uafhængige "avatar" tilfælde kan samtidig strejfe den Windows skrivebordet. Det er morsomt. En ekspert C# programmør kan nyde at finde metoder til at koordinere aktiviteten af mange sådanne "avatar" tilfælde.
Desværre er det tempo, som Window formål med gennemsigtighed er opdateret på skærmen er meget langsommere end den hastighed, hvormed OpenGL kan trække. Den "avatar" opdaterer kun 10 gange i sekundet. Jeg ved ikke, om dette kan forbedres.
5.6 "CSGL12BuiltExecutableExamplesForReference"
Den mappe med navnet "CSGL12BuiltExecutableExamplesForReference" indeholder DLL filer og EXE filer produceret af alle de eksempel projekter. Disse filer er angivet som reference, så de filer kan testes straks, selv om en person ikke har mulighed for at samle de forskellige projekter fra de fastsatte C# kode.
5.7 "CSGL12UsefulCode"
Den mappe med navnet "CSGL12UsefulCode" indeholder C# filer, som kan være nyttige for folk, der ønsker at gøre hverdagskost tegning operationer med OpenGL. Mappen indeholder også DLL filer "CSGL12DLL.dll" og "CSGL12Control.dll" for nemheds skyld.
Koden i denne mappe definerer forskellige class typer, såsom Color4f, Vector3f, Matrix4x4f, Triangle, Mesh, ImageData, Texture, ShaderProgram osv. Koden er forholdsvis effektive, men koden er kun beregnet til at inspirere folk til at udvikle deres egne implementeringer.
6. CSGL12 filer
Den "CSGL12" indsamling af C# computer kode filer omfatter filerne vist i nedenstående diagram:

Den "CSGL12" indsamling af C# computer kode filer omfatter filerne vist i dette diagram.
Den "CSGL12" software omfatter også projekter til at skabe de to DLL filer ("CSGL12DLL.dll" og "CSGL12Control.dll") vist i diagrammet. Disse to DLL filer kan oprettes for at gøre det mere bekvemt at skabe programmer, der bruger OpenGL, men det er også muligt at skabe programmer, der kun bruger den C# filer direkte.
7. "namespace CSGL12" og "class" typer
Den "CSGL12" indsamling af C# computer kode filer definerer "namespace CSGL12" og "class" typer vist i nedenstående diagram:

Den "CSGL12" indsamling af C# computer kode filer definerer "namespace CSGL12" og "class" typer vist i dette diagram.
Et program, der gør OpenGL tegningen kan oprettes ved hjælp af kun "class GL" (ved hjælp af den C# fil GL.cs direkte, eller ved at bruge DLL fil CSGL12DLL.dll der også indeholder "class GL"). Men ved hjælp "class CSGL12Control" (ved hjælp af C# fil CSGL12Control.cs direkte, eller ved at bruge DLL fil CSGL12Control.dll som også indeholder "class CSGL12Control") gør tilføje OpenGL tegning til en Form (System.Windows.Forms.Form) nemt og bekvemt.
Den C# klasser Color4f, CSGL12Support, ImageData, ..., i bunden af diagrammet udbydes kun for nemheds skyld. Disse klasser gøre det lettere at skabe programmer, der trækker ved hjælp OpenGL. Men du har måske allerede klasser at udføre operationer i disse klasser, eller du kan vælge at oprette lignende klasser at udføre operationer anderledes eller mere effektivt. Disse klasser tilbydes som eksempler på en særlig kode, design og implementering.
8. Brug af en enkelt "CSGL12Control" på et System.Windows.Forms.Form
8.1 Program struktur
Følgende diagram viser, hvordan et program med en System.Windows.Forms.Form kan bruge en enkelt "CSGL12Control" at gøre tegne med OpenGL. Diagrammet viser de forskellige CSGL12 filer bruges til at bygge det program.

Et program med et enkelt "CSGL12Control" på en System.Windows.Forms.Form
8.2 Brug Microsoft Visual C# til at oprette programmet
(1) Start Microsoft Visual C#.
(2) I menuen, vælg "File" -> "New Project...".
(3) I "New Project" dialogboks, der vises, skal du vælge "Windows Forms Application", og vælge et navn til programmet, og tryk "OK".
(4) Umiddelbart gemme "Solution" ved at vælge "File" -> "Save All". En dialogboks med titlen "Save Project" vises, så du kan indstille projektet navn, mappeplacering, og "løsningen" navn til projektet. Husk det mappeplacering, så du er klar til den næste instruktion. Tryk på "Save"-knappen for at gemme projektet.
(5) Kopier alle filerne fra den mappe "CSGL12UsefulCode" i "CSGL12" software til den mappe, der indeholder kildekodefiler af det nye projekt (dvs. den mappe, der indeholder de filer "Form1.cs", "Form1.Designer.cs", "Program.cs" osv.), sådan at de filer "CSGL12DLL.dll", "CSGL12Control.dll", "Color4f.cs" , "CSGL12Support.cs" osv., er ved siden af det nye projekt filer "Form1.cs" osv.
(6) I Microsoft Visual C#, tilføj "CSGL12" C# filer til projektet. I menuen, vælg "Project" -> "Add Existing Item...", og i "Add Existing Item" dialogboksen vælge alle de C# filer fra CSGL12 software ("Color4f.cs", "CSGL12Support.cs", "ImageData.cs", ...).
(7) I Microsoft Visual C#, tilføje "henvisninger" til DLL filer "CSGL12DLL.dll" og "CSGL12Control.dll". I menuen, vælg "Project" -> "Add Reference...", og i "Add Reference" dialogboksen, skal du vælge "Browse" fane, og vælg de filer "CSGL12DLL.dll" og "CSGL12Control.dll" fra projektet kildefilen mappe, og tryk "OK".
(8) I Microsoft Visual C#, tilføj "CSGL12Control" til "Toolbox". I menuen, vælg "Tools" -> "Choose Toolbox Items...". I "Choose Toolbox Items" dialogboks, der vises, skal du trykke på "Browse..." knappen, og gå til det projekt mappe med kildekodefiler, og vælg "CSGL12Control.dll". Tryk på "OK" knappen.
(9) I Microsoft Visual C#, se "Toolbox". I menuen, vælg "View" -> "Toolbox". I "Toolbox", skal du gå til afsnittet opkaldt "General", og find det element, opkaldt "CSGL12Control". Brug markøren, skal du klikke på elementet opkaldt "CSGL12Control" og træk det til "Form" i "Design" synspunkt.
(10) I Microsoft Visual C#, i "Form" "Design" mening flytte "CSGL12Control" eksempel på "Form" og justere sin bredde og højde. I "Properties" panel, indstille "Anchor" værdi til at omfatte "Top, Bottom, Left, Right" hvis du vil have kontrol for at ændre størrelse i henhold til ændringer i programmet vinduesstørrelse.
(11) I Microsoft Visual C#, ændre projektet egenskaber, så det kan bruge "unsafe" kode. I menuen, vælg "Project" -> "[project] Properties...". Vælg den dialogboks, der vises, skal du vælge fanen opkaldt "Build", og tjek afkrydsningsfeltet opkaldt "[X] Allow unsafe code". Luk projektet i dialogboksen Egenskaber.
(12) I Microsoft Visual C#, tilføje en ny C# fil til projektet. I menuen, vælg "Project" -> "Add New Item...". I dialogboksen navnet "Add New Item", vælg den skabelon opkaldt "Class", og vælge et navn til den nye klasse type, såsom "CSGL12MyHandler.cs", og tryk derefter på "Add" knappen. Kig på eksemplet projekt opkaldt "CSGL12Example1" på fil med navnet "CSGL12Example1Handler.cs", som et eksempel på, hvordan koden for "CSGL12MyHandler.cs" skal skrives.
(13) I Microsoft Visual C#, i "Solution Explorer", skal du klikke på "Form1". I menuen, vælg "View" -> "Code" (eller tryk F7, eller højre-klik på "Form1" og vælge "View Code". Koden i filen "Form1.cs" vises i editor. Ændre koden i filen "Form1.cs" som magen til den kode i filen "CSGL12Example1Form.cs" i projektet "CSGL12Example1" indgår i "CSGL12" software. Især skabe en variabel for en instans af din hændelseshandler klasse (f.eks "CSGL12MyHandler"), og tilføj derefter metoder for denne klasse instans som begivenhed håndterer for de forskellige arrangementer i tilfælde af "CSGL12Control" om "Form".
(14) I Microsoft Visual C#, udarbejde og gennemføre programmet. Hvis du ønsker at dele det program, du skal omfatte de to DLL filer ("CSGL12DLL.dll" og "CSGL12Control.dll") med eksekverbar fil (*.exe).
Hvis du er en ekspert C# programmør, så du kan undgå at skulle distribuere DLL filer ("CSGL12DLL.dll" og "CSGL12Control.dll") med din eksekverbare (*.exe).
Kopier filer "GL.cs", "CSGL12Control.cs", og "PrecisionTime.cs" fra projekter opkaldt "CSGL12DLL" og "CSGL12Control" i "CSGL12" software til kilden mappe på din aktuelle projekt. Tilføj filer "GL.cs", "CSGL12Control.cs", og "PrecisionTime.cs" til dit projekt, så de er udarbejdet direkte ind i programmet. Har du ikke henvisninger til "CSGL12DLL.dll" og "CSGL12Control.dll" i projektet.
Kig på "CSGL12Example1" projekt i "CSGL12" software, og se på den kode, inden filerne navngives "CSGL12Example1Form.cs" og "CSGL12Example1Form.Designer.cs" at se, hvad koden er påkrævet for at oprette og initialisere et tilfælde af "CSGL12Control" på en "Form". Tilføj samme kode til "Form1.cs" og "Form1.Designer.cs" for manuelt at oprette og initialisere et tilfælde af "CSGL12Control" på din "Form".
Denne procedure er meget upraktisk, og det kræver ekspertise og omhyggelig, men den resulterende eksekverbare (*.exe) vil ikke kræve "CSGL12DLL.dll" eller "CSGL12Control.dll". Det er meget rart at være i stand til at dele din software i form af en enkelt eksekverbar fil (*.exe) uden at det kræver andre filer.
8.3 Tilføjelse "henvisninger" til CSGL12DLL.dll og CSGL12Control.dll
Dette afsnit omfatter billeder for at bruge Microsoft Visual C# 2008 Express Edition at tilføje "henvisninger" til DLL filer CSGL12DLL.dll og CSGL12Control.dll til projektet.
I menuen, vælg "Project" -> "Add Reference...". Eller højreklik på "References" post i "Solution Explorer" panel og vælg "Add Reference...", som vist i nedenstående billede.

Kontekstmenu for "References" punkt i "Solution Explorer", der viser "Add Reference..." mulighed
Når du har valgt "Add Reference..." mulighed, en dialogboks opkaldt "Add Reference" vises. I denne dialogboks, skal du vælge "Browse" fane, og vælg den DLL filer "CSGL12DLL.dll" og "CSGL12Control.dll", som vist i nedenstående billede, og derefter trykke på knappen "OK".

Den "Browse" fanen af "Add Reference" dialogboksen med DLL filer "CSGL12DLL.dll" og "CSGL12Control.dll" både valgte
Når du har trykket på knappen "OK", den "Add Reference" dialogboksen vil forsvinde, og DLL filer "CSGL12DLL.dll" og "CSGL12Control.dll" vises i "References" filial i "Solution Explorer", som vist i nedenstående diagram.

Den DLL filer "CSGL12DLL.dll" og "CSGL12Control.dll" i "References" filial i "Solution Explorer"
8.4 Tilføjelse CSGL12Control til Toolbox i Microsoft Visual C# 2008 Express Edition
Dette afsnit omfatter billeder for at bruge Microsoft Visual C# 2008 Express Edition at tilføje CSGL12Control til "Toolbox" således at en person kan nemt tilføje forekomster af CSGL12Control til en "Form" i "Designer" (Shift+F7 som standard).
I menuen, vælg "View" -> "Toolbox". I "Toolbox", skal du gå til afsnittet opkaldt "General", som vist i nedenstående billede.

Den "General" del af "Toolbox"
Højreklik et vilkårligt sted i "Toolbox". Vælg den indstilling "Choose Items..." i forbindelse menu, der vises, som vist i nedenstående billede.

Muligheden "Choose Items..." i den sammenhængsafhængige menu for "Toolbox"
Alternativt kan i menuen, skal du vælge Vælg "Tools" -> "Choose Toolbox Items...".
Den "Choose Toolbox Items" dialogboksen skal vises, som vist i nedenstående billede.

Den "Choose Toolbox Items" dialogboksen
I "Choose Toolbox Items" dialogboksen, skal du trykke på "Browse" knappen. I "Open" dialogboks, der vises, skal du vælge DLL filen "CSGL12Control.dll", som vist i nedenstående billede, og tryk derefter på "OK" knappen.

Den "Open" dialogboksen med DLL fil "CSGL12Control.dll" udvalgte
Den "CSGL12Control" post skal nu vises i "Choose Toolbox Items" dialogboksen, som vist i nedenstående billede. Tryk på "OK" knappen.

Den "CSGL12Control" punkt på dagsordenen nu vises i "Choose Toolbox Items" dialogboksen
Den "CSGL12Control" post skal nu vises i "Toolbox", som vist i nedenstående billede.

Den "CSGL12Control" punkt på dagsordenen nu vises i "Toolbox"
8.5 Tilføjelse CSGL12Control til en "Form" ved hjælp af "Toolbox"
Dette afsnit omfatter billeder for at bruge Microsoft Visual C# 2008 Express Edition at tilføje et tilfælde af CSGL12Control til en "Form" ved hjælp af "Toolbox".
I menuen, vælg "View" -> "Designer" (Shift+F7 som standard). Eller ved at dobbeltklikke på en "Form*.cs" fil i "Solution Explorer". Eller højreklikker på et "Form*.cs" fil i "Solution Explorer" og vælg "View Designer". Brug en af disse tre metoder, "Designer" vindue til en "Form" skal vises.
I menuen, vælg "View" -> "Toolbox". I "Toolbox", skal du gå til afsnittet opkaldt "General". Et punkt opkaldt "CSGL12Control" bør vises der, som vist i nedenstående billede.

Den "CSGL12Control" burde allerede være i den "Toolbox"
Brug markøren, skal du klikke på elementet opkaldt "CSGL12Control" og træk det til "Form" i "Designer". Et tilfælde af "CSGL12Control" skal stå på "Form" som vist i nedenstående billede.

Et tilfælde af "CSGL12Control" på en "Form" i "Designer"
I "Form" "Designer" mening flytte forekomst af "CSGL12Control" på "Form" og justere sin bredde og højde.
Klik på den konstaterede "CSGL12Control" om "Form" for at vælge det. Så, i "Properties" panelet, indstille "Anchor" værdi til at omfatte "Top, Bottom, Left, Right" således at størrelsen af den "CSGL12Control" vil ændre sig i takt med ændringer i programmet vinduesstørrelse. Måske vil du også ændre variablen navn (dvs. værdien for "(Name)") for forekomst af "CSGL12Control" fra den automatiske standard (f.eks "csgL12Control") til noget passende for din kode (f.eks "mCSGL12Control" eller "mCSGL12Control1", etc).
Følgende billede viser "Form" "Designer" holdning og "Properties" panel.

Et tilfælde af CSGL12Control på en Form i Designer, og "Properties panel
9. Brug to forekomster af "CSGL12Control" på et System.Windows.Forms.Form
Følgende diagram viser et eksempel på, hvordan to forekomster af "CSGL12Control" kan føjes til en System.Windows.Forms.Form til at gøre tegning med OpenGL i et program.

Et program med to forekomster af "CSGL12Control" på en System.Windows.Forms.Form
Følg vejledningen i forrige afsnit for at tilføje et enkelt eksempel på "CSGL12Control" til en "Form". Derefter skal du blot trække en anden instans af "CSGL12Control" fra "Toolbox" til "Form" at tilføje en anden "CSGL12Control".
Hver forekomst af "CSGL12Control" vil have sin egen variable navn. Hver forekomst af "CSGL12Control" kan have sin egen forbundet hændelseshandler klassen, eller det kan bruge særskilte tilfælde af en enkelt handling-klasse type.
Undersøgelse eksemplet projekt "CSGL12Example2" for at lære, hvordan to tilfælde "CSGL12Control" kan have deres begivenheder, der sendes til to særskilte tilfælde af brugerdefinerede hændelseshandler klasser med forskellige OpenGL tegning funktioner.
Eksemplet program "CSGL12Example2" har hver forekomst af "CSGL12Control" i en "SplitContainer" "Control", blot for at vise en vej, hvor forekomst af "CSGL12Control" kan bruges. Men forekomster af "CSGL12Control" kan i stedet blive lagt direkte adgang til "Form".
10. Eksempel C# kode for et "Form" med et tilfælde af CSGL12Control
Nedenstående er den komplette C# kode indeholdt i filen "CSGL12Example1Form.cs", som er en del af eksemplet program "CSGL12Example1".
Denne kode er vist her som et simpelt eksempel på, hvordan et tilfælde af CSGL12Control kan skabes og anvendes af en "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);
}
}
}
Bemærk, at det medlem variable "mCSGL12Example1Handler" er erklæret at henvise til en instans af en class navngivet "CSGL12Example1Handler". Denne klasse vil blive beskrevet i et senere afsnit af dette dokument. Bemærk, at entreprenøren for "CSGL12Example1Form" tilføjer metoderne til den konstaterede "CSGL12Example1Handler" til "multicast delegates" forbundet med de forskellige arrangementer er genereret af et tilfælde af "CSGL12Control". Det betyder, at når den konstaterede "CSGL12Control" genererer forskellige begivenheder, disse begivenheder vil forårsage forskellige metoder til den konstaterede "CSGL12Example1Handler" (dvs. "mCSGL12Example1Handler") kan påberåbes.
Bemærk, at det medlem variable "mTimer" er erklæret at henvise til en instans af en class navngivet "System.Windows.Forms.Timer". Dette objekt bruges til at aktivere en funktion ved navn "PrivateTimerTickEventHandler" hver 10 millisekunder. Funktionen opkaldt "PrivateTimerTickEventHandler" kalder en metode i tilfælde af "CSGL12Control" (dvs. "mCSGL12Control1"), som forårsager, at "Control" at trække sig. Det er sådan et tilfælde af "CSGL12Control" kan animeret på en omtrentlig sats.
Kun en del af definitionen af "class CSGL12Example1Form" vises i C# fil med navnet "CSGL12Example1Form.cs". En anden del af definitionen af "class CSGL12Example1Form" vises i en C# fil med navnet "CSGL12Example1Form.Designer.cs". Selv om filer med navne, der matcher det mønster "*.Designer.cs" generelt er oprettet og ændres kun ved den grafiske "Form Designer" vindue af en C# editor, er det også muligt at oprette og redigere sådanne C# filer ved hjælp af en teksteditor.
Nedenstående er den komplette C# kode indeholdt i filen "CSGL12Example1Form.Designer.cs", som er en del af eksemplet 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;
}
}
Bemærk, at denne C# kode indeholder angivelsen af variablen "mCSGL12Control1", som henviser til et tilfælde af "class CSGL12.CSGL12Control" (dvs. "class CSGL12Control" i "namespace CSGL12"). Denne instans er oprettet og konfigureret i funktion "InitializeComponent".
11. Håndtering begivenheder påberåbes af et tilfælde af CSGL12Control
Det foregående afsnit viste C# kode for et "Form", der indeholdt en enkelt forekomst af "CSGL12Control". Den C# kode tilføje metoder til en "class" opkaldt "CSGL12Example1Handler" som begivenhed håndterer for forskellige begivenheder, som den konstaterede "CSGL12Control".
Her er en liste over interessante begivenheder i "CSGL12Control", og "delegate" typer er forbundet med disse arrangementer:
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
Kun den "OpenGLStarted" begivenhed er en begivenhed typespecifikke til "CSGL12Control".
Alle andre arrangementer er standard System.Windows.Forms begivenheder, hvis begivenheden håndterer skal have visse parametre (specificeret i enhver Forms dokumentation).
Den "OpenGLStarted" og "Paint" begivenheder er de vigtigste begivenheder for OpenGL tegning.
De "OpenGLStarted" begivenhed er påberåbes ved det allerførste "Paint" begivenhed er gældende.
Derfor er "OpenGLStarted" hændelseshandler skal tilføjes til kontrol før kontrollen er blevet en lejlighed til at forsøge at male sig selv, ellers er engangs-begivenhed ikke vil blive modtaget.
Denne begivenhed er blot en bekvemmelighed, og kan ignoreres.
Men at tilføje en handling for denne begivenhed gør det muligt for den, der håndterer kode til at gøre nogle engangs-initialisering, afhænger OpenGL at være klar til brug.
(OpenGL ikke kan anvendes, indtil vinduet findes, og vinduet er klar til at udføre sit første maling.
Så det "OpenGLStarted" omstændigheder undgår programmør fra risikoen for at forsøge at bruge OpenGL for tidligt efter programmet starter.
) Det er ret nemt at tilføje logik i en "Paint" handler om at gøre et engangsreferencenummer initialisering, bruger OpenGL led i "CSGL12Control".
De "OpenGLStarted" tilfælde tilbydes som en bekvemmelighed.
Nedenstående er den komplette C# kode indeholdt i filen "CSGL12Example1Handler.cs", som er en del af eksemplet program "CSGL12Example1".
Denne kode er vist her som et simpelt eksempel på, hvordan de begivenheder, der genereres af et tilfælde af "CSGL12Control" kan håndteres at henlede bruger 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;
}
}
}
Bemærk, at funktionen opkaldt "OpenGLStarted" er brugt i dette eksempel at skabe "pixel shader programs" og en OpenGL tekstur. Til dette program, vi behøver kun at oprette disse ressourcer gang, og det er mere effektivt til at skabe dem kun én gang.
Bemærk, at funktionen opkaldt "OpenGLStarted" koden tjekker, om en WGL "extension" funktion opkaldt "wglSwapIntervalEXT()" eksisterer, og, hvis denne funktion findes, koden påberåber denne funktion. Denne funktion beskriver en tilstand, som påvirker driften af programmet for hele sessionen, og vi behøver kun at kalde denne funktion gang, hvilket er grunden til, at vi forsøger at kalde denne funktion i "OpenGLStarted" funktion (som i sig selv kun paaberaabes én gang, når OpenGL er startet for en bestemt "CSGL12Control" antager vi tilføjet "OpenGLStarted" metode til de relevante omstændigheder uddelegere).
Funktionen opkaldt "Paint" indeholder al den kode til at trække en enkelt "ramme" animation ved hjælp OpenGL. Den "Paint" funktion vil blive kaldt måske 60 gange i sekundet, skyldes, at de associerede "CSGL12Control" eksempel bliver "ugyldig" (tvunget til at trække sig selv igen) med denne sats. (Se på "Form" kode eksempel i forrige afsnit for at se de timer, der bestemmer hvor hurtigt "ugyldiggørelsen" og den faktiske funktion opkald, der forårsager den konstaterede "CSGL12Control" at blive "ugyldiggjorte.)"
Alle OpenGL funktioner er påberåbes ved hjælp af en forekomst af "class GL" (eksempel: gl.gl*()). Den konstaterede "class GL" er erhvervet fra den konstaterede "CSGL12Control", som er implicit gemt i den første parameter til "Paint" funktion.
Alle OpenGL konstanterne kan specificeres med angivelse af "class" navn "GL" efterfulgt af et punktum og navnet på den konstant, dvs "GL.GL_TRIANGLES".
Den OpenGL koden i dette eksempel er ikke helt indlysende og let at forstå, men forhåbentlig kan du genkende, hvordan koden kan ændres til dine egne formål.
12. Kontrol for tilgængeligheden af en "udvidelse" funktion af OpenGL
Blot kontrollere, om Boolean flag af samme navn som den OpenGL funktion er "korrekt," før du forsøger at bruge den tilsvarende funktion.
De booleske variabel har et navn, der begynder med "b" efterfulgt af OpenGL funktion navn.
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.
// . . .
}
Kontrol er kun behov for "udvidelse" funktioner.
OpenGL 1.1 funktioner, og alle GLU funktioner, og kernen WGL funktioner, som ikke kræver en sådan kontrol. Men Boolean flag findes, og er indstillet korrekt, for alle sådanne funktioner, som "class GL", herunder de centrale OpenGL 1.1 funktioner. Der er således en sammenhængende måde at kontrollere tilgængeligheden af alle funktioner i denne klasse.
Vide, om en funktion er en "udvidelse" er ansvarlig for programmør.
Men funktionen navn suffikser, såsom "EXT", "ARB", "MESA", "NV" (NVidia), "APPLE" osv., hjælpe med til at vise forlængelse funktioner.
Hvis en funktion "gl*()" har en nabostaten funktion "gl*ARB()" eller "gl*NV()," så den funktion "gl*()" er formentlig en forlængelse (for så vidt angår Windows OPENGL32.DLL er bekymret).
Den eneste fordel ved at vide, hvorvidt en funktion er en "udvidelse" (med hensyn til Windows OPENGL32.DLL) bliver i stand til at undgå kontrol, hvis funktioner er tilgængelige.
Du kan søge efter alle OpenGL funktioner anvendes i din kode, og derefter bygge en alfabetisk liste over de forskellige funktioner anvendes.
Så, i starten af dit program, efter CSGL12Control kalder OpenGLStarted uddelegere, blot kontrollere alle Boolean flag for alle de funktioner, du har til hensigt at bruge.
Hvis du vælger at afslutte programmet, hvis eventuelle "nødvendige" funktioner mangler, så alle kontroller for sådanne funktioner i koden kan elimineres.
Du kan også danne en gruppe af ikke-væsentlige funktioner i check, og eventuelt informere brugeren af ethvert element ændringer, og eventuelt overlade kontrollen spredt rundt i koden.
Med mere OpenGL erfaring, du kan få en fornemmelse af, hvad udvidelser er relateret (eksempler: imaging, shadere, buffere, komprimering, ...).
Derfor kan du tjekke for tilstedeværelse af en enkelt kritisk funktion og anvende disse oplysninger til at afgøre, hvis hele delmængde må formodes at være til stede.
13. Fart
Af forskellige grunde, C# er langsommere end non-CLR C/C++.
C# er sidst udarbejdes ned til indfødte forsamling sprog, ligesom for C/C++, men på grund af de forsikringer, som C# sprog og .NET CLR, den overordnede hastighed af software baseret på C# og .NET er lidt langsommere end software bygges ud non-CLR C/C++.
Derfor får den højeste hastighed muligt ved hjælp non-CLR C/C++ stedet for C#.
Hertil kommer, fordi kræver nogen native bibliotek fra C# indebærer P/Invoke, der påberåber funktioner såsom OpenGL funktioner vil kræve lidt tid til at udføre arbejde i P/Invoke lag.
Ikke desto mindre "CSGL12" synes at arbejde hurtigt nok til at blive anvendt til mange realtid grafiske formål, såsom til enkle spil, 3D-seere, redaktører, eller 3D præsentationer. Dette gælder navnlig, hvis det meste af arbejdet udføres af GPU i stedet for CPU.
14. Sammenligning mellem "CSGL12" og "Tao Framework"
Den "Tao Framework" er en stor C# / .NET bibliotek, som giver en grænseflade til mange open source-biblioteker, som OpenGL, OpenAL (audio), SDL (a gaming / simulation platform), Open Dynamics Engine (ODE) (fysik), osv.
Den Tao Framework er cross-platform (Windows, Linux, Mac OS X).
"CSGL12" kun giver en grænseflade til OpenGL og er kun for Windows operativsystemet.
Den Tao Framework har et samfund. En person kan drage fordel af at kommunikere med andre brugere af Tao Framework.
Der kan imidlertid være mange formål, som "CSGL12" kan være lettere at bruge for Windows programmer.