C# OpenGL interfaccia
per il sistema operativo Windows
Colin Fahey

CSGL12Control su un Form, mostrando un “frattale„ programma pixel shader e GDI+ disegno copiato una texture

Due CSGL12Control casi su un Form, mostrando programmi di pixel shader e texture

Un avatar 3D che vaga sul desktop e può essere spostato con il cursore
1. Software
CSGL12_20090725.zip
CSGL12: C# OpenGL interfaccia per Windows, versione 12
4170499 bytes
MD5: 30781a6570441785ea636f2ae1cd16ef
2. Tutti i computer C# nel codice C# OpenGL interfaccia (CSGL12) è di “dominio pubblico„
Ho scritto tutti i computer C# codice all'interno del C# OpenGL interfaccia (CSGL12).
Dichiaro di tutti i computer C# codice all'interno del C# OpenGL interfaccia (CSGL12) che devono essere di “dominio pubblico.„
Pertanto, il codice può essere utilizzato per qualsiasi scopo (commerciale o privato), senza pagamento, senza restrizioni, senza obblighi e senza riconoscere l'autore originale.
Il codice può essere modificato, o parti di riutilizzati, senza restrizioni e senza obblighi e senza riconoscere l'autore originale.
I programmi di esempio includere una piccola quantità di codice per computer (in particolare, “shader di codice per computer) scritto da altre persone.„ Tale codice non è all'interno della stessa interfaccia e può essere banalmente rimosso. Tale codice è solo per dimostrare la semplicità di utilizzare l'interfaccia per creare e utilizzare “shader„ programmi.
3. Introduzione
“CSGL12„ è una collezione di computer C# file di codice che implementa una interfaccia grafica per la OpenGL libreria (tra cui tutte le estensioni di OpenGL fino all'anno 2007) per il sistema operativo Windows.
Il computer C# codice nel file “CSGL12„ raccolta rendono facile aggiungere OpenGL a qualsiasi disegno C# / .NET software con un “Form„ (un 'istanza di “System.Windows.Forms.Form„).
La collezione di computer “CSGL12„ file di codice include un file denominato “CSGL12Control.cs„, che definisce una classe denominata “CSGL12Control„, derivati da “System.Windows.Forms.Control„. Ogni istanza di “CSGL12Control„ indipendente rappresenta uno OpenGL disegno. E 'molto facile aggiungere più istanze di CSGL12Control ad un Form (un' istanza di System.Windows.Forms.Form).
4. Caratteristiche e requisiti di “CSGL12„
Il codice è solo per Windows sistemi operativi che supportano il .NET 2.0 Framework (Windows 2000, Windows XP, Windows Vista, Windows 7)
Il codice può essere compilato utilizzando “Microsoft Visual C# 2008 Express Edition„ (un compilatore), o simili C# compilatori.
Il codice richiede di essere costruito con la “[X] Allow unsafe code„ costruire opzione selezionata in modo che la copia di dati di immagine ottimizzato funzioni possono essere utilizzate. Se sei un programmatore esperto C# si sarà in grado di identificare facilmente le porzioni di codice C# che richiedono l'“unsafe„ e disabilitare l'opzione desiderata o se richiesto. Copiando i dati di immagine è di 10 volte più veloce utilizzando “unsafe„ codice che l'alternativa, e questo è il motivo per cui tale codice viene utilizzato. Se costruire un DLL che contiene tutte le “unsafe„ codice, quindi un progetto che utilizza DLL che non richiede di essere costruito con l'opzione “unsafe„, e così si può dedurre che l'assenza di “unsafe„ l'opzione di un progetto non comporta alcun supplemento sicurezza (perché DLL numerosi file che vengono utilizzati implicitamente o esplicitamente dal programma contiene codice “pericoloso).„
Il codice può essere compilato e utilizzato da uno dei seguenti elementi:
Microsoft Visual C# 2008 Express Edition
Microsoft Visual Studio 2008
Microsoft .NET 3.5 SDK
SharpDevelop
Mono Project
Il codice offre OpenGL più estensioni (attraverso il 2007 anni), comprese le “vertex shaders„ e “pixel shaders„.
Il codice prevede 1570 funzioni relative alla OpenGL:
336 GL functions
51 GLU functions
19 WGL functions
1164 extensions
Il codice offre alcune alternative variazioni del 1570 con funzioni differenti tipi di parametri, per comodità.
Il codice definisce più di 3244 costanti per OpenGL.
Il codice permette di avere più OpenGL stesura contesti, tutti animazione indipendente, su qualsiasi “Form„.
Facendo clic su un “CSGL12Control„ dà “fuoco in ingresso,„ permettendo successivamente la rotellina del mouse e la tastiera di input. Cursore clic e movimenti sono ricevuti quando il cursore si trova all'interno della zona rettangolare di una istanza di “CSGL12Control„.
Il codice comprende funzioni di dimostrare come fare OpenGL alcuni compiti in comune C# e .NET.
Il codice elenca tutti OpenGL costanti e le funzioni in ordine alfabetico in “class GL„ in “GL.cs„, rendendo semplice per determinare se ogni funzione è costante o mancanti (il che è improbabile, tranne che per le estensioni adottate dopo l'anno 2007).
I programmi di esempio mostra come fare GDI+ disegno di un Bitmap, e poi come copia che Bitmap ad un OpenGL texture.
Ciò consente di testo e di altri GDI+ disegno capacità di contribuire a un OpenGL scena.
La GDI+ Bitmap può essere aggiornato e inserito in un OpenGL texture più spesso una volta al OpenGL cornice.
L'esempio mostra come i programmi di scegliere tra diversi “pixel shader programs„ mentre il programma è in esecuzione.
I programmi di esempio mostra come scrivere OpenGL buffer per i file di immagine (JPG, BMP, GIF, PNG).
Premere Shift + 0 (shift-zero) OpenGL per scrivere il buffer su file di immagine.
Il codice di esempio mostra come compilare “GL.cs„ in un DLL file, quindi aggiungendo che DLL file ad un altro progetto, può impedire la Microsoft codice editori (ad esempio, Microsoft Visual C# 2008 Express Edition, ecc) con “IntelliSense„ (sensibili al contesto completamento del codice) da diventare spesso e persistente insensibili (ripetutamente la pausa per molti secondi, rendendo inutilizzabile l'editor del tutto). Avendo il file direttamente “GL.cs„ incluso in qualsiasi progetto in fase di modifica da un editor di codice Microsoft non è pratico, a meno che una persona è disposta a sopportare la lentezza del redattore. Questo problema ha colpito Microsoft Visual Studio 2003, 2005, 2008, e probabilmente pregiudica la 2010 versione, anche.
Il codice di esempio mostra l'uso di più istanze di “CSGL12Control„ su un “Form„.
Il codice di esempio include il codice per effettuare una 3D “avatar„ che vaga il desktop del Windows.
5. Esempio programmi inclusi con “CSGL12„
5.1 “CSGL12DLL„
Il progetto denominato “CSGL12DLL„ produce un DLL file chiamato “CSGL12DLL.dll„ che contiene “class GL„ (definito nel C# file “GL.cs„).
Mettere “class GL„ a un DLL file, quindi utilizzando DLL che in altri progetti che utilizzano “class GL„, aiuta a evitare un problema di estrema con tutti i Microsoft con l'editor di codice IntelliSense funzione. Utilizzando il C# file GL.cs direttamente in un progetto provocherebbe Microsoft qualsiasi editor di codice con la funzione di diventare IntelliSense totalmente insensibili e quasi inutilizzabile a causa di continuo l'inefficienza del IntelliSense caratteristica (e il fatto che evidentemente IntelliSense blocchi il programma principale del thread l'editor ).
Se si sta utilizzando un editor di codice C# che non è prodotto da Microsoft (ad esempio, “SharpDevelop„, “MonoDevelop„, ecc), allora si può semplicemente inserire il file direttamente nel tuo “GL.cs„ progetti, e si sarebbe improbabile ottenere alcun beneficio dal usando “CSGL12DLL.dll„.
5.2 “CSGL12Control„
Il progetto denominato “CSGL12Control„ produce un DLL file chiamato “CSGL12Control.dll„ che contiene “class CSGL12Control„ (definito nel C# file “CSGL12Control.cs„).
Mettere “class CSGL12Control„ a un DLL file, che consente “Control„ (ad esempio, una classe derivata da “System.Windows.Forms.Control„) da aggiungere al “Toolbox„ di Microsoft Visual C# 2008 Express Edition (e simili C# editori). Dopo aver “CSGL12Control„ nel “Toolbox„ rende facile per una persona di aggiungere un 'istanza di “CSGL12Control„ ad un “Form„ nel “Designer„ (ad esempio, una persona può semplicemente utilizzare il cursore per selezionare e trascinare un' istanza di “CSGL12Control„ dal “Toolbox„ ad un “Form„).
L'oggetto “CSGL12Control„ gestisce uno OpenGL disegno contesto. Istanze multiple di “CSGL12Control„ possono coesistere su un “Form„.
5.3 “CSGL12Example1„
Il progetto denominato “CSGL12Example1„ produce un file di programma eseguibile (EXE) chiamato “CSGL12Example1.exe„. Il programma utilizza “CSGL12DLL.dll„ e “CSGL12Control.dll„ per visualizzare un esempio di CSGL12Control e disegnare un cubo utilizzando OpenGL.
Il programma mostra l'uso di quattro diversi “pixel shaders„ “(frattale, mattoni, legno„ e “cartone).„
Il programma mostra anche l'uso di “GDI+„, un disegno .NET biblioteca, per disegnare il testo e le altre forme di un oggetto “Bitmap„ (uno “GDI+„ oggetto), e poi copiare l'immagine che i dati da “Bitmap„ ad un “texture„ in OpenGL, consentendo in tal modo l'immagine tratte da “GDI+„ a comparire in OpenGL disegno. Questa capacità è molto utile perché OpenGL priva di molte delle funzioni di disegno 2D trovati in “GDI+„ e simili 2D disegno librerie.
5.4 “CSGL12Example2„
Il progetto denominato “CSGL12Example2„ produce un file di programma eseguibile (EXE) chiamato “CSGL12Example2.exe„. Il programma utilizza “CSGL12DLL.dll„ e “CSGL12Control.dll„ per visualizzare due istanze di CSGL12Control, ciascuno dei quali richiama un cubo utilizzando OpenGL.
Il programma ha una “SplitContainer„ “Control„ sulla “Form„. Ciascuna delle due aree del “SplitContainer„ contiene un 'istanza di CSGL12Control. Così, una persona in grado di regolare la posizione della suddivisione tra le due istanze di CSGL12Control. Ciò dimostra la flessibilità del CSGL12Control.
Uno dei casi di eventi CSGL12Control invia ad una serie di gestori di eventi in un 'istanza di “CSGL12Example2Handler1.cs„, che usa lo stesso codice come “CSGL12Example1Handler.cs„ in “CSGL12Example1„ progetto di esempio. Pertanto, uno dei casi CSGL12Control attira un cubo con un selezionato “pixel shader„ tra quattro disponibili “pixel shaders„.
L'altro esempio di eventi CSGL12Control invia ad una serie di gestori di eventi in un 'istanza di “CSGL12Example2Handler2.cs„, che richiama un cubo utilizzando una texture immagine (o uno schema “a scacchiera,„ se un file immagine “image.jpg„ chiamato non è stato trovato).
5.5 “CSGL12Avatar„
Il progetto denominato “CSGL12Avatar„ produce un file di programma eseguibile (EXE) chiamato “CSGL12Avatar.exe„. Il programma utilizza “CSGL12DLL.dll„ e “CSGL12Control.dll„ per disegnare un cubo utilizzando OpenGL a “Form„ senza frontiere, con colori a base di trasparenza abilitato, per disegnare una 3D “avatar„ che vaga Windows il desktop.
Il movimento può essere avatar cliccato e trascinato in una nuova posizione utilizzando il cursore. Doppio clic sul avatar renderà svanire. Sebbene il codice si limita richiama un cubo, OpenGL può essere usato per disegnare le altre cose.
Istanze multiple “avatar„ del programma può essere avviato. Così, molti indipendenti “avatar„ casi può simultaneamente vagare la Windows desktop. Questo è divertente. Un esperto C# programmatore può godere di trovare modi per coordinare l'attività di molti di questi casi “avatar.„
Purtroppo, il tasso al quale l'oggetto Window con trasparenza è aggiornato sullo schermo è molto più lento rispetto alla velocità con cui possono attingere OpenGL. “L'avatar„ aggiorna solo 10 volte al secondo. Non so se questo può essere migliorato.
5.6 “CSGL12BuiltExecutableExamplesForReference„
La directory contiene DLL nome “CSGL12BuiltExecutableExamplesForReference„ file e file EXE prodotto da parte di tutti i progetti di esempio. Questi file sono forniti come un riferimento, in modo che i file possono essere testati immediatamente, anche se una persona non ha la possibilità di compilare i vari progetti previsti dal codice C#.
5.7 “CSGL12UsefulCode„
La directory contiene C# nome “CSGL12UsefulCode„ file che potrebbero essere utili alle persone che vogliono fare le operazioni di disegno comune con OpenGL. L'elenco comprende anche il DLL file “CSGL12DLL.dll„ e “CSGL12Control.dll„ per convenienza.
Il codice in quella directory class definisce vari tipi, come Color4f, Vector3f, Matrix4x4f, Triangle, Mesh, ImageData, Texture, ShaderProgram, ecc Il codice è ragionevolmente efficiente, ma il codice è solo destinato ad ispirare le persone a sviluppare le proprie implementazioni.
6. CSGL12 file
Il “CSGL12„ collezione di computer C# codice file include il file indicato nel seguente schema:

Il “CSGL12„ collezione di computer C# codice file include il file mostrati in questo schema.
“CSGL12„ Il software comprende anche i progetti per creare i due file DLL (“CSGL12DLL.dll„ e “CSGL12Control.dll„) mostrato nel diagramma. Questi due DLL file possono essere creati per rendere più conveniente per creare programmi che usano OpenGL, ma è anche possibile creare dei programmi, utilizzando solo i file direttamente C#.
7. “namespace CSGL12„ e “class„ tipi
Il “CSGL12„ collezione di computer C# file di codice definisce “namespace CSGL12„ e la “class„ tipi mostrato nel diagramma seguente:

Il “CSGL12„ collezione di computer C# file di codice definisce “namespace CSGL12„ e la “class„ tipi mostrato in questa figura.
Un programma che non OpenGL disegno può essere creato utilizzando solo “class GL„ (utilizzando il C# file GL.cs direttamente, o tramite il DLL file CSGL12DLL.dll che contiene anche “class GL„). Tuttavia, utilizzando “class CSGL12Control„ (utilizzando il C# file CSGL12Control.cs direttamente, o tramite il DLL file CSGL12Control.dll che contiene anche “class CSGL12Control„) rende aggiungendo OpenGL disegno ad un Form (System.Windows.Forms.Form) semplice e pratico.
Il C# classi Color4f, CSGL12Support, ImageData, ..., nella parte inferiore del diagramma sono offerte unicamente per comodità. Tali classi di rendere più semplice per creare programmi che trarre utilizzando OpenGL. Tuttavia, si potrebbe già avere le classi che eseguono le operazioni in tali classi, o si può scegliere di creare simili classi che eseguono le operazioni di diverso o in modo più efficiente. Tali classi sono offerti come esempi di un particolare codice di progettazione e di attuazione.
8. Utilizzando un unico “CSGL12Control„ su un System.Windows.Forms.Form
8.1 Struttura del programma
Il diagramma seguente mostra come un programma con un System.Windows.Forms.Form possibile utilizzare un unico “CSGL12Control„ a che fare con il disegno OpenGL. Il diagramma mostra i vari CSGL12 i file usati per costruire il programma.

Un programma con un unico “CSGL12Control„ su un System.Windows.Forms.Form
8.2 Uso Microsoft Visual C# per creare il programma
(1) Inizio Microsoft Visual C#.
(2) Nel menu, selezionare “File„ -> “New Project...„.
(3) In “New Project„ finestra di dialogo che appare, selezionate “Windows Forms Application„, e scegliere un nome per il programma, e premere “OK„.
Immediatamente (4) salvare il “Solution„ selezionando “File„ -> “Save All„. Una finestra di dialogo con il titolo “Save Project„ verrà visualizzato, permettendo di impostare il nome del progetto, directory, il nome e la “soluzione„ per il progetto. Ricordate le directory in modo che si è pronti per la prossima istruzione. “Save„ Premere il pulsante per salvare il progetto.
(5) Copia tutti i file dalla directory “CSGL12UsefulCode„ nel “CSGL12„ software per la directory che contiene i file di codice sorgente del nuovo progetto (cioè la directory contenente i file “Form1.cs„, “Form1.Designer.cs„, “Program.cs„, ecc), in modo che i file “CSGL12DLL.dll„, “CSGL12Control.dll„, “Color4f.cs„ , “CSGL12Support.cs„, ecc, sono a fianco del nuovo file di progetto “Form1.cs„, ecc
(6) In Microsoft Visual C#, “CSGL12„ C# aggiungere il file al progetto. Nel menu, selezionare “Project„ -> “Add Existing Item...„, e nella finestra di dialogo “Add Existing Item„, selezionare tutti i file C# dal CSGL12 software (“Color4f.cs„, “CSGL12Support.cs„, “ImageData.cs„, ...).
(7) In Microsoft Visual C#, aggiungere i “riferimenti„ al DLL file “CSGL12DLL.dll„ e “CSGL12Control.dll„. Nel menu, selezionare “Project„ -> “Add Reference...„, in “Add Reference„ la finestra di dialogo, selezionare la scheda “Browse„, e selezionare il file “CSGL12DLL.dll„ e “CSGL12Control.dll„ dal progetto fonte directory dei file, premere e “OK„.
(8) In Microsoft Visual C#, aggiungere il “CSGL12Control„ al “Toolbox„. Nel menu, selezionare “Tools„ -> “Choose Toolbox Items...„. In “Choose Toolbox Items„ finestra di dialogo che viene visualizzata, premere il pulsante “Browse...„, e vai al progetto con la directory di file di codice sorgente, e selezionare “CSGL12Control.dll„. Premere il pulsante “OK„.
(9) In Microsoft Visual C#, vista la “Toolbox„. Nel menu, selezionare “View„ -> “Toolbox„. In “Toolbox„, vai alla sezione denominata “General„, e individuare l'elemento chiamato “CSGL12Control„. Utilizzando il cursore, fare clic sulla voce denominata “CSGL12Control„ e trascinarlo nella “Form„ in “Design„ vista.
(10) In Microsoft Visual C#, nel “Form„ “Design„ vista, spostare il “CSGL12Control„ esempio il “Form„ e regolare la larghezza e l'altezza. In “Properties„ pannello, impostare il valore “Anchor„ includere “Top, Bottom, Left, Right„ se si desidera che il controllo per modificare le dimensioni in base ai cambiamenti nella dimensione della finestra del programma.
(11) In Microsoft Visual C#, modificare le proprietà del progetto in modo che possa utilizzare “unsafe„ codice. Nel menu, selezionare “Project„ -> “[project] Properties...„. Selezionare la finestra di dialogo che appare, scegliere la scheda denominata “Build„, e verificare che la casella di controllo denominato “[X] Allow unsafe code„. Chiudere la finestra di dialogo delle proprietà del progetto.
(12) In Microsoft Visual C#, aggiungere un nuovo file C# al progetto. Nel menu, selezionare “Project„ -> “Add New Item...„. Nella finestra di dialogo nome “Add New Item„, scegli il modello denominato “Class„, e scegliere un nome per la nuova classe di tipo, come ad esempio “CSGL12MyHandler.cs„, quindi premere il pulsante “Add„. Guardate l'esempio del progetto denominato “CSGL12Example1„, al file denominato “CSGL12Example1Handler.cs„, come un esempio di come il codice di “CSGL12MyHandler.cs„ deve essere scritto.
(13) In Microsoft Visual C#, nel “Solution Explorer„, fare clic sul “Form1„. Nel menu, selezionare “View„ -> “Code„ (o premere F7, o fate clic destro su di “Form1„ e scegli “View Code„. Il codice del file verrà visualizzato nella “Form1.cs„ l'editor. Modificare il codice nel file “Form1.cs„ essere simile al codice nel file “CSGL12Example1Form.cs„ nel progetto “CSGL12Example1„ incluso nel software “CSGL12„. In particolare, creare una variabile per un esempio del vostro gestore di eventi di classe (ad esempio, “CSGL12MyHandler„), e poi aggiungere i metodi di questa classe di esempio come gestori di eventi per i vari eventi della istanza di “CSGL12Control„ sulla “Form„.
(14) In Microsoft Visual C#, compilare ed eseguire il programma. Se si desidera condividere il programma, è necessario includere i due DLL file (“CSGL12DLL.dll„ e “CSGL12Control.dll„) con il file eseguibile (*.exe).
Se sei un programmatore esperto C#, quindi si può evitare la necessità di distribuire il file DLL (“CSGL12DLL.dll„ e “CSGL12Control.dll„) con il tuo eseguibile (*.exe).
Copiare i file “GL.cs„, “CSGL12Control.cs„, e dai progetti “PrecisionTime.cs„ nome “CSGL12DLL„ e “CSGL12Control„ nel “CSGL12„ software per la directory dei sorgenti del progetto corrente. Aggiungere il file “GL.cs„, “CSGL12Control.cs„, e “PrecisionTime.cs„ al progetto in modo che essi siano compilati direttamente nel programma. Non sono i riferimenti a “CSGL12DLL.dll„ e “CSGL12Control.dll„ nel progetto.
Vedi il progetto “CSGL12Example1„ nel “CSGL12„ software, e guardare il codice all'interno del file chiamato “CSGL12Example1Form.cs„ e “CSGL12Example1Form.Designer.cs„ per vedere che cosa è richiesto il codice per creare e inizializzare un 'istanza di “CSGL12Control„ su un “Form„. Aggiungi il codice simile a “Form1.cs„ e “Form1.Designer.cs„ manualmente creare e inizializzare un 'istanza di “CSGL12Control„ sul tuo “Form„.
Questa procedura è molto scomodo, e richiede competenza e attenzione, ma la risultante eseguibile (*.exe) non richiedono “CSGL12DLL.dll„ o “CSGL12Control.dll„. E 'molto bello essere in grado di condividere il software in forma di un unico file eseguibile (*.exe) senza bisogno di altri file.
8.3 Aggiungere “riferimenti„ a CSGL12DLL.dll e CSGL12Control.dll
Questa sezione comprende le immagini di utilizzare Microsoft Visual C# 2008 Express Edition di aggiungere “riferimenti„ alla DLL file CSGL12DLL.dll e CSGL12Control.dll al progetto.
Nel menu, selezionare “Project„ -> “Add Reference...„. Oppure, fare clic destro sulla voce “References„ nel “Solution Explorer„ pannello e selezionare “Add Reference...„, come mostrato nella figura seguente.

Menù contestuale per “References„ la voce del “Solution Explorer„, mostrando la “Add Reference...„ opzione
Dopo aver selezionato l'opzione “Add Reference...„, una finestra di dialogo verrà visualizzato il nome “Add Reference„. In tale finestra di dialogo, selezionare la scheda “Browse„, DLL e selezionare il file “CSGL12DLL.dll„ e “CSGL12Control.dll„, come mostrato nella seguente immagine, e quindi premere il pulsante “OK„.

La scheda “Browse„ del “Add Reference„ finestra di dialogo, con la DLL file “CSGL12DLL.dll„ e “CSGL12Control.dll„ sia selezionato
Dopo aver premuto il pulsante “OK„, la finestra di dialogo “Add Reference„ svaniranno, e la DLL file “CSGL12DLL.dll„ e “CSGL12Control.dll„ apparirà nel “References„ succursale nel “Solution Explorer„, come mostrato nella figura seguente.

Il DLL file “CSGL12DLL.dll„ e “CSGL12Control.dll„ nel “References„ succursale nel “Solution Explorer„
8.4 Aggiunta di CSGL12Control al Toolbox in Microsoft Visual C# 2008 Express Edition
Questa sezione comprende le immagini di utilizzare Microsoft Visual C# 2008 Express Edition aggiungere CSGL12Control al “Toolbox„ in modo che una persona può aggiungere facilmente i casi di CSGL12Control a un “Form„ nel “Designer„ (Shift+F7 per impostazione predefinita).
Nel menu, selezionare “View„ -> “Toolbox„. In “Toolbox„, vai alla sezione denominata “General„, come mostrato nella figura seguente.

Il “General„ sezione del “Toolbox„
Fai clic destro in qualsiasi punto all'interno della “Toolbox„. Selezionare l'opzione “Choose Items...„ nel menu contestuale che appare, come mostrato nella figura seguente.

L'opzione “Choose Items...„ nel menu contestuale per la “Toolbox„
In alternativa, nel menu, selezionare selezionare “Tools„ -> “Choose Toolbox Items...„.
Il “Choose Toolbox Items„ dovrebbe apparire la finestra di dialogo, come mostrato nella figura seguente.

La finestra di dialogo “Choose Toolbox Items„
In “Choose Toolbox Items„ finestra di dialogo, premere il pulsante “Browse„. In “Open„ finestra di dialogo che appare, selezionate il DLL file “CSGL12Control.dll„, come mostrato nella seguente immagine, e quindi premere il pulsante “OK„.

Il “Open„ finestra di dialogo, con la DLL file selezionato “CSGL12Control.dll„
La voce “CSGL12Control„ dovrebbe ora apparire nella finestra di dialogo “Choose Toolbox Items„, come mostrato nella figura seguente. Premere il pulsante “OK„.

La voce “CSGL12Control„ ora appare nella finestra di dialogo “Choose Toolbox Items„
La voce “CSGL12Control„ dovrebbe ora apparire nel “Toolbox„, come mostrato nella figura seguente.

La voce “CSGL12Control„ ora appare nella “Toolbox„
8.5 Aggiunta di CSGL12Control ad un “Form„ utilizzando il “Toolbox„
Questa sezione comprende le immagini di utilizzare Microsoft Visual C# 2008 Express Edition per aggiungere un 'istanza di CSGL12Control ad un “Form„ utilizzando la “Toolbox„.
Nel menu, selezionare “View„ -> “Designer„ (Shift+F7 per impostazione predefinita). In alternativa, fare doppio clic su un file “Form*.cs„ nel “Solution Explorer„. Oppure cliccate con il tasto destro uno “Form*.cs„ file nel “Solution Explorer„ e selezionare “View Designer„. Utilizzando uno di questi tre metodi, “Designer„ la finestra per un “Form„ dovrebbe apparire.
Nel menu, selezionare “View„ -> “Toolbox„. In “Toolbox„, vai alla sezione denominata “General„. Un elemento “CSGL12Control„ nome dovrebbe comparire lì, come mostrato nella figura seguente.

Il “CSGL12Control„ dovrebbe già essere in “Toolbox„
Utilizzando il cursore, fare clic sulla voce denominata “CSGL12Control„ e trascinarlo nella “Form„ in “Designer„. Un esempio di “CSGL12Control„ dovrebbe comparire sul “Form„ come mostrato nella figura seguente.

Un esempio di “CSGL12Control„ su un “Form„ nel “Designer„
In “Form„ “Designer„ vista, spostare l'istanza di “CSGL12Control„ sulla “Form„ e regolare la larghezza e l'altezza.
Clicca sulla istanza di “CSGL12Control„ sulla “Form„ per selezionarla. Poi, nel “Properties„ pannello, impostare il valore “Anchor„ includere “Top, Bottom, Left, Right„ in modo che le dimensioni del “CSGL12Control„ cambia in risposta ai cambiamenti nella dimensione della finestra del programma. Si potrebbe anche voler cambiare il nome della variabile (cioè, il valore di “(Name)„) per l'istanza di “CSGL12Control„ dal automatica predefinita (ad esempio, “csgL12Control„) a qualcosa di adeguato per il vostro codice (ad esempio, “mCSGL12Control„ o “mCSGL12Control1„, ecc.)
L'immagine seguente mostra la vista “Form„ “Designer„ e la “Properties„ pannello.

Un esempio di CSGL12Control su un Form nel Designer, e il pannello “Properties
9. Utilizzo di due istanze di “CSGL12Control„ su un System.Windows.Forms.Form
Il diagramma seguente mostra un esempio di come due istanze di “CSGL12Control„ possono essere aggiunti ad un System.Windows.Forms.Form a che fare con il disegno OpenGL in un programma.

Un programma con due istanze di “CSGL12Control„ su un System.Windows.Forms.Form
Seguire le istruzioni nella sezione precedente per aggiungere una singola istanza di “CSGL12Control„ a un “Form„. Quindi, è sufficiente trascinare una seconda istanza di “CSGL12Control„ dal “Toolbox„ al “Form„ di aggiungere un secondo “CSGL12Control„.
Ogni istanza di “CSGL12Control„ disporrà di un proprio nome di variabile. Ogni istanza di “CSGL12Control„ può disporre di un proprio gestore di eventi associati classe, oppure può utilizzare distinte istanze di un unico gestore di classe tipo.
L'esempio del progetto di studio per imparare “CSGL12Example2„ due casi “CSGL12Control„ possono avere la loro eventi inviati a due distinte istanze di classi personalizzate con il gestore di eventi distinti OpenGL disegno funzioni.
Il programma di esempio, ha “CSGL12Example2„ ogni istanza di “CSGL12Control„ in un “SplitContainer„ “Control„, semplicemente un modo per dimostrare che in caso di “CSGL12Control„ può essere usato. Tuttavia, le istanze di “CSGL12Control„ può invece essere messo direttamente al “Form„.
10. Esempio C# codice per un “Form„ con un 'istanza di CSGL12Control
Di seguito è riportato il testo completo del C# codice contenuto nel file “CSGL12Example1Form.cs„, che fa parte del programma di esempio, “CSGL12Example1„.
Questo codice è presentato qui come un semplice esempio di come un 'istanza di CSGL12Control possono essere creati e utilizzati da un “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);
}
}
}
Si noti che la variabile membro “mCSGL12Example1Handler„ è dichiarato di fare riferimento a un esempio di un class denominata “CSGL12Example1Handler„. Questa categoria sarà descritto in una successiva sezione del presente documento. Notare che il costruttore per “CSGL12Example1Form„ aggiunge i metodi di istanza di “CSGL12Example1Handler„ al “multicast delegates„ associati ai vari eventi generati da un 'istanza di “CSGL12Control„. Questo significa che quando l'istanza di “CSGL12Control„ genera vari eventi, le manifestazioni causare vari metodi di istanza di “CSGL12Example1Handler„ (vale a dire, “mCSGL12Example1Handler„) ad essere invocate.
Si noti che la variabile membro “mTimer„ è dichiarato di fare riferimento a un esempio di un class denominata “System.Windows.Forms.Timer„. Questo oggetto è utilizzato per richiamare una funzione chiamata “PrivateTimerTickEventHandler„ ogni 10 millisecondi. La funzione denominata “PrivateTimerTickEventHandler„ chiede un metodo di istanza di “CSGL12Control„ (vale a dire, “mCSGL12Control1„) che provoca “Control„ che a trarre per sé. Questo è un esempio di come può “CSGL12Control„ animato in un tasso approssimativa.
Solo una parte della definizione di “class CSGL12Example1Form„ compare nel C# file chiamato “CSGL12Example1Form.cs„. Un'altra parte della definizione di “class CSGL12Example1Form„ sembra C# in un file chiamato “CSGL12Example1Form.Designer.cs„. Anche se i file con nomi corrispondenti al modello “*.Designer.cs„ sono in genere creati e modificati solo con la grafica “Form Designer„ finestra C# di un editore, è anche possibile creare e modificare tali C# file utilizzando un editor di testo.
Di seguito è riportato il testo completo del C# codice contenuto nel file “CSGL12Example1Form.Designer.cs„, che fa parte del programma di esempio, “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;
}
}
Si noti che questo codice C# contiene la dichiarazione della variabile “mCSGL12Control1„, che si riferisce a un 'istanza di “class CSGL12.CSGL12Control„ (vale a dire, “class CSGL12Control„ in “namespace CSGL12„). Questo esempio è stato creato e configurato nella funzione “InitializeComponent„.
11. Gestione di eventi invocata da un 'istanza di CSGL12Control
La parte precedente ha mostrato C# codice per un “Form„ che conteneva una singola istanza di “CSGL12Control„. Il codice C# aggiungere metodi di “class„ nome “CSGL12Example1Handler„ come gestori di eventi per diversi eventi generati dal grado di “CSGL12Control„.
Ecco un elenco di interessanti eventi di “CSGL12Control„, e la “delegate„ associati a tali tipi di eventi:
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
Solo il “OpenGLStarted„ manifestazione è un evento di tipo specifico per la “CSGL12Control„.
Tutti gli altri eventi sono standard System.Windows.Forms eventi, i cui gestori di eventi devono avere determinati parametri (specificati in qualsiasi Forms documentazione).
Il “OpenGLStarted„ e “Paint„ eventi sono i più importanti eventi per OpenGL disegno.
“OpenGLStarted„ il caso viene invocato prima della prima “Paint„ evento è invocato.
Pertanto, la “OpenGLStarted„ gestore di eventi deve essere aggiunto al controllo prima che il controllo è l'occasione per tentare di dipingere se stessa, altrimenti il tempo di un evento non verrà ricevuto.
Questo evento è solo una comodità, e può essere ignorato.
Tuttavia, l'aggiunta di un gestore per questo evento rende possibile per il gestore di codice a fare un po di un tempo di inizializzazione che dipende OpenGL di essere pronto per l'uso.
(OpenGL non può essere utilizzato fino a quando la finestra esiste e la finestra è pronta a svolgere il suo primo vernice.
Così, il caso “OpenGLStarted„ risparmia il programmatore dal rischio di tentare di utilizzare OpenGL troppo presto dopo il programma si avvia.
) E 'abbastanza facile aggiungere “Paint„ in una logica di gestione a fare una sola volta l'inizializzazione, utilizzando il contesto OpenGL del “CSGL12Control„.
“OpenGLStarted„ la manifestazione è offerto come convenienza.
Di seguito è riportato il testo completo del C# codice contenuto nel file “CSGL12Example1Handler.cs„, che fa parte del programma di esempio, “CSGL12Example1„.
Questo codice è presentato qui come un semplice esempio di come gli eventi generati da un 'istanza di “CSGL12Control„ può essere trattata a disegnare utilizzando 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;
}
}
}
Si noti che la funzione chiamata “OpenGLStarted„ è utilizzato in questo esempio per creare uno “pixel shader programs„ e OpenGL texture. Per questo programma, abbiamo solo bisogno di creare una volta che tali risorse, ed è più efficace per creare una sola volta.
Si noti che la funzione chiamata “OpenGLStarted„ il codice verifica se uno WGL “extension„ funzione chiamata “wglSwapIntervalEXT()„ esiste, e, se tale funzione non esiste, il codice che richiama la funzione. Questa funzione imposta uno stato che influisce sul funzionamento del programma per tutta la sessione, e così abbiamo bisogno di chiamare solo una volta che la funzione, che è il motivo per cui si cerca di chiamare la funzione che nel “OpenGLStarted„ funzione (che si è fatto valere solo una volta, quando OpenGL è iniziato per un particolare “CSGL12Control„, assumendo abbiamo aggiunto il “OpenGLStarted„ metodo appropriato per la manifestazione delegato).
La funzione denominata “Paint„ contiene tutto il codice per disegnare un singolo “fotogramma„ di animazione utilizzando OpenGL. La funzione “Paint„ sarà chiamato forse 60 volte al secondo, dovuto al fatto che le relative “CSGL12Control„ esempio viene “invalidata„ (costretti a trarre per sé di nuovo) a tale tasso. (Vedi il “Form„ esempio di codice nella sezione precedente per visualizzare il timer che determina il tasso di “nullità„ e l'effettiva chiamata di funzione che provoca l'istanza di “CSGL12Control„ a diventare “falsificati.)„
Tutte le funzioni sono invocate OpenGL utilizzando un esempio della “class GL„ (esempio: gl.gl*()). L'istanza di “class GL„ è acquisito dalla istanza di “CSGL12Control„, che è implicitamente memorizzati nel primo parametro per la “Paint„ funzione.
Tutti i OpenGL costanti può essere specificato da “class„ specificando il nome “GL„ seguita da un punto e il nome della costante, cioè, “GL.GL_TRIANGLES„.
Il OpenGL codice in questo esempio non è del tutto ovvio e facile da capire, ma speriamo di poter riconoscere come il codice può essere modificato per i propri scopi.
12. Verifica la disponibilità di una funzione di “estensione„ OpenGL
Basta verificare se l'operatore booleano di bandiera lo stesso nome del OpenGL funzione è “vero„ prima di tentare di utilizzare la funzione corrispondente.
La variabile booleana ha un nome che inizia con “b„ seguita dal nome della funzione OpenGL.
if (true == gl.bglCreateProgramObjectARB)
{
// glCreateProgramObjectARB() exists and can be invoked.
// Also, because that function is related to pixel shaders, it is very
// likely that other functions that are required for the use of pixel
// shaders also exist and can be invoked.
// . . .
}
Controllo è necessaria solo per “l'estensione„ funzioni.
OpenGL 1.1 funzioni, e tutti i GLU funzioni, e funzioni fondamentali WGL, non necessitano di tale controllo. Tuttavia, Booleano bandiere esistono, e sono fissati adeguatamente, per tutte le funzioni fornite da “class GL„, comprese le funzioni fondamentali OpenGL 1.1. Pertanto, non vi è modo coerente per verificare la disponibilità di tutte le funzioni in questa categoria.
Conoscere o meno una funzione è una “estensione„ è di competenza del programmatore.
Tuttavia, la funzione suffissi di nomi, come ad esempio “EXT„, “ARB„, “MESA„, “NV„ (NVidia), “APPLE„, ecc, aiuto indicano l'estensione funzioni.
Se una funzione “gl*()„ ha una funzione “gl*ARB()„ vicine o “gl*NV(),„ la funzione “gl*()„ è probabilmente una proroga (fino al Windows OPENGL32.DLL è interessato).
L'unico vantaggio di conoscere o meno una funzione è “un'estensione„ (per quanto riguarda la Windows OPENGL32.DLL) è in grado di evitare di verificare se le funzioni sono disponibili.
È possibile cercare tutti i OpenGL funzioni utilizzate nel codice, quindi costruire un elenco alfabetico delle diverse funzioni utilizzate.
Poi, all'inizio del vostro programma, dopo la CSGL12Control invita il OpenGLStarted delegato, semplicemente controllare tutti i Booleano bandiere di tutte le funzioni che si desidera utilizzare.
Se si sceglie di chiudere il programma eventuali funzioni “richieste„ sono mancanti, quindi tutti i controlli per tali funzioni nel codice può essere eliminato.
Inoltre, è possibile formare un gruppo di non-funzioni essenziali nel verificare e, eventualmente, informare l'utente di qualsiasi funzione di modifiche e, se possibile, lasciare sparsi per i controlli nel codice.
OpenGL con più esperienza, è possibile ottenere un senso di ciò che le estensioni sono connessi (esempi: immagini, shader, tamponi, compressione, ...).
Pertanto, è possibile verificare la presenza di una sola funzione critica e di utilizzare tali informazioni per decidere se l'intera sottoinsieme è suscettibile di essere presenti.
13. Velocità
Per varie ragioni, C# è più lento di quello non-CLR C/C++.
C# viene compilato a nativo linguaggio assembly, così come per C/C++, ma, a causa delle assicurazioni fatte dalla C# lingua e la .NET CLR, la velocità del software basato su C# e .NET è un po 'più lento di quello costruito utilizzando il software non-CLR C/C++.
Pertanto, ottenendo la massima velocità possibile, utilizzando mezzi non-CLR C/C++ invece di C#.
Inoltre, a causa di chiamata qualsiasi libreria nativa da C# comporta P/Invoke, invocando funzioni come ad esempio le funzioni OpenGL richiederà un po 'di tempo per l'esecuzione di lavori nel P/Invoke livello.
Tuttavia, “CSGL12„ sembra funzionare abbastanza rapidamente da utilizzare per molti grafici in tempo reale scopo, come per semplici giochi 3D gli spettatori, gli editori, o presentazioni 3D. Ciò è particolarmente vero se la maggior parte del lavoro viene svolto dal GPU invece del CPU.
14. Confronto tra “CSGL12„ e la “Tao Framework„
Il “Tao Framework„ è un grande C# / .NET libreria che fornisce un'interfaccia per molte librerie open-source, come OpenGL, OpenAL (audio), SDL (un gioco / simulazione piattaforma), Open Dynamics Engine (ODE) (fisica), ecc
Il Tao Framework è cross-platform (Windows, Linux, Mac OS X).
“CSGL12„ solo fornisce un'interfaccia per OpenGL ed è solo per il sistema operativo Windows.
Il Tao Framework ha una comunità. Una persona può beneficiare di comunicare con i colleghi degli utenti del Tao Framework.
Tuttavia, ci possono essere molti motivi per i quali “CSGL12„ potrebbe essere più facile da usare per Windows programmi.