English  Español  Português  Français  Italiano  Deutsch  Nederlands  Svenska  Dansk  Suomi  Norsk  Русский  Polski  Română  Български  Hrvatski  Česky  中国  中國  日本語  한국어  Ελληνική  हिन्दी  العربية 
C# OpenGL interfaz
para el sistema operativo Windows
Colin Fahey
CSGL12Example1_ScreenImage.png
CSGL12Control en un Form, mostrando un “fractal” de sombreado de píxeles y GDI+ programa copiado al dibujo una textura
CSGL12Example2_ScreenImage.png
CSGL12Control dos casos en una Form, que muestra los programas de sombreado de píxeles y texturas
CSGL12Avatar_ScreenImage.png
Un avatar en 3D que vaga por el escritorio y se pueden mover con el cursor

1. Software

CSGL12_20090725.zip
CSGL12: C# OpenGL interfaz para Windows, versión 12
4170499 bytes
MD5: 30781a6570441785ea636f2ae1cd16ef

2. Todos los C# código de computadora en el C# OpenGL interfaz (CSGL12) está en el “dominio público”

Escribí todas las C# código C# OpenGL dentro de la interfaz (CSGL12).
Declaro que todos los C# código C# OpenGL dentro de la interfaz (CSGL12) a ser de “dominio público.”
Por lo tanto, el código puede ser usado para cualquier propósito (comercial o privado), sin pago, sin restricciones, sin obligaciones, y sin reconocer al autor original.
El código puede ser modificado, reutilizado o partes, sin restricciones, y sin obligaciones, y sin reconocer al autor original.
El ejemplo programas incluyen una pequeña cantidad de código de computadora (en concreto, “shader código de computadora) escrito por otras personas.”  Este código no está dentro de la propia interfaz y se pueden trivially eliminado.  Este código es simplemente para demostrar la simplicidad de uso de la interfaz para crear y utilizar “shader” programas. 

3. Introducción

“CSGL12” es una colección de archivos de código C# equipo que implemente una interfaz OpenGL a la biblioteca de gráficos (incluidas todas las extensiones de OpenGL hasta el año 2007) para el sistema operativo Windows.
El código C# archivos de la colección “CSGL12” hacer más fácil añadir OpenGL dibujo a cualquier C# / .NET software con un “Form” (una instancia de “System.Windows.Forms.Form”).
“CSGL12” la colección de archivos de código de ordenador incluye un archivo llamado “CSGL12Control.cs”, que define una clase llamada “CSGL12Control”, derivados de “System.Windows.Forms.Control”.  Cada instancia de “CSGL12Control” independiente OpenGL representa un área de dibujo.  Es muy fácil añadir varias instancias de CSGL12Control a un Form (una instancia de System.Windows.Forms.Form).

4. Características y requisitos de “CSGL12”

El código es sólo para Windows los sistemas operativos que soportan el .NET 2.0 Framework (Windows 2000, Windows XP, Windows Vista, Windows 7)
El código puede ser compilado usando “Microsoft Visual C# 2008 Express Edition” (un compilador gratuito), o similar C# compiladores.
El código exige que se está construyendo con la construcción de “[X] Allow unsafe code” opción seleccionada, de manera que optimiza las funciones de copiar datos de imagen se pueden utilizar.  Si usted es un experto programador C# será capaz de identificar fácilmente las porciones de código de la C# que requieren la opción “unsafe” y desactivarlo si se desea o requiere.  Los datos de la imagen de copia es de 10 veces más rápido utilizando el código “unsafe” que la alternativa, y es por ello tal código se usa.  Si usted construye un DLL que contiene todo el código “unsafe” y, a continuación, un proyecto que DLL usos que no requieren que se está construyendo con el “unsafe” opción, y por lo que puede inferir que la ausencia de la opción en un “unsafe” proyecto no implica ningún la seguridad (porque DLL numerosos archivos que se utilizan implícita o explícitamente por el programa contiene código “inseguro).” 
El código puede ser recopilada y utilizada por cualquiera de los siguientes:
Microsoft Visual C# 2008 Express Edition
Microsoft Visual Studio 2008
Microsoft .NET 3.5 SDK
SharpDevelop
Mono Project
El código ofrece más OpenGL extensiones (hasta el año 2007), incluyendo “vertex shaders” y “pixel shaders”.
El código establece 1570 funciones relacionadas con OpenGL:
 336  GL  functions
  51  GLU functions
  19  WGL functions
