English  Español  Português  Français  Italiano  Deutsch  Nederlands  Svenska  Dansk  Suomi  Norsk  Русский  Polski  Română  Български  Hrvatski  Česky  中国  中國  日本語  한국어  Ελληνική  हिन्दी  العربية 
C# OpenGL интерфейс
за Windows операционна система
Colin Fahey
CSGL12Example1_ScreenImage.png
CSGL12Control по Form, показващи "fractal" Pixel Shader програма и GDI+ рисунка копирани на текстура
CSGL12Example2_ScreenImage.png
Две CSGL12Control копия на Form, показващи Pixel Shader програми и текстури
CSGL12Avatar_ScreenImage.png
А 3D въплъщение че roams десктопа и могат да бъдат преместени с курсора

1. Софтуер

CSGL12_20090725.zip
CSGL12: C# OpenGL интерфейс за Windows, версия 12
4170499 bytes
MD5: 30781a6570441785ea636f2ae1cd16ef

2. Всички обяви на C# компютърен код в C# OpenGL интерфейс (CSGL12) е в "публичния домейн"

Написах всичко на C# компютърен код в рамките на C# OpenGL интерфейс (CSGL12).
Декларирам, всички от C# компютърен код в рамките на C# OpenGL интерфейс (CSGL12), за да бъде в "публичния домейн."
Ето защо, компютърен код може да се използва за всякакви цели (търговски или частни), без заплащане, без ограничения, без задължения и без признаване на оригиналния автор.
Кодът може да бъде променена, или части се използват повторно, без ограничения и без задължения и без признаване на оригиналния автор.
Примерът програми включват малък размер на компютърен код (конкретно, "shader компютърен код), написани от други хора."  Такива код не е в рамките на самия интерфейс и могат да бъдат отстранени trivially.  Такива код е само, за да се демонстрира простота на използване на интерфейс за създаване и използване "shader" програми. 

3. Въведение

"CSGL12" е колекция от C# компютърни файлове с код, който осъществява връзката с OpenGL графична библиотека (включително всички удължавания на OpenGL до 2007 година) за Windows операционна система.
В C# компютърен код файлове в "CSGL12" колекция позволяват лесно да добавите OpenGL съставяне на всеки C# / .NET софтуер с "Form" (копие на "System.Windows.Forms.Form").
В "CSGL12" събиране на компютърен код файлове включва файл на име "CSGL12Control.cs", което определя класа на име "CSGL12Control", получени от "System.Windows.Forms.Control".  Всяко копие на "CSGL12Control" представлява независим OpenGL рисунка област.  То е много лесно да добавите няколко копия на CSGL12Control до Form (копие на System.Windows.Forms.Form).

4. Характеристики и изисквания на "CSGL12"

Кодът е само за Windows операционни системи, които поддържат .NET 2.0 Framework (Windows 2000, Windows XP, Windows Vista, Windows 7)
Кодът може да се използва "Microsoft Visual C# 2008 Express Edition" (безплатен компилатор), или други подобни C# компилатори.
Кодът изисква бъде изградена с "[X] Allow unsafe code" изгради опция избрани така, че изображението оптимизирани данни копиране функции могат да бъдат използвани.  Ако Вие сте експерт C# програмист ще можете лесно да се идентифицира части от C# код, който изисква "unsafe" опция и ги прекъснем, ако желания или задължителни.  Image копиране на данни е 10 пъти по-бързо чрез "unsafe" кода от алтернативата, и този е защо този код е използван.  Ако построят DLL, който ще съдържа всички по-"unsafe" код, след което един проект, който използва тази DLL не изисква бъде изградена с "unsafe" опция, както и за да можете да се заключава, че липсата на "unsafe" опция в един проект, не означава всяко допълнително безопасност (поради многото DLL файлове, които се използват косвено или пряко от програмата съдържа "опасен" код). 
Кодът може да се състави и използвана от всеки от следните елементи:
Microsoft Visual C# 2008 Express Edition
Microsoft Visual Studio 2008
Microsoft .NET 3.5 SDK
SharpDevelop
Mono Project
Кодът предлага най-OpenGL разширения (чрез 2007 години), включително "vertex shaders" и "pixel shaders".
Кодексът предвижда 1570 функции, свързани с OpenGL:
 336  GL  functions
  51  GLU functions
  19  WGL functions
1164  extensions
Кодът предлага някои алтернативни варианти на 1570 функции с различни видове параметър, за удобство.
Кодексът определя повече от 3244 константи за OpenGL.
Кодексът дава възможност да имате няколко OpenGL рисунка контексти, всички animating независимо, по всяко "Form".
Кликването върху "CSGL12Control" тя дава "принос фокус," позволяващ последващо клавиатура и мишка колело въвеждане.  Курсор кликвания и движения се получават, когато курсорът е в рамките на правоъгълна площ на един екземпляр на "CSGL12Control".
Кодът включва функции, да се демонстрира как да се направят някои OpenGL общи задачи в C# и .NET.
Кодът изброява всички OpenGL константи и функции по азбучен ред в "class GL" в "GL.cs", което прави лесно да се определи дали някоя константа или функция липсва (което е малко вероятно, с изключение на разширения прие след години 2007).
Примерът програми покажа как се прави GDI+ съставяне на Bitmap, и след това как да се копират, че Bitmap до OpenGL текстура.
Това дава възможност на текст и други GDI+ съставяне способности да допринесат за една OpenGL сцена.
В GDI+ Bitmap може да бъде актуализиран и качен на един OpenGL текстура толкова често, колкото е веднъж OpenGL рамка.
Примерът програми покажа как да избират измежду няколко различни "pixel shader programs" докато програмата работи.
Примерът програми покажа как да пиша OpenGL буфери за имидж файлове (JPG, BMP, GIF, PNG).
Прес Shift + 0 (Shift-Zero), за да напишете OpenGL буфер за имидж файлове.
Примерът код показва как "GL.cs" в съставянето на DLL файл, след което добави, че DLL файл към друг проект, може да се предотврати Microsoft код редактори (например, Microsoft Visual C# 2008 Express Edition, и т.н.) с "IntelliSense" (контекстно-чувствителни код на проекта) от стават често и постоянно неотзивчив (неколкократно прекъснете за много секунди, което прави напълно неизползваеми редактор).  Като файла "GL.cs" пряко включени в проект, който се променя с Microsoft код редактор не е практичен, освен ако човек има желание да издържите мудността на редактор.  Този проблем е засегнат Microsoft Visual Studio 2003, 2005, 2008 и вероятно ще повлияе на 2010 версия, също. 
Примерът код демонстрира използването на множество копия на "CSGL12Control" по "Form".
Примерът код включва код, за да направи 3D "проява" че roams десктопа на Windows.

5. Пример програми с включени "CSGL12"

5.1 "CSGL12DLL"

Проектът на име "CSGL12DLL" произвежда DLL файл на име "CSGL12DLL.dll" който съдържа "class GL" (определена в C# файл "GL.cs").
Поставянето на "class GL" при един DLL файла и след това, че използвате DLL в други проекти, които използват "class GL", помага за избягване на екстремни проблем с всички Microsoft код редактори с IntelliSense функция.  Използване на C# файл GL.cs директно в проект ще предизвика Microsoft кода редактор с IntelliSense функция, за да стане напълно неизползваем несъчувствен и почти непрекъснато се дължи на неефективност на IntelliSense функция (както и факта, че IntelliSense очевидно блокира основната програма темата на редактора ). 
Ако използвате C# код редактор, който не е произведен от Microsoft (напр.  "SharpDevelop", "MonoDevelop", и т.н.), тогава можете просто да включват файл "GL.cs" пряко в своите проекти, а вие ще се очаква да получат някаква полза от използването на "CSGL12DLL.dll". 

5.2 "CSGL12Control"

Проектът на име "CSGL12Control" произвежда DLL файл на име "CSGL12Control.dll" който съдържа "class CSGL12Control" (определена в C# файл "CSGL12Control.cs").
Поставянето на "class CSGL12Control" при един DLL файл позволява на този "Control" (т.е.  клас, получен от "System.Windows.Forms.Control"), за да бъдат добавени към "Toolbox" на Microsoft Visual C# 2008 Express Edition (и подобни C# редактори).  Като "CSGL12Control" в "Toolbox" го прави лесен за да може човек да добавите инстанция на "CSGL12Control" до "Form" в "Designer" (например, човек може просто да използвате курсора изберете и плъзнете копие на "CSGL12Control" от "Toolbox" до "Form"). 
В "CSGL12Control" обект управлява една OpenGL рисунка контекст.  Множество копия на "CSGL12Control" могат да съжителстват в "Form".

5.3 "CSGL12Example1"

Проектът на име "CSGL12Example1" води до изпълнимия програмен файл (EXE) име "CSGL12Example1.exe".  Програмата използва "CSGL12DLL.dll" и "CSGL12Control.dll" за показване копие на CSGL12Control и нарисувате куб с OpenGL.
Програмата демонстрира използването на четири различни "pixel shaders" "(fractal, тухла, дърво," и "карикатура)." 
Програмата също така демонстрира използването на "GDI+", A .NET рисунка библиотека, за да съставят текст и други форми на "Bitmap" обект (а "GDI+" обект), а след това да копирате данните от снимката, че "Bitmap" до "texture" в OpenGL, като по този начин позволява на изображението, изготвени от "GDI+" да се яви в OpenGL рисуване.  Тази способност е много полезна, защото OpenGL липсват много от 2D рисунка функции в "GDI+" и подобни 2D изготвянето libaries.

5.4 "CSGL12Example2"

Проектът на име "CSGL12Example2" води до изпълнимия програмен файл (EXE) име "CSGL12Example2.exe".  Програмата използва "CSGL12DLL.dll" и "CSGL12Control.dll" за показване на два случая на CSGL12Control, всяка от които обръща един куб използвайки OpenGL.
Програмата разполага с "SplitContainer" "Control" върху "Form".  Всяка от двете части на "SplitContainer" съдържа копие на CSGL12Control.  По този начин човек може да коригира позицията на разделението между двете копия на CSGL12Control.  Това доказва гъвкавостта на CSGL12Control.
Един от случаите на CSGL12Control изпраща събития до набор от събитието хендлери в случай на "CSGL12Example2Handler1.cs", който използва същия код като "CSGL12Example1Handler.cs" в "CSGL12Example1" пример проект.  По тази причина, един от случаите, CSGL12Control обръща един куб с един "pixel shader" избрани измежду четири часа на разположение "pixel shaders". 
Другият случай на CSGL12Control събития изпраща до набор от събитието хендлери в случай на "CSGL12Example2Handler2.cs", което привлича един куб използвате текстура изображение (или на "шахматна дъска" модел, ако графичен файл на име "image.jpg" не е намерен). 

5.5 "CSGL12Avatar"

Проектът на име "CSGL12Avatar" води до изпълнимия програмен файл (EXE) име "CSGL12Avatar.exe".  Програмата използва "CSGL12DLL.dll" и "CSGL12Control.dll" да нарисувате куб с OpenGL на "Form" без граници, с цветовете на базата на прозрачност активиран, за да нарисувате 3D "проява" че roams на Windows Desktop област.
Движещите avatar може да се кликнахте и влачат на ново място с помощта на курсора.  Щракнете два пъти върху avatar ще направи изчезват.  Въпреки, че кода просто привлича един куб, OpenGL могат да бъдат използвани за изготвяне други неща. 
Множество случаи на "проява" на програмата може да бъде стартиран.  По този начин, много независими "въплъщение" случаи могат едновременно поскитвам Windows на работния плот.  Това е забавно.  Един експерт C# програмист може да се насладите намиране на начини да се координира дейността на много такива "въплъщение" случаи. 
За съжаление, скоростта, с която Window обект с прозрачността се обновява на екрана е много по-бавен от скоростта, с която OpenGL да рисувам.  В "въплъщение" актуализации само 10 пъти в секунда.  Аз не знам дали това може да бъде подобрено. 

5.6 "CSGL12BuiltExecutableExamplesForReference"

Директорията на име "CSGL12BuiltExecutableExamplesForReference" съдържа DLL файлове и файлове EXE произведени от всички примера проекти.  Тези файлове са предвидени като позоваване, така че файловете, може да се тестват веднага, дори и ако лицето не притежава способността да се събира на различни проекти от предоставената C# код.

5.7 "CSGL12UsefulCode"

Директорията на име "CSGL12UsefulCode" съдържа C# файлове, които биха могли да бъдат полезни за хората, които искат да направят общоприета рисунка операции с OpenGL.  Директорията включва също DLL файлове "CSGL12DLL.dll" и "CSGL12Control.dll" за удобство.
Кодът в тази директория class определя различните видове, като например Color4f, Vector3f, Matrix4x4f, Triangle, Mesh, ImageData, Texture, ShaderProgram и др  Кодът е достатъчно ефективна, но кодът е предназначена само за да вдъхновяват хората да развиват своите собствени реализации.

6. CSGL12 файлове

В "CSGL12" събиране на C# компютърен код файлове включва файлове, показани в следната схема:
csgl12_files.png
В "CSGL12" събиране на C# компютърен код файлове включва файлове, показани в тази схема.
В "CSGL12" софтуер включва проекти, които да създадат две DLL файлове ("CSGL12DLL.dll" и "CSGL12Control.dll") е показано на диаграмата.  Тези два DLL файлове могат да бъдат създадени, за да го направи и по-удобен за създаване на програми, които използват OpenGL, но също така е възможно да се създават програми, като се използват само за C# файлове директно.

7. "namespace CSGL12" и "class" видове

В "CSGL12" събиране на C# компютърен код файлове определя "namespace CSGL12" и "class" видове показани в следната схема:
csgl12_namespace_and_classes.png
В "CSGL12" събиране на C# компютърен код файлове определя "namespace CSGL12" и "class" видове, посочени в тази схема.
Програма, която прави OpenGL чертеж може да бъде създаден, като се използват само "class GL" (използване на C# файл GL.cs пряко, или чрез използване на DLL файл CSGL12DLL.dll, който също съдържа "class GL").  Въпреки това, като се използва "class CSGL12Control" (чрез използване на C# файл CSGL12Control.cs директно, или чрез използване на DLL файл CSGL12Control.dll който също съдържа "class CSGL12Control") прави добавянето OpenGL съставяне на Form (System.Windows.Forms.Form) лесно и удобно.
В C# класове Color4f, CSGL12Support, ImageData, ..., в долната част на схемата се предлагат само за удобство.  Тези упражнения правят по-лесно да се създадат програми, които се изготвят чрез OpenGL.  Въпреки това, може би вече са упражнения, които извършват дейности в тези класове, или можете да изберете да създадете подобни упражнения, които извършват операции по различен начин, или по-ефективно.  Тези упражнения се предлагат като примери на определен код проектиране и изпълнение. 

8. Използвайки едно "CSGL12Control" по System.Windows.Forms.Form

8.1 Програма структура

Следната диаграма показва как една програма с System.Windows.Forms.Form може да се използва единен "CSGL12Control" да направя рисунка с OpenGL.  Диаграмата показва различните CSGL12 файлове, използвани за изграждане на програмата.
csgl12_windows_form_program.png
Програма, с една единствена "CSGL12Control" по System.Windows.Forms.Form

8.2 Използването Microsoft Visual C# да създаде програма

(1) Старт Microsoft Visual C#.
(2) В менюто изберете "File" -> "New Project...".
(3) В "New Project" диалогов прозорец, който се появява, изберете "Windows Forms Application", и изберете име за участие в програмата и натиснете "OK".
(4) Незабавно записване на "Solution" като изберете "File" -> "Save All".  Диалогов прозорец със заглавие "Save Project" ще се появи, ви дава възможност да зададете име на проекта, директорията местоположение, както и "решение" за името на проекта.  Запомни директорията място, така че да са готови за следващата инструкция.  Натиснете бутона, за да спаси "Save" проекта.
(5) Копирайте всички файлове от директорията "CSGL12UsefulCode" в "CSGL12" софтуер в директорията, съдържаща файлове с изходен код на нов проект (т.е.  директорията, съдържаща файлове "Form1.cs", "Form1.Designer.cs", "Program.cs" и т.н.), така че файловете "CSGL12DLL.dll", "CSGL12Control.dll", "Color4f.cs" , "CSGL12Support.cs" и т.н., са заедно с нов проект файлове "Form1.cs" и др
(6) В Microsoft Visual C#, добавете "CSGL12" C# файлове към проекта.  В менюто изберете "Project" -> "Add Existing Item...", а в "Add Existing Item" диалоговия прозорец изберете всички от C# файлове от CSGL12 софтуер ("Color4f.cs", "CSGL12Support.cs", "ImageData.cs", ...).
(7) В Microsoft Visual C#, добавете "препратките" към DLL файлове "CSGL12DLL.dll" и "CSGL12Control.dll".  В менюто изберете "Project" -> "Add Reference...", а в "Add Reference" диалоговия прозорец изберете "Browse" табулатор и изберете файловете "CSGL12DLL.dll" и "CSGL12Control.dll" от проекта Източник файл указател, и натиснете "OK". 
(8) В Microsoft Visual C#, добавете "CSGL12Control" към "Toolbox".  В менюто изберете "Tools" -> "Choose Toolbox Items...".  В "Choose Toolbox Items" диалоговия прозорец, който се появява, натиснете бутона "Browse...", и отидете в директорията проекта с изходния код на файлове и изберете "CSGL12Control.dll".  Натиснете бутона "OK".
(9) В Microsoft Visual C#, да разглеждат "Toolbox".  В менюто изберете "View" -> "Toolbox".  В "Toolbox", отидете на раздела на име "General", и намерете статията на име "CSGL12Control".  Използване на курсора, щракнете върху елемента, на име "CSGL12Control" и плъзнете до "Form" в "Design" гледка. 
(10) В Microsoft Visual C#, в "Form" "Design" панорама, преместете "CSGL12Control" инстанция относно "Form" и коригирате неговата ширина и височина.  В "Properties" панел, задаване на "Anchor" стойност да се включат "Top, Bottom, Left, Right", ако искате да промените размера на контрол в съответствие с промените в програмата прозорец размер.
(11) В Microsoft Visual C#, промяна на проекта свойства, така че да можете да използвате "unsafe" код.  В менюто изберете "Project" -> "[project] Properties...".  Изберете диалоговия прозорец, който се появява, изберете раздела на име "Build" и проверка отметката име "[X] Allow unsafe code".  Затваряне на проекта свойства диалоговата кутия.
(12) В Microsoft Visual C#, добавете нов C# файл към проекта.  В менюто изберете "Project" -> "Add New Item...".  В диалоговия прозорец на име "Add New Item", изберете шаблон "Class" име, и изберете име за новия клас тип, като например "CSGL12MyHandler.cs", и след това натиснете бутона "Add".  Вижте примера проект на име "CSGL12Example1", в името на файла "CSGL12Example1Handler.cs", като пример за това как кода на "CSGL12MyHandler.cs" трябва да бъдат написани. 
(13) В Microsoft Visual C#, в "Solution Explorer", кликнете върху "Form1".  В менюто изберете "View" -> "Code" (или натиснете F7, или кликнете с десния бутон върху "Form1" и избирате "View Code".  Кодът в досието "Form1.cs" ще се появят в редактор.  Промяна на кода във файла "Form1.cs" да бъдат сходни с кода във файла "CSGL12Example1Form.cs" в проекта "CSGL12Example1" включени в "CSGL12" софтуер.  По-специално, създаване на променлива за копие на вашия случай секундант клас (напр.  "CSGL12MyHandler"), а след това добавете методи на този клас например по случай хендлери за различните прояви на копие на "CSGL12Control" върху "Form". 
(14) В Microsoft Visual C#, съставяне и изпълнение на програмата.  Ако желаете да споделите в програмата, трябва да включва двете DLL файлове ("CSGL12DLL.dll" и "CSGL12Control.dll") с изпълнимия файл (*.exe). 
Ако Вие сте експерт C# програмист, тогава можеш да се избегне необходимостта да разпространявате DLL файлове ("CSGL12DLL.dll" и "CSGL12Control.dll") с вашия изпълнимия (*.exe).
Копиране на файловете "GL.cs", "CSGL12Control.cs", и "PrecisionTime.cs" от проектите, на име "CSGL12DLL" и "CSGL12Control" в "CSGL12" софтуер за източника директория на текущия си проект.  Добавяне на файлове "GL.cs", "CSGL12Control.cs", и "PrecisionTime.cs" на вашия проект, така че те са съставени директно в програмата.  Не са препратки към "CSGL12DLL.dll" и "CSGL12Control.dll" в проекта. 
Погледни в "CSGL12Example1" проект в "CSGL12" софтуер и погледни на кода в рамките на файлове, наречена "CSGL12Example1Form.cs" и "CSGL12Example1Form.Designer.cs" да видим какво код е необходимо да се създаде и инициализиране копие на "CSGL12Control" по "Form".  Добави подобна "Form1.cs" код, за да и "Form1.Designer.cs" ръчно да създавате и инициализиране копие на "CSGL12Control" в "Form". 
Тази процедура е много неприятен и изисква опит и внимателни грижи, но в резултат на изпълнимия (*.exe) няма да изискват "CSGL12DLL.dll" или "CSGL12Control.dll".  Много е хубаво да бъде в състояние да споделят своя софтуер под формата на един единствен изпълним файл (*.exe), без да се изискват други файлове.

8.3 Добавянето на "препратки" към CSGL12DLL.dll и CSGL12Control.dll

Този раздел включва изображения на използване Microsoft Visual C# 2008 Express Edition да добавите "референции" към DLL файлове CSGL12DLL.dll и CSGL12Control.dll с проекта.
В менюто изберете "Project" -> "Add Reference...".  Или, щракнете с десния бутон върху елемента "References" в "Solution Explorer" панел и изберете "Add Reference...", както е показано в следната изображение. 
adding_references_001.png
Контекстното меню за "References" точка в "Solution Explorer", показващ "Add Reference..."  опция
След като изберете опцията "Add Reference...", диалогова кутия "Add Reference" име ще се появи.  В този диалогов прозорец изберете "Browse" табулатор и изберете DLL файлове "CSGL12DLL.dll" и "CSGL12Control.dll", както е показано в следната снимка, а след това натиснете бутона с надпис "OK". 
adding_references_002.png
В раздела "Browse" на "Add Reference" диалоговия прозорец с DLL файлове "CSGL12DLL.dll" и "CSGL12Control.dll" двете избрани
След натискане на бутона с надпис "OK", на "Add Reference" диалоговия прозорец ще изчезне, а DLL файлове "CSGL12DLL.dll" и "CSGL12Control.dll" ще се появят в "References" клон в "Solution Explorer", както е показано в следната схема.
adding_references_003.png
В DLL файлове "CSGL12DLL.dll" и "CSGL12Control.dll" в "References" клон в "Solution Explorer"

8.4 Добавянето CSGL12Control към Toolbox в Microsoft Visual C# 2008 Express Edition

Този раздел включва изображения на използване Microsoft Visual C# 2008 Express Edition да добавите CSGL12Control към "Toolbox" така, че човек може лесно да добавите копия на CSGL12Control до "Form" в "Designer" (Shift+F7 по подразбиране).
В менюто изберете "View" -> "Toolbox".  В "Toolbox", отидете на раздела на име "General", както е показано в следната изображение.
adding_control_to_toolbox_001.png
В "General" секция на "Toolbox"
Щракнете с десния бутон някъде в рамките на "Toolbox".  Изберете опцията "Choose Items..."  в контекстното меню, което се появява, както е показано в следната изображение.
adding_control_to_toolbox_002.png
Опцията "Choose Items..."  в контекстното меню за "Toolbox"
Освен това, в менюто, изберете изберете "Tools" -> "Choose Toolbox Items...".
В "Choose Toolbox Items" диалогов прозорец трябва да се появи, както е показано в следната изображение.
adding_control_to_toolbox_003.png
В диалоговия прозорец "Choose Toolbox Items"
В "Choose Toolbox Items" диалоговия прозорец, натиснете бутона "Browse".  В "Open" диалоговия прозорец, който се появява, изберете DLL файл "CSGL12Control.dll", както е показано в следната снимка, а след това натиснете бутона "OK". 
adding_control_to_toolbox_004.png
В "Open" диалоговия прозорец с DLL файл "CSGL12Control.dll" избрани
В "CSGL12Control" точка трябва да се появи в диалоговия прозорец "Choose Toolbox Items", както е показано в следната изображение.  Натиснете бутона "OK".
adding_control_to_toolbox_005.png
В "CSGL12Control" т.  сега се появява в диалоговия прозорец "Choose Toolbox Items"
В "CSGL12Control" точка трябва да се появи в "Toolbox", както е показано в следната изображение. 
adding_control_to_toolbox_006.png
В "CSGL12Control" т.  сега се появява в "Toolbox"

8.5 Добавянето CSGL12Control до "Form" чрез използване на "Toolbox"

Този раздел включва изображения на използване Microsoft Visual C# 2008 Express Edition да добавите копие на CSGL12Control до "Form" с помощта на "Toolbox". 
В менюто изберете "View" -> "Designer" (Shift+F7 по подразбиране).  Или, двукратно щракнете върху "Form*.cs" файл в "Solution Explorer".  Или с десен бутон на мишката щракнете върху файла "Form*.cs" в "Solution Explorer" и изберете "View Designer".  Използването на един от тези три метода на "Designer" прозореца за "Form" трябва да се появи.
В менюто изберете "View" -> "Toolbox".  В "Toolbox", отидете на раздела на име "General".  Един елемент "CSGL12Control" име трябва да се появи там, както е показано в следната изображение. 
adding_control_to_toolbox_006.png
В "CSGL12Control" би трябвало вече да са в "Toolbox"
Използване на курсора, щракнете върху елемента, на име "CSGL12Control" и плъзнете до "Form" в "Designer".  Един случай на "CSGL12Control" да се появи на "Form", както е показано в следната изображение. 
adding_control_to_toolbox_007.png
Един случай на "CSGL12Control" по "Form" в "Designer"
В "Form" "Designer" панорама, местете с копие на "CSGL12Control" на "Form" и да коригирате нейната ширина и височина. 
Кликнете върху копие на "CSGL12Control" на "Form" за да я изберете.  Тогава, в "Properties" панел, задаване на "Anchor" стойност да се включат "Top, Bottom, Left, Right" така, че размерът на "CSGL12Control" ще се променят в отговор на промените в размера на програмния прозорец.  Може също да искате да смените променливата име (т.е.  стойността за "(Name)") за копие на "CSGL12Control" от автоматичен по подразбиране (напр.  "csgL12Control") на нещо подходящо за Вашия код (напр.  "mCSGL12Control" или "mCSGL12Control1" и др.) 
Следното изображение показва "Form" "Designer" оглед и "Properties" панел.
CSGL12Control_ScreenImage.png
Един случай на CSGL12Control по Form в Designer и "Properties панел

9. , Като се използват две копия на "CSGL12Control" по System.Windows.Forms.Form

Следната диаграма показва пример за това как два случая на "CSGL12Control" могат да бъдат добавени към System.Windows.Forms.Form да направя рисунка с OpenGL в програмата.
csgl12_windows_form_program_with_two_controls.png
А програмата, като се използват две копия на "CSGL12Control" по System.Windows.Forms.Form
Следвайте инструкциите в предишния раздел, за да добавите един единствен екземпляр на "CSGL12Control" към "Form".  След това само трябва да плъзнете втори екземпляр на "CSGL12Control" от "Toolbox" към "Form" да добавите втора "CSGL12Control". 
Всяко копие на "CSGL12Control" ще имат своя собствена променлива име.  Всяко копие на "CSGL12Control" може да има своя собствена, свързани събитие секундант клас, или да използвате отделни копия на един треньор клас тип. 
Проучване пример проект "CSGL12Example2" да научите как два случая "CSGL12Control" могат да имат свои събития изпращат две отделни копия на потребителски събитие секундант упражнения с различни OpenGL съставяне функции. 
Примерната програма "CSGL12Example2" е всяко копие на "CSGL12Control" в "SplitContainer" "Control", просто един начин да се докаже в кои от случаите на "CSGL12Control" може да се използва.  Обаче, копия на "CSGL12Control" може вместо да бъдат поставени директно към "Form". 

10. Пример C# код за "Form" с копие на CSGL12Control

Това е пълния C# кода, съдържащи се в досието "CSGL12Example1Form.cs", която е част от програма, например "CSGL12Example1". 
Този код е представен тук като прост пример за това как копие на CSGL12Control могат да бъдат създавани и използвани от "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);
        }




    }




}
Забележете, че членът променлива "mCSGL12Example1Handler" е обявена за да се позова на случай на class име "CSGL12Example1Handler".  Този клас ще бъдат описани в следващите раздел на този документ.  Забележете, че на строителя за "CSGL12Example1Form" добави методите на копие на "CSGL12Example1Handler" към "multicast delegates", свързани с различни събития, генерирани от копие на "CSGL12Control".  Това означава, че когато например на "CSGL12Control" генерира различни събития, тези събития ще предизвика различни методи на инстанция на "CSGL12Example1Handler" (т.е.  "mCSGL12Example1Handler"), за да бъде използвана.
Забележете, че членът променлива "mTimer" е обявена за да се позова на случай на class име "System.Windows.Forms.Timer".  Тази цел се използва, за да се позове функция "PrivateTimerTickEventHandler" име на всеки 10 милисекунди.  Функцията на име "PrivateTimerTickEventHandler" разговори метод на копие на "CSGL12Control" (т.е.  "mCSGL12Control1"), който причинява този "Control" да се изготвят само себе си.  Това е начинът, копие на "CSGL12Control" могат анимирани с приблизителна скорост.
Само част от дефиницията на "class CSGL12Example1Form" появява в C# файл на име "CSGL12Example1Form.cs".  Друга част от дефиницията на "class CSGL12Example1Form" появи в C# файл на име "CSGL12Example1Form.Designer.cs".  Въпреки, че файлове с имена, отговаряща на модела "*.Designer.cs" са създадени и променени само от графичните "Form Designer" прозореца на C# редактор, че също така е възможно да се създават и променят C# тези файлове с помощта на текстов редактор. 
Това е пълния C# кода, съдържащи се в досието "CSGL12Example1Form.Designer.cs", която е част от програма, например "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(1212);
            this.mCSGL12Control1.Name = "mCSGL12Control1";
            this.mCSGL12Control1.Size = new System.Drawing.Size(640480);
            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(664504);
            this.Controls.Add(this.mCSGL12Control1);
            this.Name = "CSGL12Example1Form";
            this.Text = "CSGL12Example1";
            this.ResumeLayout(false);

        }

        #endregion

        private CSGL12.CSGL12Control mCSGL12Control1;
    }
}
Забележете, че този код C# съдържа декларация на променлива "mCSGL12Control1", който се позовава на копие на "class CSGL12.CSGL12Control" (т.е.  "class CSGL12Control" в "namespace CSGL12").  Този случай е създаден и конфигуриран във функцията "InitializeComponent". 

