GDI+ i OpenGL

Sven Nilsen, student 2006

Det er ikke så lett å få til 2D-grafikk med bare polygoner som hjelpemiddel. Jeg ønsker å kunne bruke GDI+ kommandoer til å tegne mer avansert 2D-grafikk, som skal ligge oppå 3D-grafikken som tegnes i resten av programmet. Teknikken skal brukes til å lage interaktive kontroller.

Innledning

GDI+ er et kraftig verktøy for 2D-grafikk som vi finner i C# og andre .NET-språk. Det går ann å tegne med GDI+ på Bitmap-objekter (System.Drawing.Bitmap) som er en del av .NET Framework.

Med Tao OpenGL kan man gjøre om Bitmap-objekter til teksturer. Ved tegning kan man først kalle opp rutinene som tegner med GDI+. Dette gjøres på et Bitmap-objekt. Så gjøres Bitmap-objektet om til en tekstur, og tegnes som en quad. Bildet kan også være delvis transparent. Når man skal tegne menyer og 2D-kontroller, er det ikke nødvendig å ha med dybdetesting. Uten dybdetesting går det også raskere.

Struktur for grensesnitt

Vi lager en enkel modell for hvordan vi vil bygge opp et grensesnitt i 2D: Hver kontroll tegnes på et bilde av samme størrelse som kontrollen. Størrelset på bildet må ha dimensjoner 2^n i høyde og bredde for å kunne gjøres om til tekstur. Denne størrelsen kan man regne ut automatisk ved følgende funksjon:

private int BufferSize(int size)
{
    return (int)(Math.Pow(2, Math.Ceiling(Math.Log(size) / Math.Log(2))));
}

Etter at vi har tegnet utseendet til kontrollen på bildet, tegnes bildet som en tekstur på et polygon:

Vi trenger ikke bare tegning, men brukeren skal også kunne kommunisere med kontrollen ved hjelp av musen. For at ikke flere kontroller skal krangle om hvem som skal kommunisere, lager vi en klasse for å holde styr på hvem som til enhver tid kommuniserer med musen. Klassen kaller vi ControlManager, og den tar seg av både tegning av kontroller og kommunisering mellom bruker og kontroll.

Alle kontroller må arve fra klassen SimpleControl. Denne klassen inneholder egenskaper for posisjon og størrelse til kontrollen.

Objekthiarki

Så lenge ingen av kontrollene kommuniserer med brukeren, blir alle kontroller spurt om de vil opprette kommunikasjon etter hvert som brukeren flytter musen. Sjekken skjer mot en rektangel som definerer plassering og størrelsen av kontrollen. Dersom musen befinner seg innenfor en slik rektangel, spørres kontrollen som denne rektangelen tilhører om den vil opprette kommunikasjon. Hvis ikke kontrollen vil, fortsetter sjekkingen med de andre kontrollene. Sjekkingen skjer i motsatt rekkefølge av tegnerekkefølgen, slik at kontroller som tegnes øverst, vil spørres først.

I ControlManager er det variabelen ’m_capturingControl’ som bestemmer hvilken kontroll som har kommunikasjonen.

Når en kontroll oppretter kommunikasjon, får den tilsendt et objekt som representerer vinduet grafikken tegnes i. Gjennom dette objektet kan kontrollen koble seg på de ulike input den ønsker. Så lenge musen beveger seg, spørres kontrollen om den vil avslutte kommunikasjonen. Når kommunikasjonen er avsluttet, kan andre kontroller opprette kommunikasjon.

Ved denne metoden kan for eksempel brukeren flytte en slidebar på maksverdi uten å miste ”taket” når musen forflytter seg utenfor kontrollen.

Effekter og farger

Spill og 3D grafikk oppdaterer tegning vanligvis et visst antall ganger i sekundet. Dette kan vi utnytte til å lage effekter som endrer seg over tid. For eksempel kan fargen på knapper endres gradvis når brukeren holder musen over den.

Den enkleste måten å lage en fade-effekt med farger, er å lage en egen klasse som håndterer dette. Vi har kalt klassen vår for ’ColorFadeEffect’. Klassen inneholder to metoder, en for å starte fading, og en for å gå tilbake. Intervallet bestemmes i millisekunder, og angir hvor lang tid det skal gå før fargen er ferdig fadet. ’ColorFadeEffect’ har innebygd funksjon for å fortsette fra det stedet man var sist, dersom fargen var halveis ferdig fadet før man vil gå tilbake. Kontrollen som skal fade farge, oppretter et objekt av typen ’ColorFadeEffect’, og henter ut fargen med funksjonen ’GetColor’.

Ofte ønsker man et spesielt utseende på grensesnittet som passer til programmet man lager. Ved å la alle kontroller bestemme fargevalg ut ifra en felles klasse, behøver man ikke å endre fargene flere steder siden. Klassen heter ’GuiLook’. Hver kontroll får angitt et GuiLook-objekt i konstruktøren.

Referanser

Forklaringer

Event - En måte å abonnere på en hendelse i .NET språk. Funksjoner kan kobles mot en event, og funksjonen blir da kalt opp når hendelsen skjer.

Eksempel

Se
Shape Blending