1164  extensions
El código ofrece distintas variantes de las funciones 1570 con diferentes tipos de parámetros, para mayor comodidad.
El código define más de 3244 constantes para OpenGL.
El código permite tener múltiples contextos OpenGL dibujo, animación de todos con independencia, en cualquier “Form”.
Al hacer clic en una “entrada” le da “CSGL12Control” “atención,” permitiendo posterior rueda del ratón y teclado de entrada.  Movimientos del cursor y los clics recibidos cuando el cursor se encuentra dentro de la zona rectangular de una instancia de “CSGL12Control”.
El código incluye funciones para demostrar cómo hacer algunas tareas comunes OpenGL en C# y .NET.
Todas las listas de códigos OpenGL constantes y las funciones en orden alfabético en “class GL” en “GL.cs”, por lo que es fácil determinar si alguna función es constante o desaparecidos (que es poco probable, a excepción de las extensiones después de aprobado el año 2007).
Los programas de ejemplo para mostrar cómo hacer GDI+ a punto de Bitmap y, a continuación, la forma de copia que Bitmap a un OpenGL textura.
De esta manera, texto y otros GDI+ aprovechando las capacidades para contribuir a un OpenGL escena.
El GDI+ Bitmap puede ser actualizado y subido a un OpenGL textura tan a menudo como una vez por OpenGL marco.
Los programas de ejemplo para mostrar cómo elegir entre varios diferentes “pixel shader programs” mientras que el programa se está ejecutando.
Los programas de ejemplo para mostrar cómo escribir OpenGL búferes a archivos de imagen (JPG, BMP, GIF, PNG).
Prensa Shift + 0 (cambio de cero) para escribir el buffer de OpenGL a archivos de imagen.
El código de ejemplo muestra cómo compilar “GL.cs” en DLL a un archivo y, a continuación, añadiendo que DLL archivo a otro proyecto, puede impedir que el código de los editores Microsoft (por ejemplo, Microsoft Visual C# 2008 Express Edition, etc) con “IntelliSense” (sensibles al contexto de código) de cada frecuencia y persistencia de que no (varias veces la pausa de varios segundos, haciendo el editor totalmente inutilizable).  Habiendo “GL.cs” directamente el archivo incluido en un proyecto que está siendo editada por un editor de código Microsoft no es práctico, a menos que una persona está dispuesta a soportar la lentitud del editor.  Este problema ha afectado Microsoft Visual Studio 2003, 2005, 2008, y probablemente afectará a la versión 2010, también. 
El código de ejemplo demuestra el uso de múltiples casos de “CSGL12Control” en un “Form”.
El código de ejemplo incluye código para hacer un “avatar” 3D que vaga por el escritorio de Windows.

5. Programas de ejemplo incluido con “CSGL12”

5.1 “CSGL12DLL”

El proyecto denominado “CSGL12DLL” produce un DLL archivo llamado “CSGL12DLL.dll” que contiene “class GL” (definidos en la C# archivo “GL.cs”).
“class GL” puesta en DLL a un archivo y, a continuación, utilizando DLL que en otros proyectos que utilizan “class GL”, ayuda a evitar un problema con la extrema Microsoft todos los editores de código con el IntelliSense función.  Uso de la C# archivo GL.cs directamente en un proyecto causaría Microsoft cualquier editor de código con la función para IntelliSense totalmente inutilizable y no responde casi continuamente debido a la ineficiencia de la IntelliSense función (y el hecho de que los bloques IntelliSense evidentemente el programa principal hilo del editor ). 
Si está usando un editor de código C# que no es producido por Microsoft (por ejemplo, “SharpDevelop”, “MonoDevelop”, etc), entonces usted puede simplemente incluir el archivo “GL.cs” directamente en sus proyectos, y es poco probable que obtener ningún beneficio de usar “CSGL12DLL.dll”. 

5.2 “CSGL12Control”

El proyecto denominado “CSGL12Control” produce un DLL archivo llamado “CSGL12Control.dll” que contiene “class CSGL12Control” (definidos en la C# archivo “CSGL12Control.cs”).
“class CSGL12Control” puesta en DLL a un archivo, que permite “Control” (es decir, una clase derivada de “System.Windows.Forms.Control”) que se añade a la “Toolbox” de Microsoft Visual C# 2008 Express Edition (y similares C# editores).  Habiendo “CSGL12Control” en el “Toolbox” hace fácil para que una persona que añadir una instancia de “CSGL12Control” a un “Form” en el “Designer” (por ejemplo, una persona puede simplemente utilizar el cursor para seleccionar y arrastrar una instancia de “CSGL12Control” de la “Toolbox” a un “Form”). 
El objeto “CSGL12Control” gestiona un dibujo OpenGL contexto.  Varias instancias de “CSGL12Control” pueden coexistir en un “Form”.

5.3 “CSGL12Example1”

El proyecto denominado “CSGL12Example1” produce un archivo de programa ejecutable (EXE) “CSGL12Example1.exe” nombre.  El programa utiliza “CSGL12DLL.dll” y “CSGL12Control.dll” para mostrar un ejemplo de CSGL12Control y dibujar un cubo utilizando OpenGL.
El programa demuestra el uso de cuatro diferentes “pixel shaders” “(fractal, ladrillo, madera,” y “de dibujos animados).” 
El programa también demuestra el uso de “GDI+”, una biblioteca .NET dibujo, extraer el texto y otras formas “Bitmap” a un objeto (una “GDI+” objeto) y, a continuación, copia los datos de la imagen de que “Bitmap” a un “texture” en OpenGL, lo que permite extraer la imagen por “GDI+” a aparecer en OpenGL dibujo.  Esta habilidad es muy útil OpenGL porque carece de muchas de las características de dibujo 2D encuentra en “GDI+” y similares 2D dibujo libaries.

5.4 “CSGL12Example2”

El proyecto denominado “CSGL12Example2” produce un archivo de programa ejecutable (EXE) “CSGL12Example2.exe” nombre.  El programa utiliza “CSGL12DLL.dll” y “CSGL12Control.dll” para mostrar dos casos de CSGL12Control, cada uno de los cuales señala a un cubo utilizando OpenGL.
El programa tiene un “SplitContainer” “Control” sobre la “Form”.  Cada una de las dos zonas de la “SplitContainer” contiene una instancia de CSGL12Control.  Así, una persona puede ajustar la posición de la división entre las dos instancias de CSGL12Control.  Esto demuestra la flexibilidad de la CSGL12Control.
Uno de los casos de eventos CSGL12Control envía a una serie de eventos en una instancia de “CSGL12Example2Handler1.cs”, que utiliza el mismo código “CSGL12Example1Handler.cs” como en el ejemplo “CSGL12Example1” proyecto.  Por lo tanto, uno de los casos CSGL12Control llama un cubo con una “pixel shader” seleccionada de entre cuatro disponibles “pixel shaders”. 
El otro ejemplo de eventos CSGL12Control envía a una serie de eventos en una instancia de “CSGL12Example2Handler2.cs”, que señala un cubo usando una textura de imagen (o un patrón de “tablero de ajedrez,” si un archivo de imagen con nombre “image.jpg” no se encuentra). 

5.5 “CSGL12Avatar”

El proyecto denominado “CSGL12Avatar” produce un archivo de programa ejecutable (EXE) “CSGL12Avatar.exe” nombre.  El programa utiliza “CSGL12DLL.dll” y “CSGL12Control.dll” para dibujar un cubo utilizando OpenGL a “Form” sin fronteras, con la transparencia de color en función activada, para dibujar un 3D “avatar” que vaga por la zona Windows escritorio.
El movimiento avatar puede hacer clic y arrastrar a una nueva ubicación utilizando el cursor.  Doble clic en el avatar hará desaparecer.  Aunque el código se basa simplemente un cubo, OpenGL se puede utilizar para sacar otras cosas. 
Varias instancias del “avatar” se puede iniciar el programa.  Por lo tanto, independiente “avatar” muchos casos al mismo tiempo puede vagar por las Windows escritorio.  Esto es divertido.  C# un experto programador puede disfrutar de encontrar maneras de coordinar la actividad de muchos de esos casos “avatar.” 
Lamentablemente, el tipo al que el objeto con transparencia Window se actualiza en la pantalla es mucho más lento que la velocidad a la que pueden recurrir OpenGL.  El “avatar” sólo actualiza 10 veces por segundo.  No sé si esto puede ser mejorado. 

5.6 “CSGL12BuiltExecutableExamplesForReference”

El directorio llamado “CSGL12BuiltExecutableExamplesForReference” contiene archivos DLL y EXE todos los archivos producidos por el ejemplo de los proyectos.  Estos archivos son siempre como referencia, de manera que los archivos pueden ser probados de inmediato, incluso si una persona no tiene la capacidad de compilar los distintos proyectos de la siempre C# código.

5.7 “CSGL12UsefulCode”

El “CSGL12UsefulCode” directorio llamado C# contiene archivos que pueden ser útiles a las personas que quieren hacer con las operaciones de dibujo comunes OpenGL.  El directorio también incluye la DLL archivos “CSGL12DLL.dll” y “CSGL12Control.dll” por conveniencia.
El código en el directorio que define class diversos tipos, tales como Color4f, Vector3f, Matrix4x4f, Triangle, Mesh, ImageData, Texture, ShaderProgram, etc  El código es razonablemente eficiente, pero el código es sólo la intención de inspirar a la gente a desarrollar sus propias aplicaciones.

6. CSGL12 archivos

“CSGL12” la colección de archivos de código C# equipo incluye los archivos que se muestran en el siguiente diagrama:
csgl12_files.png
“CSGL12” la colección de archivos de código C# equipo incluye los archivos que se muestran en este diagrama.
“CSGL12” El software también incluye proyectos para la creación de los dos archivos DLL (“CSGL12DLL.dll” y “CSGL12Control.dll”) se muestra en el diagrama.  DLL esos dos archivos se pueden crear para que sea más conveniente para crear los programas que utilizan OpenGL, pero también es posible crear programas usando sólo la C# archivos directamente.

7. “namespace CSGL12” y “class” tipos

“CSGL12” la colección de archivos de código C# ordenador define “namespace CSGL12” y la “class” tipos de muestra en el siguiente diagrama:
csgl12_namespace_and_classes.png
“CSGL12” la colección de archivos de código C# ordenador define “namespace CSGL12” y la “class” tipos de muestra en este diagrama.
Un programa que hace OpenGL dibujo se pueden crear utilizando únicamente “class GL” (utilizando el C# archivo GL.cs directamente, o utilizando el DLL archivo CSGL12DLL.dll que también contiene “class GL”).  Sin embargo, el uso “class CSGL12Control” (utilizando el C# archivo CSGL12Control.cs directamente, o utilizando el DLL archivo CSGL12Control.dll que también contiene “class CSGL12Control”) hace añadiendo OpenGL dibujo a un Form (System.Windows.Forms.Form) fácil y conveniente.
El C# clases Color4f, CSGL12Support, ImageData, ..., en la parte inferior del diagrama se ofrecen sólo por conveniencia.  Aquellas clases que sea más fácil para crear programas que dibujar usando OpenGL.  Sin embargo, usted puede ser que ya tienen las clases que realizan las operaciones en las clases, o puede optar por crear clases similares que llevan a cabo las operaciones de forma diferente o más eficiente.  Las clases se ofrecen como ejemplos de un código de diseño y aplicación. 

8. Utilizando un único “CSGL12Control” en un System.Windows.Forms.Form

8.1 Estructura del Programa

El siguiente diagrama muestra cómo un programa con un System.Windows.Forms.Form puede utilizar un solo “CSGL12Control” hacer dibujo con OpenGL.  El diagrama muestra los diferentes archivos CSGL12 utilizó para construir el programa.
csgl12_windows_form_program.png
Un programa con una sola “CSGL12Control” en un System.Windows.Forms.Form

8.2 Microsoft Visual C# utilizando para crear el programa

(1) Inicio Microsoft Visual C#.
(2) En el menú, seleccione “File” -> “New Project...”.
(3) En el “New Project” cuadro de diálogo que aparece, seleccione “Windows Forms Application”, y elegir un nombre para el programa, y pulse “OK”.
Inmediatamente (4) guardar el “Solution” seleccionando “File” -> “Save All”.  Un cuadro de diálogo con el título aparecerá “Save Project”, lo que le permite configurar el nombre de proyecto, ubicación del directorio, el nombre y la “solución” para el proyecto.  Recuerde la ubicación del directorio para que esté listo para la siguiente instrucción.  “Save” pulse el botón para guardar el proyecto.
(5) Copiar todos los archivos del directorio “CSGL12UsefulCode” en el “CSGL12” software para el directorio que contiene los archivos de código fuente del nuevo proyecto (es decir, el directorio que contiene los archivos “Form1.cs”, “Form1.Designer.cs”, “Program.cs”, etc), de manera que los archivos “CSGL12DLL.dll”, “CSGL12Control.dll”, “Color4f.cs” , “CSGL12Support.cs”, etc, están junto con el nuevo proyecto “Form1.cs” archivos, etc
(6) En Microsoft Visual C#, agregue el “CSGL12” C# archivos con el proyecto.  En el menú, seleccione “Project” -> “Add Existing Item...”, y en el “Add Existing Item” cuadro de diálogo, seleccionar todos los archivos de la C# software CSGL12 (“Color4f.cs”, “CSGL12Support.cs”, “ImageData.cs”, ...).
(7) En Microsoft Visual C#, añadir “referencias” a la DLL archivos “CSGL12DLL.dll” y “CSGL12Control.dll”.  En el menú, seleccione “Project” -> “Add Reference...”, y en el “Add Reference” cuadro de diálogo, seleccione la pestaña “Browse”, y seleccione los archivos “CSGL12DLL.dll” y “CSGL12Control.dll” el proyecto de directorio de archivos fuente, y pulse “OK”. 
(8) En Microsoft Visual C#, agregue el “CSGL12Control” a la “Toolbox”.  En el menú, seleccione “Tools” -> “Choose Toolbox Items...”.  “Choose Toolbox Items” en el cuadro de diálogo que aparece, pulse el botón “Browse...”, e ir al directorio de proyecto con los archivos de código fuente, y seleccione “CSGL12Control.dll”.  Pulse el botón “OK”.
(9) En Microsoft Visual C#, ver la “Toolbox”.  En el menú, seleccione “View” -> “Toolbox”.  En el “Toolbox”, vaya a la sección denominada “General”, y localice el elemento “CSGL12Control”.  Utilizando el cursor, haga clic en el elemento “CSGL12Control” y arrástrelo a la “Form” en “Design” vista. 
(10) En Microsoft Visual C#, en el “Form” “Design” vista, mueva el “CSGL12Control” ejemplo, en la “Form” y ajustar su anchura y altura.  En el panel de “Properties”, establezca el valor “Anchor” incluir “Top, Bottom, Left, Right” si desea que el control para cambiar el tamaño de acuerdo a los cambios en el tamaño de la ventana del programa.
(11) En Microsoft Visual C#, cambiar las propiedades del proyecto para que pueda “unsafe” usar código.  En el menú, seleccione “Project” -> “[project] Properties...”.  Seleccione el cuadro de diálogo que aparece, seleccione la pestaña “Build” nombre y marque la casilla de verificación denominada “[X] Allow unsafe code”.  Cierre el cuadro de diálogo de propiedades del proyecto.
(12) En Microsoft Visual C#, C# añadir un nuevo archivo en el proyecto.  En el menú, seleccione “Project” -> “Add New Item...”.  En el cuadro de diálogo llamado “Add New Item”, elija la plantilla “Class” nombre y elegir un nombre para el nuevo tipo de clase, como “CSGL12MyHandler.cs” y, a continuación, pulse el botón “Add”.  Miren el ejemplo proyecto denominado “CSGL12Example1”, en el archivo llamado “CSGL12Example1Handler.cs”, como un ejemplo de cómo el código de “CSGL12MyHandler.cs” debe ser por escrito. 
(13) En Microsoft Visual C#, en el “Solution Explorer”, haga clic en “Form1”.  En el menú, seleccione “View” -> “Code” (o pulse F7, o click-derecho en “Form1” y elegir “View Code”.  El código en el archivo “Form1.cs” aparecerá en el editor.  Modificar el código en el archivo “Form1.cs” a ser similar al código en el archivo “CSGL12Example1Form.cs” en el proyecto “CSGL12Example1” incluido en el “CSGL12” software.  En particular, una variable para crear una instancia de su clase de eventos (por ejemplo, “CSGL12MyHandler”), y, a continuación, agregue los métodos de esa clase de eventos como ejemplo para los distintos eventos de la instancia de “CSGL12Control” sobre la “Form”. 
(14) En Microsoft Visual C#, compilar y ejecutar el programa.  Si desea compartir el programa, debe incluir los dos archivos DLL (“CSGL12DLL.dll” y “CSGL12Control.dll”) con el archivo ejecutable (*.exe). 
Si usted es un experto programador C#, entonces usted puede evitar la necesidad de distribuir los archivos DLL (“CSGL12DLL.dll” y “CSGL12Control.dll”) con su ejecutable (*.exe).
Copie los archivos “GL.cs”, “CSGL12Control.cs”, y “PrecisionTime.cs” de los proyectos denominado “CSGL12DLL” y “CSGL12Control” en el “CSGL12” software para el directorio de fuentes de su proyecto actual.  Añadir los archivos “GL.cs”, “CSGL12Control.cs”, y “PrecisionTime.cs” a su proyecto a fin de que se compilan directamente en el programa.  No tienen referencias a “CSGL12DLL.dll” y “CSGL12Control.dll” en el proyecto. 
Vea la “CSGL12Example1” proyecto en el “CSGL12” software, y mirar el código en los archivos denominados “CSGL12Example1Form.cs” y “CSGL12Example1Form.Designer.cs” para ver qué código es necesario para crear e inicializar una instancia de “CSGL12Control” en un “Form”.  Añadir un código similar a “Form1.cs” y “Form1.Designer.cs” a crear e inicializar manualmente una instancia de “CSGL12Control” en su “Form”. 
Este procedimiento es muy inconveniente, y requiere de conocimientos especializados y la atención, pero el ejecutable resultante (*.exe) no requerirá “CSGL12DLL.dll” o “CSGL12Control.dll”.  Es muy agradable poder compartir el software en forma de un único archivo ejecutable (*.exe) sin necesidad de otros archivos.

8.3 Añadir “referencias” a CSGL12DLL.dll y CSGL12Control.dll

Esta sección incluye imágenes de la utilización de Microsoft Visual C# 2008 Express Edition añadir “referencias” a la DLL archivos CSGL12DLL.dll y CSGL12Control.dll al proyecto.
En el menú, seleccione “Project” -> “Add Reference...”.  O bien, haga clic con el botón “References” tema en el panel de “Solution Explorer” y seleccione “Add Reference...”, como se muestra en la siguiente imagen. 
adding_references_001.png
El menú contextual para la “References” tema en el “Solution Explorer”, que muestra la opción “Add Reference...”
Después de seleccionar la opción “Add Reference...”, un cuadro de diálogo llamado “Add Reference” aparecerá.  En este cuadro de diálogo, seleccione la pestaña “Browse”, y seleccione el DLL archivos “CSGL12DLL.dll” y “CSGL12Control.dll”, como se muestra en la imagen siguiente y, a continuación, pulse el botón “OK”. 
adding_references_002.png
“Browse” la ficha de la “Add Reference” cuadro de diálogo, con la DLL archivos “CSGL12DLL.dll” y “CSGL12Control.dll” ambos seleccionados
Después de pulsar el botón “OK”, el cuadro de diálogo “Add Reference” desaparecerán, y la DLL archivos “CSGL12DLL.dll” y “CSGL12Control.dll” se publicará en el “References” sucursal en el “Solution Explorer”, como se muestra en el diagrama siguiente.
adding_references_003.png
El DLL archivos “CSGL12DLL.dll” y “CSGL12Control.dll” en el “References” sucursal en el “Solution Explorer”

8.4 CSGL12Control añadir a la Toolbox en Microsoft Visual C# 2008 Express Edition

Esta sección incluye imágenes de la utilización de Microsoft Visual C# 2008 Express Edition añadir CSGL12Control a la “Toolbox” para que una persona puede agregar fácilmente a casos de CSGL12Control un “Form” en el “Designer” (Shift+F7 por defecto).
En el menú, seleccione “View” -> “Toolbox”.  En el “Toolbox”, vaya a la sección denominada “General”, como se muestra en la siguiente imagen.
adding_control_to_toolbox_001.png
“General” la sección de la “Toolbox”
Haga clic derecho en cualquier lugar dentro de la “Toolbox”.  Seleccione la opción “Choose Items...”  en el menú contextual que aparece, como se muestra en la siguiente imagen.
adding_control_to_toolbox_002.png
“Choose Items...”  la opción en el menú contextual de la “Toolbox”
Por otra parte, en el menú, seleccione seleccione “Tools” -> “Choose Toolbox Items...”.
“Choose Toolbox Items” el cuadro de diálogo debe aparecer, como se muestra en la siguiente imagen.
adding_control_to_toolbox_003.png
El cuadro de diálogo “Choose Toolbox Items”
“Choose Toolbox Items” en el cuadro de diálogo, pulse el botón “Browse”.  “Open” en el cuadro de diálogo que aparece, seleccione la DLL archivo “CSGL12Control.dll”, como se muestra en la imagen siguiente y, a continuación, pulse el botón “OK”. 
adding_control_to_toolbox_004.png
“Open” el cuadro de diálogo, con la DLL archivo seleccionado “CSGL12Control.dll”
El tema “CSGL12Control” debe aparecer ahora en el cuadro de diálogo “Choose Toolbox Items”, como se muestra en la siguiente imagen.  Pulse el botón “OK”.
adding_control_to_toolbox_005.png
“CSGL12Control” ahora el tema aparece en el cuadro de diálogo “Choose Toolbox Items”
El tema “CSGL12Control” debe aparecer ahora en el “Toolbox”, como se muestra en la siguiente imagen. 
adding_control_to_toolbox_006.png
El “CSGL12Control” tema aparece ahora en la “Toolbox”

8.5 CSGL12Control añadir a un “Form” utilizando el “Toolbox”

Esta sección incluye imágenes de la utilización de Microsoft Visual C# 2008 Express Edition añadir una instancia de CSGL12Control a un “Form” utilizando el “Toolbox”. 
En el menú, seleccione “View” -> “Designer” (Shift+F7 por defecto).  O bien, haga doble clic en un archivo “Form*.cs” en el “Solution Explorer”.  O haga clic derecho en un archivo “Form*.cs” en el “Solution Explorer” y seleccione “View Designer”.  Utilizando uno de los tres métodos, “Designer” la ventana para una “Form” debería aparecer.
En el menú, seleccione “View” -> “Toolbox”.  En el “Toolbox”, vaya a la sección denominada “General”.  Un elemento “CSGL12Control” debe aparecer allí, como se muestra en la siguiente imagen. 
adding_control_to_toolbox_006.png
El “CSGL12Control” debería estar ya en el “Toolbox”
Utilizando el cursor, haga clic en el elemento “CSGL12Control” y arrástrelo a la “Form” en “Designer”.  Una instancia de “CSGL12Control” debe aparecer en la “Form” como se muestra en la siguiente imagen. 
adding_control_to_toolbox_007.png
Una instancia de “CSGL12Control” en un “Form” en el “Designer”
En el “Form” “Designer” vista, mueva el ejemplo de “CSGL12Control” sobre la “Form” y ajustar su anchura y altura. 
Haga clic en la instancia de “CSGL12Control” sobre la “Form” para seleccionarlo.  A continuación, en el panel de “Properties”, establezca el valor “Anchor” incluir “Top, Bottom, Left, Right” de modo que el tamaño de la “CSGL12Control” va a cambiar en respuesta a los cambios en el tamaño de la ventana del programa.  Usted también puede cambiar el nombre de la variable (es decir, el valor de “(Name)”) para la instancia de “CSGL12Control” automática a partir de la predeterminada (por ejemplo, “csgL12Control”) a algo apropiado para su código (por ejemplo, “mCSGL12Control” o “mCSGL12Control1”, etc.) 
La siguiente imagen muestra la “Form” “Designer” vista y el panel de “Properties”.
CSGL12Control_ScreenImage.png
Una instancia de CSGL12Control en un Form en el Designer, y el panel de “Properties

9. Mediante el uso de dos casos de “CSGL12Control” en un System.Windows.Forms.Form

El siguiente diagrama muestra un ejemplo de cómo dos casos de “CSGL12Control” se puede añadir a un System.Windows.Forms.Form que ver con OpenGL dibujo en un programa.
csgl12_windows_form_program_with_two_controls.png
Un programa con dos casos de “CSGL12Control” en un System.Windows.Forms.Form
Siga las instrucciones en la sección anterior para añadir una única instancia de “CSGL12Control” a un “Form”.  Después, simplemente arrastre una segunda instancia de “CSGL12Control” de la “Toolbox” a la “Form” para añadir un segundo “CSGL12Control”. 
Cada instancia de “CSGL12Control” tendrá su propio nombre de variable.  Cada instancia de “CSGL12Control” puede tener su propia clase de eventos asociados, o puede utilizar distintas instancias de un solo tipo de clase manejador. 
Estudio “CSGL12Example2” el proyecto de ejemplo para aprender cómo dos casos puede tener su “CSGL12Control” eventos enviados a dos diferentes casos de la costumbre de evento con distintas clases de dibujo OpenGL funciones. 
El programa de ejemplo “CSGL12Example2” tiene cada instancia de “CSGL12Control” en un “SplitContainer” “Control”, simplemente para demostrar una manera en que “CSGL12Control” de ejemplo se pueden utilizar.  Sin embargo, los casos de “CSGL12Control” puede ser directamente a la “Form”. 

10. C# código de ejemplo para una “Form” con una instancia de CSGL12Control

El siguiente es el código completo de C# que figura en el archivo “CSGL12Example1Form.cs”, que forma parte del programa de ejemplo “CSGL12Example1”. 
Este código se presenta aquí como un simple ejemplo de cómo una instancia de CSGL12Control pueden ser creados y utilizados por 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);
        }




    }




}
Observe que la variable miembro se declara “mCSGL12Example1Handler” para referirse a una instancia de una class nombre “CSGL12Example1Handler”.  Esta clase se describe en un apartado posterior de este documento.  Observe que el constructor para “CSGL12Example1Form” añade los métodos de la instancia de “CSGL12Example1Handler” a la “multicast delegates” asociadas a los diferentes eventos generados por un caso de “CSGL12Control”.  Esto significa que cuando la instancia de “CSGL12Control” genera varios eventos, los acontecimientos hará que los diversos métodos de la instancia de “CSGL12Example1Handler” (es decir, “mCSGL12Example1Handler”), que se invoca.
Observe que la variable miembro se declara “mTimer” para referirse a una instancia de una class nombre “System.Windows.Forms.Timer”.  Este objeto se utiliza para invocar una función llamada “PrivateTimerTickEventHandler” cada 10 milisegundos.  La función llamada “PrivateTimerTickEventHandler” llama a un método de la instancia de “CSGL12Control” (es decir, “mCSGL12Control1”) que causa que “Control” llamar propio.  Este es un ejemplo de cómo puede “CSGL12Control” animado en una tasa aproximada.
Sólo una parte de la definición de “class CSGL12Example1Form” aparece en el C# archivo llamado “CSGL12Example1Form.cs”.  Otra parte de la definición de “class CSGL12Example1Form” aparece en C# un archivo llamado “CSGL12Example1Form.Designer.cs”.  Aunque los archivos con nombres que coincidan con el patrón “*.Designer.cs” son generalmente creados y modificados por el sólo “Form Designer” ventana gráfica C# de un editor, también es posible crear y modificar esos archivos C# utilizando un editor de texto. 
El siguiente es el código completo de C# que figura en el archivo “CSGL12Example1Form.Designer.cs”, que forma parte del programa de ejemplo “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;
    }
}
Observe que este código C# contiene la declaración de la variable “mCSGL12Control1”, que se refiere a un caso de “class CSGL12.CSGL12Control” (es decir, “class CSGL12Control” en “namespace CSGL12”).  Este ejemplo se ha creado y configurado en la función “InitializeComponent”. 