11. Обработка на събития, използвана от копие на CSGL12Control

Предишният раздел показа C# код за "Form" тази, която се съдържа един единствен екземпляр на "CSGL12Control".  В C# код добави методите на "class" име "CSGL12Example1Handler" като събитие хендлери за различни събития, генерирани от копие на "CSGL12Control". 
Ето и списък с интересни събития от "CSGL12Control" и "delegate" видове, свързани с тези събития:
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
Само "OpenGLStarted" събитие е събитие, вид, специфични за "CSGL12Control".
Всички други събития са стандартни System.Windows.Forms събития, чийто случай касовите трябва да има определени параметри (всеки Forms, посочени в документацията).
В "OpenGLStarted" и "Paint" събития са най-важните събития за OpenGL рисуване.
В "OpenGLStarted" случай е използвана преди първа по рода си събитие "Paint" е използвана.
Следователно, "OpenGLStarted" събитие handler трябва да бъде добавен към контрола преди контрол има възможност да се опитаме да рисуваш себе си, в противен случай, един път случай няма да бъде получен.
Това събитие е само за удобство и може да бъде игнориран.
Въпреки това, добавянето на handler за това събитие дава възможност за handler код, за да направите някои еднократно инициализационния, че зависи от OpenGL е готов за работа.
(OpenGL не могат да бъдат използвани до прозореца, съществува и през прозореца е готова да изпълнява първия си боя.
Така че, в случай "OpenGLStarted" пренасочване на програмист от риска при опит да се използват OpenGL твърде скоро след началото на програмата.
) Това е доста лесно да се добави логика в "Paint" треньор да направя едно време initialization, използвайки OpenGL контекста на "CSGL12Control".
В случай, "OpenGLStarted" се предлага за удобство.
Това е пълния C# кода, съдържащи се в досието "CSGL12Example1Handler.cs", която е част от програма, например "CSGL12Example1". 
Този код е представен тук като прост пример за това как събития, генерирани от копие на "CSGL12Control" да се работи за изготвяне използвайки 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(512512, 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(64128128140));
        }
















        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(00, 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(0Color.White));


                    g.FillEllipse(mBrush1, new Rectangle(00256256));
                    g.FillEllipse(mBrush1, new Rectangle(256256256256));

                    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;
        }




    }




}
Забележете, че функцията на име "OpenGLStarted" се използва в този пример за да създадете "pixel shader programs" и OpenGL текстура.  По тази програма, ние само трябва да се създадат тези ресурси веднъж, и то е по-ефективно да се създаде само веднъж. 
Забележете, че функцията на име "OpenGLStarted" кода проверки, ако WGL "extension" функция, наречена "wglSwapIntervalEXT()" съществува, и ако тази функция съществува, кодът се позовава тази функция.  Тази функция е отправна заявяват, че се отразява на функционирането на програмата за цялата сесия, и така ние се нуждаем само повикване тази функция веднъж, поради което ние опит да се обадя, че функцията на "OpenGLStarted" функция (която е използвана само веднъж, когато OpenGL се стартира за конкретен "CSGL12Control", като се приема че сме добавили "OpenGLStarted" метод за съответния случай делегат).
Функцията на име "Paint" съдържа всички по-код, за да изготвят единна "рамка" на анимация използвайки OpenGL.  В "Paint" функция, ще се нарече може би 60 пъти в секунда, което се дължи на факта, че свързаните с "CSGL12Control" например е "обезсилило" (принудени да съставят самата отново) в този курс.  (Виж по "Form" код например в предишния раздел, за да видите таймер, която определя размера на "недействителност" и действителната функция разговор, който води в случай на "CSGL12Control" да стане "анулирана.)" 
Всички OpenGL функции се ползва като се използва например от "class GL" (пример: gl.gl*()).  В случай на "class GL" е придобито от копие на "CSGL12Control", което е имплицитно съхраняват в първия параметър за "Paint" функция.
Всички OpenGL константи могат да бъдат уточнени, като посочите "class" име "GL", последван от една точка и името на постоянна; т.е.  "GL.GL_TRIANGLES".
В OpenGL код в този пример не е напълно очевидно и лесно за разбиране, но се надяваме, че Вие можете да признае това как може да бъде модифициран за вашите собствени нужди.

12. Проверка за наличие на "разширение" функция на OpenGL

Просто проверете дали булевото флаг със същото име като OpenGL функция е "вярна," преди да се опитват да използват съответните функции.
В булевото променлива има име, което започва с "b", последвана от 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.

    // . . .
}
Проверка е необходимо за "разширението" функции.
OpenGL 1.1 функции, както и всички GLU функции и основни WGL функции, не се нуждаят от такава проверка.  Въпреки това, булевото знамена съществуват, и са представени по подходящ начин, за всички тези функции, предоставени от "class GL", включително основните OpenGL 1.1 функции.  По този начин, има един последователен начин, за да се провери наличието на всички функции в този клас. 
Знаейки това дали не е функция е "разширение" е отговорност на програмист.
Въпреки това, функция име суфикси, като "EXT", "ARB", "MESA", "NV" (NVidia), "APPLE" и т.н., да посочи разширяването функции.
Ако една функция "gl*()" има съседни функция "gl*ARB()" или "gl*NV()," тогава функцията "gl*()" вероятно е разширение (що се отнася до Windows OPENGL32.DLL е засегната).
Единственото предимство на знае дали има или няма функция е "разширение" (по отношение на Windows OPENGL32.DLL) е в състояние да избегне проверката, ако функции са на разположение.
Можете да търсите за всички OpenGL функциите, използвани в кода, след което изгради в списъка по азбучен ред на различните функции използват.
Тогава, в началото на вашата програма, след CSGL12Control призовава OpenGLStarted делегат, трябва само да провери всички булевото знамена за всички функции, които възнамерявате да използвате.
Ако решите да прекрати програмата, ако има "такива, необходими" функции са изчезнали, а след това всички проверки за такива функции в кода могат да бъдат премахнати.
Също така, можете да образуват групата на несъществени функции в проверката, и евентуално информира потребителя за всяка функция промени, а вероятно и оставете проверки, разпръснати в целия код.
С повече OpenGL опит, можете да получите на чувство за какво са свързани с разширения (примери: Снимки, shaders, буферите, компресия, ...).
Поради това, можете да проверите за наличие на една единствена функция и критично използване на тази информация, за да решите дали цялата подмножество е вероятно да бъде налице.

