C# OpenGL interface
Windows para o sistema operacional
Colin Fahey

CSGL12Control sobre um Form, mostrando uma “fractal” pixel shader programa e GDI+ desenho copiado para uma textura

Dois casos CSGL12Control sobre um Form, mostrando pixel shader programas e texturas

Um 3D avatar que anda a área de trabalho e pode ser movido com o cursor
1. Software
CSGL12_20090725.zip
CSGL12: C# OpenGL interface para Windows, versão 12
4170499 bytes
MD5: 30781a6570441785ea636f2ae1cd16ef
2. Todos os C# computador código no C# OpenGL interface (CSGL12) é de “domínio público”
Escrevi todos os C# computador código dentro da C# OpenGL interface (CSGL12).
Dou todas as C# computador código dentro da C# OpenGL interface (CSGL12), a ser do “domínio público.”
Por isso, o computador código podem ser usados para qualquer finalidade (comercial ou privado), sem pagamento, sem restrições, sem obrigações, e sem reconhecer o autor original.
O código pode ser modificado, ou porções reutilizados, sem restrições, e sem obrigações, e sem reconhecer o autor original.
O exemplo programas incluem uma pequena quantidade de código informático (especificamente, “shader computador código) escrito por outras pessoas.” Esse código não é dentro da própria interface e podem ser trivialmente removido. Esse código é apenas para demonstrar a simplicidade da utilização da interface para criar e usar “shader” programas.
3. Introdução
“CSGL12” é uma coleção de arquivos C# computador código que implementa uma interface para a biblioteca OpenGL gráficos (incluindo todas as extensões de OpenGL até ao ano 2007) para o Windows sistema operativo.
O código C# computador arquivos na “CSGL12” cobrança se torna mais fácil para adicionar OpenGL saque a qualquer C# / .NET software com um “Form” (um exemplo de “System.Windows.Forms.Form”).
A recolha “CSGL12” arquivos de código de computador inclui um arquivo chamado “CSGL12Control.cs”, que define uma classe denominada “CSGL12Control”, derivados de “System.Windows.Forms.Control”. Cada instância do “CSGL12Control” representa um desenho independente OpenGL área. É muito fácil adicionar várias instâncias do CSGL12Control para uma Form (um exemplo de System.Windows.Forms.Form).
4. Características e requisitos do “CSGL12”
O código só é Windows para sistemas operacionais que suportam o .NET 2.0 Framework (Windows 2000, Windows XP, Windows Vista, Windows 7)
O código pode ser compilado usando “Microsoft Visual C# 2008 Express Edition” (um compilador livre), ou similar C# compiladores.
O código exige a ser construída com a opção selecionada “[X] Allow unsafe code” construir imagem otimizada de modo que os dados copiando funções podem ser utilizadas. Se você é um perito C# programador você será capaz de identificar facilmente as partes do código C# que exigem que o “unsafe” opção e desativá-los se desejado ou necessário. Imagem copiando dados é 10 vezes mais rápido usando “unsafe” código que a alternativa, e é por isso que tal código é utilizado. Se você construir uma DLL que contém todas as “unsafe” código e, em seguida, um projeto que utiliza DLL que não exige a ser construída com a “unsafe” opção, e por isso pode-se inferir que a ausência do “unsafe” opção em um projeto não implica qualquer extra segurança (porque muitas DLL ficheiros que são utilizados implícita ou explicitamente pelo programa contêm código “inseguro).”
O código pode ser compilado e utilizado por qualquer das seguintes características:
Microsoft Visual C# 2008 Express Edition
Microsoft Visual Studio 2008
Microsoft .NET 3.5 SDK
SharpDevelop
Mono Project
O código oferece mais OpenGL extensões (até o ano 2007), incluindo “vertex shaders” e “pixel shaders”.
O código prevê 1570 funções relacionadas com OpenGL:
336 GL functions
51 GLU functions
19 WGL functions
1164 extensions
O código oferece algumas alternativas variações do parâmetro 1570 funções com diferentes tipos, por conveniência.
O código define mais de 3244 constantes para OpenGL.
O código torna possível ter múltiplos contextos OpenGL desenho, todos animating independente, em qualquer “Form”.
Clicando sobre um “CSGL12Control” lhe dá “entrada foco,” permitindo posterior teclado e mouse roda entrada. Cursor movimentos e cliques são recebidos quando o cursor estiver dentro da área retangular de uma instância do “CSGL12Control”.
O código inclui funções para demonstrar como fazer algumas tarefas comuns OpenGL em C# e .NET.
O código enumera todos OpenGL constantes e funções, por ordem alfabética, no “class GL” em “GL.cs”, fazendo com que seja fácil de determinar se qualquer constante ou função está em falta (que é pouco provável, excepto para as extensões aprovadas após o final do ano 2007).
O exemplo mostra como fazer programas GDI+ desenho de um Bitmap e, em seguida, como a cópia que Bitmap para OpenGL uma textura.
Isso permite que textos e outros GDI+ desenho das capacidades para contribuir para uma OpenGL cena.
O GDI+ Bitmap podem ser atualizados e enviados para uma textura OpenGL quantas vezes uma vez por OpenGL frame.
O exemplo programas mostram como a escolha entre várias “pixel shader programs” enquanto o programa está sendo executado.
O exemplo mostra como escrever programas OpenGL buffers para os arquivos de imagem (JPG, BMP, GIF, PNG).
Imprensa Shift + 0 (shift-zero) para escrever a OpenGL buffer para arquivos de imagens.
O exemplo de código demonstra como compilar “GL.cs” no DLL um arquivo e, em seguida, acrescentando que DLL arquivo para um outro projeto, pode impedir que o código Microsoft editores (por exemplo, Microsoft Visual C# 2008 Express Edition, etc) com “IntelliSense” (context-sensitive code conclusão) de tornar-se frequentemente e persistentemente unresponsive (repetidas vezes pausando por vários segundos, tornando o editor totalmente inutilizáveis). Tendo o arquivo “GL.cs” diretamente incluídas em qualquer projecto a ser editado por um editor Microsoft código não é prático, a menos que uma pessoa está disposta a suportar a lentidão do editor. Este problema tem afetado Microsoft Visual Studio 2003, 2005, 2008, e provavelmente irá afetar a versão 2010, também.
O exemplo de código demonstra o uso de múltiplas instâncias de “CSGL12Control” em um “Form”.
O exemplo de código inclui código para fazer um “avatar” que anda 3D o desktop de Windows.
5. Exemplo programas incluídos no “CSGL12”
5.1 “CSGL12DLL”
O projeto chamado “CSGL12DLL” produz DLL um arquivo chamado “CSGL12DLL.dll” que contém “class GL” (definido no C# arquivo “GL.cs”).
Colocar “class GL” em DLL para um arquivo, e então utilizar essa DLL em outros projetos que usam “class GL”, ajuda a evitar um problema extrema com todos os editores Microsoft código com o IntelliSense recurso. Usando o C# arquivo GL.cs diretamente em um projeto iria causar qualquer Microsoft código editor com o IntelliSense recurso para ficar totalmente insensível e inutilizável quase continuamente, devido à ineficiência do IntelliSense característica (eo facto de IntelliSense aparentemente bloqueia a discussão principal do programa do editor ).
Se você estiver usando um editor C# código que não é produzido por Microsoft (por exemplo, “SharpDevelop”, “MonoDevelop”, etc), você pode simplesmente incluir o ficheiro “GL.cs” diretamente em seus projetos, e que seria improvável a ganhar uma vantagem de utilizar “CSGL12DLL.dll”.
5.2 “CSGL12Control”
O projeto chamado “CSGL12Control” produz DLL um arquivo chamado “CSGL12Control.dll” que contém “class CSGL12Control” (definido no C# arquivo “CSGL12Control.cs”).
Colocar “class CSGL12Control” em DLL para um arquivo, permite que “Control” (isto é, uma classe derivada de “System.Windows.Forms.Control”) a ser adicionado ao “Toolbox” de Microsoft Visual C# 2008 Express Edition (e similares C# editores). Tendo “CSGL12Control” no “Toolbox” torna fácil para uma pessoa para adicionar uma instância do “CSGL12Control” para um “Form” no “Designer” (por exemplo, uma pessoa pode simplesmente usar o cursor para selecionar e arrastar uma instância do “CSGL12Control” da “Toolbox” para um “Form”).
O “CSGL12Control” objeto gere um OpenGL desenho contexto. Várias instâncias do “CSGL12Control” podem coexistir em um “Form”.
5.3 “CSGL12Example1”
O projeto chamado “CSGL12Example1” produz um programa executável (arquivo EXE) chamado “CSGL12Example1.exe”. O programa usa “CSGL12DLL.dll” e “CSGL12Control.dll” para mostrar um exemplo de CSGL12Control e desenhar um cubo usando OpenGL.
O programa demonstra a utilização de quatro diferentes “pixel shaders” “(fractal, tijolo, madeira” e “desenho animado).”
O programa também mostra o uso de “GDI+”, um desenho .NET biblioteca, para desenhar texto e outras formas para “Bitmap” um objeto (um “GDI+” objeto) e, em seguida, copiar os dados de imagem que “Bitmap” para uma “texture” em OpenGL, permitindo assim que a imagem traçada por “GDI+” para aparecer na OpenGL desenho. Esta capacidade é muito útil porque OpenGL carece de muitos dos recursos encontrados na 2D desenho “GDI+” e similares 2D desenho libaries.
5.4 “CSGL12Example2”
O projeto chamado “CSGL12Example2” produz um programa executável (arquivo EXE) chamado “CSGL12Example2.exe”. O programa usa “CSGL12DLL.dll” e “CSGL12Control.dll” para apresentar dois casos de CSGL12Control, cada um dos que chama um cubo usando OpenGL.
O programa tem uma “SplitContainer” “Control” sobre o “Form”. Cada uma das duas áreas do “SplitContainer” contém uma instância do CSGL12Control. Assim, uma pessoa pode ajustar a posição da cisão entre as duas instâncias do CSGL12Control. Isto demonstra a flexibilidade do CSGL12Control.
Um dos casos de CSGL12Control envia eventos para um conjunto de manipuladores evento em uma instância do “CSGL12Example2Handler1.cs”, que usa o mesmo código “CSGL12Example1Handler.cs” como no exemplo “CSGL12Example1” projecto. Portanto, uma das instâncias CSGL12Control chama um cubo com uma “pixel shader” seleccionados de entre quatro disponíveis “pixel shaders”.
A exemplo de outros eventos CSGL12Control envia para um conjunto de manipuladores evento em uma instância do “CSGL12Example2Handler2.cs”, que desenha um cubo com uma textura imagem (ou um “tabuleiro de jogo” padrão, se um arquivo de imagem chamado “image.jpg” não for encontrada).
5.5 “CSGL12Avatar”
O projeto chamado “CSGL12Avatar” produz um programa executável (arquivo EXE) chamado “CSGL12Avatar.exe”. O programa usa “CSGL12DLL.dll” e “CSGL12Control.dll” para desenhar um cubo usando OpenGL sobre a “Form” sem uma fronteira, com a cor com base transparência ativada, para chamar um 3D “avatar” que anda a Windows desktop área.
O movimento avatar podem ser clicados e arrastados para um novo local usando o cursor. Dê um duplo clique no avatar irá torná-lo desaparecer. Embora o código estabelece apenas um cubo, OpenGL pode ser usada para chamar outras coisas.
Várias instâncias do “avatar” programa pode ser iniciado. Assim, muitas instâncias independentes “avatar” pode simultaneamente deambulam pelas Windows desktop. Isto é divertido. Um perito C# programador possa desfrutar encontrar formas de coordenar a actividade de muitos desses casos “avatar.”
Infelizmente, a taxa na qual o objeto Window com transparência é atualizada na tela é muito mais lento do que a taxa a que possa chamar OpenGL. O “avatar” só atualiza 10 vezes por segundo. Não sei se isso pode ser melhorado.
5.6 “CSGL12BuiltExecutableExamplesForReference”
O diretório chamado “CSGL12BuiltExecutableExamplesForReference” contém arquivos DLL e EXE produzida por todos os arquivos do exemplo projectos. Esses arquivos são fornecidos como uma referência, de modo que os arquivos possam ser testadas imediatamente, mesmo se uma pessoa não tem a capacidade de compilar os diversos projectos a partir do C# código.
5.7 “CSGL12UsefulCode”
O diretório chamado “CSGL12UsefulCode” contém arquivos C# que poderiam ser úteis para pessoas que querem fazer banalizado desenho operações com OpenGL. O repertório inclui também a DLL arquivos “CSGL12DLL.dll” e “CSGL12Control.dll” por conveniência.
O código nesse diretório class define diversos tipos, tais como Color4f, Vector3f, Matrix4x4f, Triangle, Mesh, ImageData, Texture, ShaderProgram, etc O código é razoavelmente eficiente, mas o código se destina apenas para inspirar as pessoas a desenvolverem suas próprias implementações.
6. CSGL12 arquivos
O “CSGL12” coleção de arquivos C# computador código inclui os ficheiros mostra o seguinte esquema:

O “CSGL12” coleção de arquivos C# computador código inclui os arquivos mostrado neste diagrama.
“CSGL12” O software também inclui projectos para criar o DLL dois arquivos (“CSGL12DLL.dll” e “CSGL12Control.dll”) mostrado no diagrama. Esses dois DLL arquivos podem ser criados para tornar mais fácil para criar programas que utilizem OpenGL, mas também é possível criar programas utilizando apenas o C# arquivos diretamente.
7. “namespace CSGL12” e “class” tipos
O “CSGL12” coleção de arquivos C# computador código define “namespace CSGL12” e os tipos “class” mostra o seguinte esquema:

O “CSGL12” coleção de arquivos C# computador código define “namespace CSGL12” e os tipos “class” mostrado neste diagrama.
Um programa que faz OpenGL desenho pode ser criado usando somente “class GL” (usando o C# arquivo GL.cs directamente, ou usando o DLL arquivo CSGL12DLL.dll que também contém “class GL”). No entanto, usando “class CSGL12Control” (usando o C# arquivo CSGL12Control.cs directamente, ou usando o DLL arquivo CSGL12Control.dll que também contém “class CSGL12Control”) faz a adição OpenGL desenho de um Form (System.Windows.Forms.Form) fácil e conveniente.
O C# classes Color4f, CSGL12Support, ImageData, ..., no fundo do diagrama são oferecidas apenas por conveniência. Essas classes tornar mais fácil para criar programas que chamar utilizando OpenGL. No entanto, talvez você já tem turmas que executam as operações dessas classes, ou você pode optar por criar classes semelhantes que realizam as operações de maneira diferente ou mais eficiente. Essas aulas são oferecidas como exemplos de um código especial concepção e execução.
8. Utilizando uma única “CSGL12Control” sobre um System.Windows.Forms.Form
8.1 Programa estrutura
O diagrama seguinte mostra como um programa com uma System.Windows.Forms.Form pode usar um único “CSGL12Control” para fazer desenhos com OpenGL. O diagrama mostra as várias CSGL12 arquivos usados para construir o programa.

Um programa utilizando um único “CSGL12Control” em um System.Windows.Forms.Form
8.2 Usando Microsoft Visual C# para criar o programa
(1) Iniciar Microsoft Visual C#.
(2) No menu, selecione “File” -> “New Project...”.
(3) No “New Project” caixa de diálogo que aparece, selecione “Windows Forms Application”, e escolher um nome para o programa, e prima “OK”.
Imediatamente (4) salvar o “Solution”, seleccionando “File” -> “Save All”. Uma caixa de diálogo com o título “Save Project” irá aparecer, permitindo que você defina o nome do projeto, diretório local, ea “solução” nome para o projeto. Lembre-se do diretório local, para que você esteja pronto para a próxima instrução. “Save” Pressione o botão para salvar o projeto.
(5) Copie todos os arquivos do diretório “CSGL12UsefulCode” no “CSGL12” software para o diretório contendo os arquivos de código fonte do novo projeto (ou seja, o directório contendo os ficheiros “Form1.cs”, “Form1.Designer.cs”, “Program.cs”, etc), de tal forma que os arquivos “CSGL12DLL.dll”, “CSGL12Control.dll”, “Color4f.cs” , “CSGL12Support.cs”, etc, estão a par do novo projecto ficheiros “Form1.cs”, etc
(6) Em Microsoft Visual C#, adicione o “CSGL12” C# arquivos para o projeto. No menu, selecione “Project” -> “Add Existing Item...”, e “Add Existing Item” na caixa de diálogo, selecione todos os arquivos de C# o CSGL12 software (“Color4f.cs”, “CSGL12Support.cs”, “ImageData.cs”, ...).
(7) Em Microsoft Visual C#, adicionar “referências” ao DLL arquivos “CSGL12DLL.dll” e “CSGL12Control.dll”. No menu, selecione “Project” -> “Add Reference...”, e “Add Reference” na caixa de diálogo, selecione a guia “Browse”, e selecione os arquivos “CSGL12DLL.dll” e “CSGL12Control.dll” do projeto arquivo fonte directório, e prima “OK”.
(8) Em Microsoft Visual C#, adicione o “CSGL12Control” ao “Toolbox”. No menu, selecione “Tools” -> “Choose Toolbox Items...”. No “Choose Toolbox Items” caixa de diálogo que aparece, pressione o botão “Browse...”, e vá para o diretório do projeto com o código-fonte arquivos, e selecione “CSGL12Control.dll”. Pressione o botão “OK”.
(9) Em Microsoft Visual C#, ver a “Toolbox”. No menu, selecione “View” -> “Toolbox”. No “Toolbox”, vá para a seção denominada “General”, e localize o item chamado “CSGL12Control”. Usando o cursor, clique no item chamado “CSGL12Control” e arrastá-lo para o “Form” em “Design” vista.
(10) Em Microsoft Visual C#, no “Form” “Design” vista, mova o “CSGL12Control” exemplo sobre o “Form” e ajustar sua largura e altura. No painel “Properties”, defina o valor “Anchor” para incluir “Top, Bottom, Left, Right” se você deseja que o controle para alterar tamanho de acordo com mudanças na janela do programa tamanho.
(11) Em Microsoft Visual C#, alterar o projecto propriedades, para que ele possa usar “unsafe” código. No menu, selecione “Project” -> “[project] Properties...”. Selecione a caixa de diálogo que aparecer, escolha o separador denominado “Build”, e marque a caixa de verificação denominada “[X] Allow unsafe code”. Feche a caixa de diálogo Propriedades do projeto.
(12) Em Microsoft Visual C#, C# adicionar um novo arquivo para o projeto. No menu, selecione “Project” -> “Add New Item...”. Na caixa de diálogo denominada “Add New Item”, escolha o modelo chamado “Class”, e escolher um nome para a nova classe, tais como “CSGL12MyHandler.cs” e, em seguida, pressione o botão “Add”. Vejam o exemplo projeto chamado “CSGL12Example1”, no arquivo chamado “CSGL12Example1Handler.cs”, como um exemplo de como o código de “CSGL12MyHandler.cs” deve ser escrita.
(13) Em Microsoft Visual C#, no “Solution Explorer”, clique sobre “Form1”. No menu, selecione “View” -> “Code” (ou prima F7, ou clique com o botão direito sobre “Form1” e escolha “View Code”. O código no arquivo “Form1.cs” aparecerá no editor. Modifique o código no arquivo “Form1.cs” ser similar ao código no arquivo “CSGL12Example1Form.cs” no projeto “CSGL12Example1” incluídos na “CSGL12” software. Em particular, criar uma variável para uma instância do seu evento manipulador classe (por exemplo, “CSGL12MyHandler”) e, em seguida, adicionar os métodos que a classe exemplo de como lidam com o caso para os diversos eventos da instância do “CSGL12Control” sobre o “Form”.
(14) Em Microsoft Visual C#, compilar e executar o programa. Se você deseja compartilhar o programa, você deve incluir os dois arquivos DLL (“CSGL12DLL.dll” e “CSGL12Control.dll”) com o arquivo executável (*.exe).
Se você é um perito C# programador, então você pode evitar a necessidade de distribuir os arquivos DLL (“CSGL12DLL.dll” e “CSGL12Control.dll”) com seu executável (*.exe).
Copie os arquivos “GL.cs”, “CSGL12Control.cs”, e “PrecisionTime.cs” dos projectos nomeados “CSGL12DLL” e “CSGL12Control” no “CSGL12” software para o diretório fonte do seu projeto atual. Adicione os arquivos “GL.cs”, “CSGL12Control.cs”, e “PrecisionTime.cs” para o seu projeto para que eles sejam compilados diretamente para o programa. Você não tem referências para “CSGL12DLL.dll” e “CSGL12Control.dll” no projecto.
Olha o “CSGL12Example1” projecto na “CSGL12” software, e olhar para o código dentro de arquivos chamado “CSGL12Example1Form.cs” e “CSGL12Example1Form.Designer.cs” que ver o código é necessário para criar e inicializar uma instância do “CSGL12Control” em um “Form”. Adicione código semelhante ao “Form1.cs” e “Form1.Designer.cs” de criar manualmente e inicializar uma instância do “CSGL12Control” em seu “Form”.
Este procedimento é muito inconveniente, e exige conhecimentos específicos e uma atenção redobrada, mas a resultante executável (*.exe) não vai exigir “CSGL12DLL.dll” ou “CSGL12Control.dll”. É muito agradável de ser capazes de partilhar o seu software na forma de um único arquivo executável (*.exe) sem exigir outros ficheiros.
8.3 Adicionando “referências” ao CSGL12DLL.dll e CSGL12Control.dll
Esta seção inclui imagens de utilizar Microsoft Visual C# 2008 Express Edition para adicionar “referências” ao DLL arquivos CSGL12DLL.dll e CSGL12Control.dll ao projeto.
No menu, selecione “Project” -> “Add Reference...”. Ou, clique com o botão direito “References” item na “Solution Explorer” painel e seleccionar “Add Reference...”, como mostrado na imagem seguinte.

Menu de contexto para o item “References” no “Solution Explorer”, mostrando a opção “Add Reference...”
Após selecionar os “Add Reference...” opção, uma caixa de diálogo denominada “Add Reference” irá aparecer. Nessa caixa de diálogo, selecione a guia “Browse”, e selecione o DLL arquivos “CSGL12DLL.dll” e “CSGL12Control.dll”, como mostrado na imagem seguinte e, em seguida, pressione o botão “OK”.

O “Browse” guia do “Add Reference” caixa de diálogo com o DLL arquivos “CSGL12DLL.dll” e “CSGL12Control.dll” ambos selecionados
Após pressionar o botão “OK”, o “Add Reference” caixa de diálogo irá desaparecer, e os DLL arquivos “CSGL12DLL.dll” e “CSGL12Control.dll” aparecerão na “References” sucursal no “Solution Explorer”, como mostrado no diagrama seguinte.

O DLL arquivos “CSGL12DLL.dll” e “CSGL12Control.dll” no “References” sucursal no “Solution Explorer”
8.4 Adicionando CSGL12Control ao Toolbox em Microsoft Visual C# 2008 Express Edition
Esta seção inclui imagens de utilizar Microsoft Visual C# 2008 Express Edition para adicionar CSGL12Control ao “Toolbox” para que uma pessoa pode facilmente adicionar casos de CSGL12Control para um “Form” no “Designer” (Shift+F7 por padrão).
No menu, selecione “View” -> “Toolbox”. No “Toolbox”, vá para a seção denominada “General”, como mostrado na imagem seguinte.

O “General” secção do “Toolbox”
Botão direito do mouse em qualquer lugar dentro do “Toolbox”. Selecione a opção “Choose Items...” no menu de contexto que aparece, como mostrado na imagem seguinte.

O “Choose Items...” opção no menu de contexto para o “Toolbox”
Alternativamente, no menu, selecione selecione “Tools” -> “Choose Toolbox Items...”.
O “Choose Toolbox Items” caixa de diálogo deve aparecer, como mostrado na imagem seguinte.

A caixa de diálogo “Choose Toolbox Items”
No “Choose Toolbox Items” caixa de diálogo, pressione o botão “Browse”. No “Open” caixa de diálogo que aparece, selecione o DLL arquivo “CSGL12Control.dll”, como mostrado na imagem seguinte e, em seguida, pressione o botão “OK”.

O “Open” caixa de diálogo com o DLL arquivo “CSGL12Control.dll” selecionados
O “CSGL12Control” item deverá aparecer na caixa de diálogo “Choose Toolbox Items”, como mostrado na imagem seguinte. Pressione o botão “OK”.

O “CSGL12Control” item agora aparece na caixa de diálogo “Choose Toolbox Items”
O “CSGL12Control” item deverá aparecer na “Toolbox”, como mostrado na imagem seguinte.

O “CSGL12Control” item agora aparece na “Toolbox”
8.5 Adicionando CSGL12Control para um “Form” usando o “Toolbox”
Esta seção inclui imagens de utilizar Microsoft Visual C# 2008 Express Edition para adicionar uma instância do CSGL12Control para um “Form” usando o “Toolbox”.
No menu, selecione “View” -> “Designer” (Shift+F7 por padrão). Ou, clique duas vezes em um arquivo “Form*.cs” no “Solution Explorer”. Ou clique com o botão direito “Form*.cs” um arquivo na “Solution Explorer” e selecione “View Designer”. Usando um desses três métodos, a “Designer” janela para um “Form” deve aparecer.
No menu, selecione “View” -> “Toolbox”. No “Toolbox”, vá para a seção denominada “General”. Um item chamado “CSGL12Control” deve aparecer lá, como mostrado na imagem seguinte.

O “CSGL12Control” já deveria estar na “Toolbox”
Usando o cursor, clique no item chamado “CSGL12Control” e arrastá-lo para o “Form” em “Designer”. Uma instância do “CSGL12Control” deverá constar no “Form” como mostrado na imagem seguinte.

Uma instância do “CSGL12Control” sobre um “Form” no “Designer”
No “Form” “Designer” exibir, mover a instância do “CSGL12Control” sobre a “Form” e ajustar sua largura e altura.
Clique na instância do “CSGL12Control” na “Form” para selecioná-lo. Em seguida, no painel “Properties”, defina o valor “Anchor” para incluir “Top, Bottom, Left, Right” para que o tamanho da “CSGL12Control” vai mudar em resposta a alterações na janela do programa tamanho. Você pode também querer alterar o nome da variável (ou seja, o valor para “(Name)”) para a instância do “CSGL12Control” automática a partir do padrão (por exemplo, “csgL12Control”) para algo apropriado para o seu código (por exemplo, “mCSGL12Control” ou “mCSGL12Control1”, etc.)
A imagem seguinte mostra o “Form” “Designer” vista ea “Properties” painel.

Uma instância do CSGL12Control sobre um Form no Designer, eo painel “Properties
9. Usando dois casos de “CSGL12Control” em um System.Windows.Forms.Form
O diagrama seguinte mostra um exemplo de como duas instâncias do “CSGL12Control” pode ser adicionado a uma System.Windows.Forms.Form para fazer desenhos com OpenGL em um programa.

Um programa com duas instâncias do “CSGL12Control” sobre um System.Windows.Forms.Form
Siga as instruções na seção anterior para adicionar uma única instância do “CSGL12Control” para um “Form”. Então, basta arrastar uma segunda instância do “CSGL12Control” a partir do “Toolbox” ao “Form” para adicionar uma segunda “CSGL12Control”.
Cada instância do “CSGL12Control” variável terá o seu próprio nome. Cada instância do “CSGL12Control” pode ter seus próprios associados evento manipulador classe, ou pode usar instâncias distintas de uma única classe manipulador tipo.
Estude o exemplo “CSGL12Example2” projecto para saber como “CSGL12Control” dois casos podem ter seus eventos enviados para duas distintas instâncias do evento personalizado manipulador classes com funções distintas OpenGL desenho.
O exemplo programa “CSGL12Example2” tem “CSGL12Control” em cada instância de um “SplitContainer” “Control”, simplesmente para demonstrar uma maneira em que instância do “CSGL12Control” pode ser usado. No entanto, os casos de “CSGL12Control” pode ser colocado diretamente em vez de o “Form”.
10. Exemplo C# código para uma “Form” com uma instância do CSGL12Control
O seguinte é o completo C# código contido no arquivo “CSGL12Example1Form.cs”, que faz parte do programa exemplo “CSGL12Example1”.
Este código é aqui apresentado como um simples exemplo de como uma instância de CSGL12Control podem ser criados e utilizados por um “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 o membro “mCSGL12Example1Handler” variável é declarada, para referir-se a uma instância de um class chamado “CSGL12Example1Handler”. Esta classe será descrita em uma seção posterior deste documento. Repare que o construtor para “CSGL12Example1Form” acrescenta os métodos da instância do “CSGL12Example1Handler” ao “multicast delegates” associado com os vários eventos gerados por uma instância de “CSGL12Control”. Isto significa que quando a instância do “CSGL12Control” gera vários eventos, os eventos irão causar diversos métodos da instância do “CSGL12Example1Handler” (ou seja, “mCSGL12Example1Handler”) a ser invocado.
Observe que o membro “mTimer” variável é declarada, para referir-se a uma instância de um class chamado “System.Windows.Forms.Timer”. Este objeto é utilizado para invocar uma função chamada “PrivateTimerTickEventHandler” cada 10 milissegundos. A função exige um método chamado “PrivateTimerTickEventHandler” da instância do “CSGL12Control” (ou seja, “mCSGL12Control1”) que provoca que “Control” de chamar a si próprio. Este é um exemplo de como pode “CSGL12Control” animados em uma taxa aproximada.
Apenas parte da definição de “class CSGL12Example1Form” aparece na C# arquivo chamado “CSGL12Example1Form.cs”. Outra parte da definição de “class CSGL12Example1Form” aparece na C# um arquivo chamado “CSGL12Example1Form.Designer.cs”. Embora arquivos com nomes que correspondam ao padrão “*.Designer.cs” geralmente são criados e modificados apenas pela gráfica “Form Designer” janela de um C# editor, também é possível criar e modificar esses arquivos C# usando um editor de texto.
O seguinte é o completo C# código contido no arquivo “CSGL12Example1Form.Designer.cs”, que faz parte do programa exemplo “CSGL12Example1”.
namespace CSGL12Example1
{
partial class CSGL12Example1Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.mCSGL12Control1 = new CSGL12.CSGL12Control();
this.SuspendLayout();
//
// mCSGL12Control1
//
this.mCSGL12Control1.Anchor = ((System.Windows.Forms.AnchorStyles)
((((System.Windows.Forms.AnchorStyles.Top
| System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.mCSGL12Control1.BackColor = System.Drawing.SystemColors.Control;
this.mCSGL12Control1.Location = new System.Drawing.Point(12, 12);
this.mCSGL12Control1.Name = "mCSGL12Control1";
this.mCSGL12Control1.Size = new System.Drawing.Size(640, 480);
this.mCSGL12Control1.TabIndex = 0;
this.mCSGL12Control1.Text = "CSGL12Control1";
//
// CSGL12Example1Form
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(664, 504);
this.Controls.Add(this.mCSGL12Control1);
this.Name = "CSGL12Example1Form";
this.Text = "CSGL12Example1";
this.ResumeLayout(false);
}
#endregion
private CSGL12.CSGL12Control mCSGL12Control1;
}
}
Repare que este C# código contém a declaração da variável “mCSGL12Control1”, que se refere a uma instância do “class CSGL12.CSGL12Control” (ou seja, “class CSGL12Control” em “namespace CSGL12”). Este exemplo é criado e configurado na função “InitializeComponent”.
11. Manuseando eventos invocada por uma instância de CSGL12Control
A secção anterior mostrou C# um código para “Form” que continha uma única instância do “CSGL12Control”. O código C# adicionar métodos de “class” um evento chamado “CSGL12Example1Handler” como manipuladores para diversos eventos gerados pelo exemplo de “CSGL12Control”.
Aqui está uma lista de eventos de “CSGL12Control” interessante, e os tipos “delegate” associados a esses 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
Apenas o “OpenGLStarted” evento é um evento específico para o tipo “CSGL12Control”.
Todos os outros eventos são padrão System.Windows.Forms eventos, cujo evento tratadores deve ter certos parâmetros (especificado em qualquer Forms documentação).
O “OpenGLStarted” e “Paint” eventos são os mais importantes eventos para OpenGL desenho.
“OpenGLStarted” O evento é invocado antes do primeiro grande evento “Paint” é invocado.
Por isso, o evento “OpenGLStarted” manipulador deve ser adicionado ao controle antes de o controle tem a oportunidade de tentar pintar si mesmo, caso contrário a um evento em tempo não vai ser recebida.
Este evento é uma mera conveniência, e podem ser ignoradas.
No entanto, adicionando um manipulador para este evento torna possível para o manipulador de fazer algum código-uma vez que depende de inicialização OpenGL estar pronto para uso.
(OpenGL não pode ser usado até que a janela da janela existe e está pronto para desempenhar a sua primeira pintura.
Portanto, o evento “OpenGLStarted” poupando o programador a partir do risco de tentativa de utilizar OpenGL demasiado cedo após o programa será iniciado.
) É bastante fácil de adicionar lógica de um manipulador “Paint” para fazer um um-tempo inicialização, utilizando o OpenGL contexto da “CSGL12Control”.
“OpenGLStarted” O evento é oferecido como uma comodidade.
O seguinte é o completo C# código contido no arquivo “CSGL12Example1Handler.cs”, que faz parte do programa exemplo “CSGL12Example1”.
Este código é aqui apresentado como um simples exemplo de como os eventos gerados por uma instância de “CSGL12Control” podem ser manipulados para desenhar utilizando OpenGL.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
// This program requires "references" to the following:
//
// CSGL12DLL.dll (defines CSGL12.GL)
// CSGL12Control.dll (defines CSGL12.CSGL12Control)
using CSGL12;
namespace CSGL12Example1
{
public class CSGL12Example1Handler
{
private Mesh mMesh;
private ShaderProgram mShaderProgram1;
private ShaderProgram mShaderProgram2;
private ShaderProgram mShaderProgram3;
private ShaderProgram mShaderProgram4;
private ShaderProgram mShaderProgramSelected;
private Bitmap mHUDBitmap;
private Texture mHUDTexture;
private Font mFont1;
private Font mFont2;
private Font mFont3;
private Font mFont4;
private Pen mPen1;
private Brush mBrush1;
private double mViewDistance = 800.0;
private double mViewAzimuthDegrees = 0.0;
private double mViewAltitudeDegrees = 0.0;
private double mViewAzimuthDegreesVelocity = 9.0;
private double mViewAltitudeDegreesVelocity = 5.0;
private Point mMouseClientPositionStart;
private double mViewAzimuthDegreesStart = 0.0;
private double mViewAltitudeDegreesStart = 0.0;
public CSGL12Example1Handler()
{
mMesh = new Mesh();
mShaderProgram1 = new ShaderProgramMandelbrotSet();
mShaderProgram2 = new ShaderProgramWood();
mShaderProgram3 = new ShaderProgramBrick();
mShaderProgram4 = new ShaderProgramCartoon();
mShaderProgramSelected = mShaderProgram1;
mHUDBitmap = new Bitmap(512, 512, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
mHUDTexture = new Texture();
mFont1 = new Font("Verdana", 36.0f);
mFont2 = new Font("Verdana", 24.0f);
mFont3 = new Font("Courier New", 16.0f);
mFont4 = new Font("Courier New", 10.0f);
mPen1 = new Pen(Color.Red, 3.0f);
mBrush1 = new SolidBrush(Color.FromArgb(64, 128, 128, 140));
}
public void OpenGLStarted( CSGL12Control csgl12Control )
{
GL gl = csgl12Control.GetGL();
if (null == gl) { return; }
// Load shaders and set variables
if (true == gl.bglCreateProgramObjectARB)
{
if (null != mShaderProgram1)
{
mShaderProgram1.ShaderProgramCreate(gl);
}
if (null != mShaderProgram2)
{
mShaderProgram2.ShaderProgramCreate(gl);
}
if (null != mShaderProgram3)
{
mShaderProgram3.ShaderProgramCreate(gl);
}
if (null != mShaderProgram4)
{
mShaderProgram4.ShaderProgramCreate(gl);
}
}
// Create cube mesh
mMesh = new Mesh();
mMesh.BuildCube(400.0f);
// Create a texture
mHUDTexture.CreateTextureFromBitmap(gl, mHUDBitmap, true);
// To prevent "tearing" (irregular streaks) due to swapping buffers at
// arbitrary times relative to the vsync times, we indicate that we wish
// to wait for vsync before swapping buffers.
// This request applies when the display driver control panel -- in the
// OpenGL settings area -- is set to let the application decide whether or
// not to wait for vsync. Otherwise, the driver control panel overrides
// any request made here.
if (true == gl.bwglSwapIntervalEXT)
{
gl.wglSwapIntervalEXT(1);
}
}
public void Paint(object sender, PaintEventArgs e)
{
if (null == sender) { return; }
if (false == (sender is CSGL12Control)) { return; }
CSGL12Control csgl12Control = (sender as CSGL12Control);
GL gl = csgl12Control.GetGL();
int clientWidth = csgl12Control.ClientRectangle.Width;
int clientHeight = csgl12Control.ClientRectangle.Height;
if (clientWidth <= 0)
{
clientWidth = 1;
}
if (clientHeight <= 0)
{
clientHeight = 1;
}
// Set the viewport
gl.glViewport(0, 0, clientWidth, clientHeight);
// Clear the viewport
gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
// Basic drawing conditions
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL.GL_LEQUAL);
gl.glEnable(GL.GL_CULL_FACE);
gl.glCullFace(GL.GL_BACK);
gl.glFrontFace(GL.GL_CCW);
// PROJECTION matrix, typically for perspective correction or orthographic projection
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
double aspectRatio = 1.0;
if (0 != clientHeight)
{
aspectRatio = ((double)(clientWidth) / (double)(clientHeight));
}
double verticalFieldOfViewAngle = 60.0;
gl.gluPerspective
(
verticalFieldOfViewAngle, // Field of view angle (Y angle; degrees)
aspectRatio, // width/height
0.1, // distance to near clipping plane
64000.0 // distance to far clipping plane
);
// MODELVIEW matrix, typically used to transform individual models
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
// Preserve current matrix for the active matrix stack (in this case the MODELVIEW matrix)
gl.glPushMatrix();
if (mViewAltitudeDegreesVelocity != 0.0)
{
if (mViewAltitudeDegrees > 70.0)
{
mViewAltitudeDegrees = 70.0;
mViewAltitudeDegreesVelocity *= -1.0;
}
else if (mViewAltitudeDegrees < -70.0)
{
mViewAltitudeDegrees = -70.0;
mViewAltitudeDegreesVelocity *= -1.0;
}
mViewAzimuthDegrees += mViewAzimuthDegreesVelocity * csgl12Control.GetPreviousFrameDurationSeconds();
mViewAltitudeDegrees += mViewAltitudeDegreesVelocity * csgl12Control.GetPreviousFrameDurationSeconds();
}
Vector3f from =
new Vector3f
(
(float)(mViewDistance * Math.Cos(mViewAltitudeDegrees * (Math.PI / 180.0)) * Math.Sin(mViewAzimuthDegrees * (Math.PI / 180.0))),
(float)(mViewDistance * Math.Sin(mViewAltitudeDegrees * (Math.PI / 180.0))),
(float)(mViewDistance * Math.Cos(mViewAltitudeDegrees * (Math.PI / 180.0)) * Math.Cos(mViewAzimuthDegrees * (Math.PI / 180.0)))
);
Vector3f to = new Vector3f(0.0f, 0.0f, 0.0f);
Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
Matrix4x4f camera = Matrix4x4f.LookAt(from, to, up);
float[] matrix = new float[16];
matrix[0] = camera.m11;
matrix[1] = camera.m21;
matrix[2] = camera.m31;
matrix[3] = 0.0f;
matrix[4] = camera.m12;
matrix[5] = camera.m22;
matrix[6] = camera.m32;
matrix[7] = 0.0f;
matrix[8] = camera.m13;
matrix[9] = camera.m23;
matrix[10] = camera.m33;
matrix[11] = 0.0f;
matrix[12] = camera.m14;
matrix[13] = camera.m24;
matrix[14] = camera.m34;
matrix[15] = 1.0f;
gl.glMultMatrixf(matrix);
if (mShaderProgramSelected != null)
{
mShaderProgramSelected.DemonstrateModificationOfVariables(gl, csgl12Control.GetPreviousFrameStartTimeSeconds(), csgl12Control.GetPreviousFrameDurationSeconds());
mShaderProgramSelected.Select(gl);
}
// Draw model(s), using active texture or shader
mMesh.Draw(gl);
// If we used a shader, disable it now...
if (true == gl.bglUseProgramObjectARB)
{
ShaderProgram.ShaderProgram_Select(gl, 0);
}
// Restore the previously-preserved matrix for the active matrix stack (in this case the MODELVIEW matrix)
gl.glPopMatrix();
// Demonstrate drawing text to a GDI+ Bitmap and then copying to
// an OpenGL texture.
DemonstrateDrawingTextToAGDIBitmapAndCopyingToAnOpenGLTexture(csgl12Control, gl);
// Flush all the current rendering and flip the back buffer to the front.
gl.wglSwapBuffers(csgl12Control.GetHDC());
}
public void DemonstrateDrawingTextToAGDIBitmapAndCopyingToAnOpenGLTexture(CSGL12Control csgl12Control, GL gl)
{
bool updateOverlayImage = false;
// The following code only enables an update of the Bitmap
// and OpenGL texture every 64 frames, thus avoiding the
// slowdown of performing updates every single frame.
// HOWEVER, updating the Bitmap and OpenGL texture can be
// done EVERY frame with acceptable speed.
// Updates should be limited to once per frame, but the
// logic to trigger updates can be based on when the relevant
// text changes.
if ((csgl12Control.GetTotalFramesDrawn() % 64) == 0)
{
updateOverlayImage = true;
}
bool showOverlayImage = true;
if (true == updateOverlayImage)
{
using (Graphics g = Graphics.FromImage(mHUDBitmap))
{
g.Clear(Color.FromArgb(0, Color.White));
g.FillEllipse(mBrush1, new Rectangle(0, 0, 256, 256));
g.FillEllipse(mBrush1, new Rectangle(256, 256, 256, 256));
PointF center = new PointF(0.5f * (256.0f + 0.0f), 0.5f * (256.0f + 0.0f));
PointF displacement = new PointF();
double fraction = csgl12Control.GetTotalElapsedTimeSeconds() * 0.1;
displacement.X = 128.0f * (float)Math.Cos(2.0 * Math.PI * fraction);
displacement.Y = 128.0f * (float)Math.Sin(2.0 * Math.PI * fraction);
g.DrawLine(mPen1, center, new PointF(center.X + displacement.X, center.Y + displacement.Y));
PointF carat = new PointF(0.0f, 0.0f);
String text = "";
text = "C# OpenGL (CSGL)";
g.DrawString(text, mFont1, Brushes.Black, carat);
carat.Y += mFont1.GetHeight();
text = "Здравствуйте";
g.DrawString(text, mFont2, Brushes.Black, carat);
carat.Y += mFont2.GetHeight();
text = "γεια σου";
g.DrawString(text, mFont2, Brushes.Black, carat);
carat.Y += mFont2.GetHeight();
text = "مرحبا";
g.DrawString(text, mFont2, Brushes.Black, carat);
carat.Y += mFont2.GetHeight();
text = "שלום";
g.DrawString(text, mFont2, Brushes.Black, carat);
carat.Y += mFont2.GetHeight();
carat.Y += 64.0f;
text = "Shift + 0: Save BMP,PNG,JPG,GIF";
g.DrawString(text, mFont4, Brushes.Black, carat);
carat.Y += mFont4.GetHeight();
text = "1,2,3,4 : Switch shader program";
g.DrawString(text, mFont4, Brushes.Black, carat);
carat.Y += mFont4.GetHeight();
carat.Y += 12.0f;
text = "Text : GDI+ on 512*512 Bitmap.";
g.DrawString(text, mFont4, Brushes.Black, carat);
carat.Y += mFont4.GetHeight();
text = "Bitmap copied to OpenGL texture.";
g.DrawString(text, mFont4, Brushes.Black, carat);
carat.Y += mFont4.GetHeight();
text = "Texture update once per 64 frames,";
g.DrawString(text, mFont4, Brushes.Black, carat);
carat.Y += mFont4.GetHeight();
text = "but more often would be OK.";
g.DrawString(text, this.mFont4, Brushes.Black, carat);
carat.Y += this.mFont4.GetHeight();
carat.Y += 12.0f;
text = String.Format("Frame:{0}", csgl12Control.GetTotalFramesDrawn());
text += " ";
text += String.Format("Time:{0:f2}", csgl12Control.GetTotalElapsedTimeSeconds());
double previousFrameDurationSeconds =
csgl12Control.GetPreviousFrameDurationSeconds();
if (previousFrameDurationSeconds > 1.0e-10)
{
double framesPerSecondOverall =
1.0 / previousFrameDurationSeconds;
text += " ";
text += String.Format("FPS:{0:f2}", framesPerSecondOverall );
}
g.DrawString(text, mFont3, Brushes.Black, carat);
carat.Y += mFont3.GetHeight();
}
mHUDTexture.UpdateTextureWithBitmapData(gl, mHUDBitmap);
}
if (true == showOverlayImage)
{
CSGL12Support.SupportDrawTextureImageUnrotatedAndOrthographically
(
gl,
csgl12Control.ClientSize.Width,
csgl12Control.ClientSize.Height,
mHUDTexture,
0,
0, // i.e., 0 == draw TOP of image at TOP of viewport, Y-axis points DOWN
mHUDTexture.GetWidth(), // glControl.ClientSize.Width, // mHUDTexture.GetWidth(),
mHUDTexture.GetHeight() // glControl.ClientSize.Height // mHUDTexture.GetHeight()
);
}
}
public void KeyDown(object sender, KeyEventArgs e)
{
if (null == sender) { return; }
if (false == (sender is CSGL12Control)) { return; }
CSGL12Control csgl12Control = (sender as CSGL12Control);
GL gl = csgl12Control.GetGL();
if (e.KeyCode == Keys.A)
{
}
if (e.KeyCode == Keys.Z)
{
}
if (e.KeyCode == Keys.D1)
{
mShaderProgramSelected = mShaderProgram1;
}
if (e.KeyCode == Keys.D2)
{
mShaderProgramSelected = mShaderProgram2;
}
if (e.KeyCode == Keys.D3)
{
mShaderProgramSelected = mShaderProgram3;
}
if (e.KeyCode == Keys.D4)
{
mShaderProgramSelected = mShaderProgram4;
}
// NOTE: The only way for cursor key events (up,down,left,right)
// to make it to this function is for the main form to implement
// the following:
//
// protected override bool ProcessDialogKey ( Keys keyData )
//
// and explicitly invoke this KeyDown() method with the
// an appropriately formed KeyEventArgs instance.
if (e.KeyCode == Keys.Up)
{
mViewDistance -= 10.0;
}
if (e.KeyCode == Keys.Down)
{
mViewDistance += 10.0;
}
if (e.KeyCode == Keys.Left)
{
mViewAzimuthDegrees += 1.0;
}
if (e.KeyCode == Keys.Right)
{
mViewAzimuthDegrees -= 1.0;
}
// Save an image of the viewport (press Shift-0 (zero)). The following
// code writes out the viewport in the following image formats: BMP, PNG, GIF, JPG.
// If you only want a single format, comment out the other file write commands.
// BMP has no compression artifacts, but the file can be quite large.
// PNG looks good, and supports 8-bit transparancy (good for textures, etc).
// GIF looks bad unless you build the color table intelligently (there is a
// neural network color table builder for GIF, in C#/.NET, that you can
// find on the Internet; perhaps Paint.NET uses that code); but GIF files
// can be quite small, and supports animation.
// JPG looks good under most circumstances, and the file size can be quite small,
// but transparency is not supported.
// So, for pixel-perfect images, where file size is not important, BMP might be appropriate.
// For textures with transparency, PNG might be appropriate.
// For good-looking images, and small file size, and use in Web pages, JPG might be appropriate.
// For some purposes, with small file sizes, and use in Web pages, GIF might be appropriate.
if ((e.KeyCode == Keys.D0) && (e.Shift == true))
{
DateTime now = DateTime.Now;
String dateTimeString = String.Format("{0:d4}{1:d2}{2:d2}{3:d2}{4:d2}{5:d2}{6:d3}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Millisecond);
String frameIndexString = String.Format("{0:d6}", csgl12Control.GetTotalFramesDrawn());
String fileNameWithoutExtension = "screen" + "_" + dateTimeString + "_" + frameIndexString;
CSGL12Support.SupportWriteViewportToImageFile(gl, fileNameWithoutExtension + ".bmp", System.Drawing.Imaging.ImageFormat.Bmp);
CSGL12Support.SupportWriteViewportToImageFile(gl, fileNameWithoutExtension + ".png", System.Drawing.Imaging.ImageFormat.Png);
CSGL12Support.SupportWriteViewportToImageFile(gl, fileNameWithoutExtension + ".gif", System.Drawing.Imaging.ImageFormat.Gif);
CSGL12Support.SupportWriteViewportToImageFile(gl, fileNameWithoutExtension + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
public void KeyUp(object sender, KeyEventArgs e)
{
}
public void MouseDown(object sender, MouseEventArgs e)
{
if (null == sender) { return; }
if (false == (sender is CSGL12Control)) { return; }
CSGL12Control csgl12Control = (sender as CSGL12Control);
mMouseClientPositionStart = csgl12Control.PointToClient(Cursor.Position);
mViewAzimuthDegreesStart = mViewAzimuthDegrees;
mViewAltitudeDegreesStart = mViewAltitudeDegrees;
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
mViewAzimuthDegreesVelocity = 0.0;
mViewAltitudeDegreesVelocity = 0.0;
}
if ((e.Button & MouseButtons.Right) == MouseButtons.Right)
{
mViewAzimuthDegreesVelocity = 9.0;
mViewAltitudeDegreesVelocity = 5.0;
}
}
public void MouseUp(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Right) == MouseButtons.Right)
{
}
}
public void MouseMove(object sender, MouseEventArgs e)
{
if (null == sender) { return; }
if (false == (sender is CSGL12Control)) { return; }
CSGL12Control csgl12Control = (sender as CSGL12Control);
Point mouseClientPositionCurrent = csgl12Control.PointToClient(Cursor.Position);
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
double azimuth =
mViewAzimuthDegreesStart
- (360.0 / (double)(csgl12Control.Width + 1))
* (double)(mouseClientPositionCurrent.X - mMouseClientPositionStart.X);
double altitude =
mViewAltitudeDegreesStart
+ (180.0 / (double)(csgl12Control.Height + 1))
* (double)(mouseClientPositionCurrent.Y - mMouseClientPositionStart.Y);
double epsilon = 0.05;
if (azimuth < (-180 + epsilon)) { azimuth = (-180 + epsilon); }
if (azimuth > (180 - epsilon)) { azimuth = (180 - epsilon); }
if (altitude < (-90 + epsilon)) { altitude = (-90 + epsilon); }
if (altitude > (90 - epsilon)) { altitude = (90 - epsilon); }
mViewAzimuthDegrees = azimuth;
mViewAltitudeDegrees = altitude;
}
}
public void MouseWheel(object sender, MouseEventArgs e)
{
mViewDistance -= 0.1 * (double)e.Delta;
}
}
}
Observe que a função chamada “OpenGLStarted” é utilizado neste exemplo para criar “pixel shader programs” e OpenGL uma textura. Para este programa, apenas precisamos criar esses recursos uma vez, e é mais eficiente para criá-los apenas uma vez.
Observe que a função chamada “OpenGLStarted” o código verifica se um WGL “extension” função chamada “wglSwapIntervalEXT()” existe, e, se essa função não existir, o código chama essa função. Esta função define uma situação que afecta o funcionamento do programa para toda a sessão, e para isso precisamos de chamar a função apenas uma vez, e é por isso que tentam chamar a função no “OpenGLStarted” função (que por si só é invocado uma vez, quando OpenGL é iniciado por um particular “CSGL12Control”, assumindo acrescentámos “OpenGLStarted” o método adequado para o evento delegado).
A função chamada “Paint” contém todo o código para desenhar um único “quadro” de animação utilizando OpenGL. O “Paint” função será chamada talvez 60 vezes por segundo, devido ao facto de os associados “CSGL12Control” exemplo está a ser “invalidados” (forçada a chamar novamente própria) a essa taxa. (Olha o “Form” código de exemplo na seção anterior para ver o cronômetro que determina a taxa de “nulidade” e da real função chamada que provoca a instância do “CSGL12Control” se tornar “invalidados.)”
Todas as funções são invocadas OpenGL usando uma instância do “class GL” (exemplo: gl.gl*()). A exemplo do “class GL” é adquirido a partir do exemplo de “CSGL12Control”, que é armazenado implicitamente no primeiro parâmetro para o “Paint” função.
Todos os OpenGL constantes pode ser especificado pelo “class” especificando o nome “GL” seguido por um ponto eo nome da constante, ou seja, “GL.GL_TRIANGLES”.
O OpenGL código neste exemplo não é totalmente claro e fácil de compreender, mas espero que você pode reconhecer o modo como o código pode ser modificado para seus próprios fins.
12. Verificando a disponibilidade de uma função de “extensão” OpenGL
Basta verificar se o sinalizador Booleano do mesmo nome que o OpenGL função é “verdade” antes de tentar utilizar a função correspondente.
O Boolean variável tem um nome que começa com “b” seguido pelo OpenGL função nome.
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.
// . . .
}
Verificação só é necessária para a “extensão” funções.
OpenGL 1.1 funções, e todas as funções GLU, e núcleo WGL funções, não exigem tais testes. No entanto, Boleano bandeiras existem, e são fixados adequadamente, para todas as funções fornecidas por “class GL”, incluindo o núcleo OpenGL 1.1 funções. Assim, existe uma forma coerente a fim de verificar a disponibilidade de todas as funções em que a classe.
Sabendo ou não uma função é uma “extensão” é de responsabilidade do programador.
No entanto, a função nome sufixos, tais como “EXT”, “ARB”, “MESA”, “NV” (NVidia), “APPLE”, etc, contribuir para indicar extensão funções.
Se uma função “gl*()” tem uma função “gl*ARB()” vizinhas ou “gl*NV()” e, em seguida, a função “gl*()” é provavelmente uma extensão (no que diz respeito à Windows OPENGL32.DLL está em causa).
A única vantagem de conhecer ou não uma função é uma “extensão” (no que diz respeito à Windows OPENGL32.DLL) está a ser capaz de evitar a verificar se estão disponíveis funções.
Você pode procurar por todos os OpenGL funções usadas em seu código e, em seguida, construir uma lista alfabética das diferentes funções usadas.
Depois, no início de seu programa, após a CSGL12Control chama o delegado OpenGLStarted, basta verificar todos Boleano bandeiras para todas as funções que pretende utilizar.
Se você optar por encerrar o programa se houver “exigidas” funções são inexistentes e, em seguida, todos os controlos de tais funções no código pode ser eliminada.
Além disso, você pode formar um grupo de não-funções essenciais no controlo e, eventualmente, informar o usuário de qualquer característica mudanças e, possivelmente, deixar controlos dispersos em torno do código.
OpenGL com mais experiência, você pode ter uma noção do que estão relacionadas com extensões (exemplos: imagiologia, sombreador, amortecedores, compressão, ...).
Portanto, você pode verificar a presença de uma única função crítica e utilizar essa informação para decidir se a todo o subconjunto é susceptível de estar presente.
13. Velocidade
Por diversas razões, C# é mais lento do que non-CLR C/C++.
C# é eventualmente compilados para montagem idioma nativo, assim como para C/C++, mas, devido aos protestos feitos pela C# linguagem eo .NET CLR, a velocidade global de software construída C# e .NET é ligeiramente mais lento do que o software construído usando non-CLR C/C++.
Assim, recebendo a maior velocidade possível utilizar meios non-CLR C/C++ ao invés de C#.
Além disso, uma vez chamando a partir de qualquer biblioteca nativa C# envolve P/Invoke, invocando funções tais como a OpenGL funções irá requerer algum tempo para desempenhar o trabalho em P/Invoke camada.
No entanto, parece “CSGL12” para trabalhar com rapidez suficiente para ser usado por muitos efeitos gráficos em tempo real, tais como jogos de simples, os telespectadores 3D, editores, ou apresentações em 3D. Isto é especialmente verdade se a maior parte do trabalho está sendo feito pela GPU vez dos CPU.
14. Comparação entre “CSGL12” e os “Tao Framework”
O “Tao Framework” é uma grande biblioteca C# / .NET que fornece uma interface para muitas bibliotecas de código aberto, tais como OpenGL, OpenAL (áudio), SDL (um jogo / simulação plataforma), Open Dynamics Engine (ODE) (física), etc
O Tao Framework é cross-platform (Windows, Linux, Mac OS X).
“CSGL12” só fornece uma interface para OpenGL e é apenas para o Windows sistema operativo.
O Tao Framework tem uma comunidade. Uma pessoa pode se beneficiar de comunicar com outros usuários do Tao Framework.
No entanto, pode haver muitas finalidades para as quais “CSGL12” poderia ser mais fácil de usar para Windows programas.