11. Manejo de eventos invocados por una instancia de CSGL12Control

La sección anterior mostró C# el código de un “Form” que contiene una única instancia de “CSGL12Control”.  El código C# añadir métodos de “class” un llamado “CSGL12Example1Handler” como de eventos para diferentes eventos generados por la instancia de “CSGL12Control”. 
Aquí hay una lista de eventos interesantes de “CSGL12Control”, y la “delegate” tipos asociados a los eventos:
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
Sólo el “OpenGLStarted” evento es un evento específico para el tipo “CSGL12Control”.
Todos los demás eventos son estándar System.Windows.Forms eventos, cuyo caso deben tener los manipuladores de determinados parámetros (especificados en cualquier Forms documentación).
El “OpenGLStarted” y “Paint” eventos son los acontecimientos más importantes para OpenGL dibujo.
El “OpenGLStarted” caso se invoca antes de la primera “Paint” caso se invoca.
Por lo tanto, el manejador de evento “OpenGLStarted” hay que añadir al control antes de que el control tiene la oportunidad de tratar de pintar en sí, de lo contrario el tiempo de un evento no será recibido.
Este evento no es más que una conveniencia, y puede ser ignorada.
Sin embargo, la adición de un manejador para este evento hace posible que el manejador de código para hacer un tiempo de inicialización que depende de OpenGL está listo para usar.
(OpenGL no se puede utilizar hasta la ventana y existe la ventana está dispuesto a realizar su primera pintura.
Por lo tanto, el caso de piezas de repuesto “OpenGLStarted” el programador del riesgo de tratar de utilizar OpenGL demasiado pronto después de iniciar el programa.
) Es muy fácil añadir la lógica en un manejador de “Paint” hacer un tiempo de inicialización, utilizando el contexto de OpenGL la “CSGL12Control”.
“OpenGLStarted” El evento se ofrece como una conveniencia.
El siguiente es el código completo de C# que figura en el archivo “CSGL12Example1Handler.cs”, que forma parte del programa de ejemplo “CSGL12Example1”. 
Este código se presenta aquí como un simple ejemplo de cómo los acontecimientos generados por un caso de “CSGL12Control” puede ser manejado a dibujar usando 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;
        }




    }




}
Observe que la función llamada “OpenGLStarted” se utiliza en este ejemplo para crear un “pixel shader programs” y OpenGL textura.  Para este programa, sólo tenemos que crear esos recursos una vez, y es más eficiente para crear sólo una vez. 
Observe que la función llamada “OpenGLStarted” el código comprueba si WGL “extension” una función llamada “wglSwapIntervalEXT()” existe, y, si existe esa función, el código que invoca la función.  Que establece una función de estado que afecta el funcionamiento del programa para todo el período de sesiones, por lo que sólo necesitan llamar a esa función una vez, que es la razón por la que intento llamar a esa función en el “OpenGLStarted” función (que a su vez sólo es invocado una vez, cuando OpenGL se inicia por un “CSGL12Control”, suponiendo que hemos añadido el método “OpenGLStarted” caso a los delegados).
La función llamada “Paint” contiene todo el código para dibujar un “cuadro” de la animación usando OpenGL.  “Paint” la función se denominará tal vez 60 veces por segundo, debido al hecho de que los asociados “CSGL12Control” ejemplo, se está “invalidado” (obligados a recurrir de nuevo) en esa tasa.  (Mire el ejemplo de código “Form” en la sección anterior para ver el reloj que determina la tasa de “anulación” y la llamada a la función que hace que la instancia de “CSGL12Control” a ser “anulados.)” 
Todas las funciones se invocan OpenGL utilizando una instancia de la “class GL” (por ejemplo: gl.gl*()).  El ejemplo de “class GL” se adquirirán a partir de la instancia de “CSGL12Control”, que implícitamente se almacena en el primer parámetro de la función “Paint”.
Todos los OpenGL constantes pueden ser especificados por “class” especificando el nombre “GL” seguida por un punto y el nombre de la constante, es decir, “GL.GL_TRIANGLES”.
OpenGL el código de este ejemplo no es del todo evidente y fácil de entender, pero espero que usted puede reconocer la forma en que el código puede ser modificado por sus propios fines.