13. Скорост

По различни причини, C# е по-бавен от non-CLR C/C++.
C# накрая се съставят до родния асемблер, просто като за C/C++, но благодарение на уверенията, направени от C# език и .NET CLR, общата скорост на софтуер, изграден върху C# и .NET е малко по-бавен, отколкото чрез вграден софтуер non-CLR C/C++.
Ето защо, се възможно най-високата скорост означава използване non-CLR C/C++ вместо C#.
Освен това, тъй като призовава всички родом от библиотеката C# включва P/Invoke, призовавам функции, като например OpenGL функции ще изисква известно време за извършване на работа в P/Invoke слой.
Независимо от това, "CSGL12" изглежда да работи достатъчно бързо да се използва за много реално време графични цели, например за прости игри, 3D зрителите, редактори, или 3D презентации.  Това е особено вярно, ако по-голямата част от работата се извършва от GPU вместо в CPU.

14. Сравнение между "CSGL12" и "Tao Framework"

В "Tao Framework" е голяма C# / .NET библиотека, който осигурява интерфейс за много библиотеки с отворен код, като OpenGL, OpenAL (аудио), SDL (а игрални / симулация платформа), Open Dynamics Engine (ODE) (физика) и др
В Tao Framework е кръст-платформа (Windows, Linux, Mac OS X).
"CSGL12" само предоставя интерфейс към OpenGL и е само за Windows операционна система.
В Tao Framework има общността.  Едно лице може да се възползва от общуването с други потребители на Tao Framework.
Въпреки това, може да има различни цели, за които "CSGL12" може да бъде по-лесно да се използва за Windows програми. 
colinfahey.com
Информация за контакти
English  Español  Português  Français  Italiano  Deutsch  Nederlands  Svenska  Dansk  Suomi  Norsk  Русский  Polski  Română  Български  Hrvatski  Česky  中国  中國  日本語  한국어  Ελληνική  हिन्दी  العربية