12. Comprobación de la disponibilidad de una “extensión” de la función OpenGL

Basta comprobar si el pabellón de booleano el mismo nombre que la función es “verdad” OpenGL antes de intentar usar la función correspondiente.
La variable booleana tiene un nombre que comienza con “b” seguido por el nombre de la función 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.

    // . . .
}
Sólo es necesaria la comprobación de la “extensión” funciones.
OpenGL 1.1 funciones, y todas las funciones GLU, y WGL funciones básicas, no requieren de dicha verificación.  Sin embargo, existen banderas booleanas, y se establecen adecuadamente, para todas las funciones proporcionadas por “class GL”, incluyendo el núcleo OpenGL 1.1 funciones.  Por lo tanto, existe un modo para comprobar la disponibilidad de todas las funciones de esa clase. 
Conocer si una función es una “extensión” es responsabilidad del programador.
Sin embargo, la función nombre sufijos, como “EXT”, “ARB”, “MESA”, “NV” (NVidia), “APPLE”, etc, ayudan a indicar las funciones de extensión.
Si una función “gl*()” tiene una función “gl*ARB()” vecinos o “gl*NV(),” entonces la función “gl*()” es probablemente una extensión (en lo que respecta a la Windows OPENGL32.DLL se trate).
La única ventaja de saber si una función es una “extensión” (en lo que respecta a la Windows OPENGL32.DLL) está siendo capaz de evitar la comprobación de si las funciones están disponibles.
Puede buscar por todos los OpenGL funciones utilizados en su código y, a continuación, crear una lista alfabética de las distintas funciones utilizadas.
Luego, al comienzo de su programa, después de la CSGL12Control pide la OpenGLStarted delegado, simplemente marque todas las banderas booleanas para todas las funciones que va a utilizar.
Si decide dar por terminado el programa si las hubiera “requerido” funciones están desaparecidos, entonces todos los controles para las funciones en el código puede ser eliminado.
Asimismo, puede formar un grupo de los no esenciales funciones en el control y, posiblemente, informar al usuario de cualquier característica de los cambios y, posiblemente, abandonar los controles dispersos alrededor en el código.
OpenGL con más experiencia, puede tener una idea de lo que las extensiones están relacionados (ejemplos: imágenes, shaders, buffers, compresión, ...).
Por lo tanto, se puede comprobar la presencia de una sola función crítica y utilizar esa información para decidir si todo el subconjunto es probable que se presente.

13. Velocidad

Por diversas razones, C# es más lento que non-CLR C/C++.
C# es finalmente nativo compilado a lenguaje ensamblador, al igual que para C/C++, pero, debido a las garantías formuladas por el C# la lengua y la .NET CLR, la velocidad global de software basado en C# y .NET es algo más lento que el software desarrollado usando non-CLR C/C++.
Por lo tanto, obtener la velocidad más alta posible utilizando medios non-CLR C/C++ lugar de C#.
Por otra parte, porque llamando a cualquier biblioteca nativa de C# implica P/Invoke, invocando funciones tales como la OpenGL funciones será necesario algún tiempo para realizar un trabajo en la capa P/Invoke.
No obstante, “CSGL12” parece funcionar con la suficiente rapidez para ser utilizado por muchos en tiempo real, efectos gráficos, como por simples juegos, 3D, editores, o las presentaciones 3D.  Esto es especialmente cierto si la mayor parte del trabajo que se está haciendo por el GPU en lugar de la CPU.

14. Comparación entre “CSGL12” y la “Tao Framework”

El “Tao Framework” es un gran C# / .NET librería que proporciona una interfaz para muchas bibliotecas de código abierto, tales como OpenGL, OpenAL (audio), SDL (un juego / plataforma de simulación), Open Dynamics Engine (ODE) (física), etc
El Tao Framework es multiplataforma (Windows, Linux, Mac OS X).
“CSGL12” sólo proporciona una interfaz para OpenGL y es sólo para los Windows sistema operativo.
El Tao Framework tiene una comunidad.  Una persona puede beneficiarse de la comunicación con otros usuarios de la Tao Framework.
Sin embargo, puede haber muchos fines para los que “CSGL12” podría ser más fácil de utilizar para Windows programas. 
colinfahey.com
información de contacto
English  Español  Português  Français  Italiano  Deutsch  Nederlands  Svenska  Dansk  Suomi  Norsk  Русский  Polski  Română  Български  Hrvatski  Česky  中国  中國  日本語  한국어  Ελληνική  हिन्दी  العربية