En dator är dum dum burk men med stor potensial. Det kluriga med realtids-3d-programmering är att allt ska gå fort. För att det ska gå fort ska inte datorn beräkna massa onödiga beräkningar på sånt som inte är synligt i skärmen för tillfället. dvs. regel nummer ett:
Allt som inte syns ska INTE finnas!
Detta kallas CULLING.
Min terräng måste vara intelligent dvs, bara de delar av terrängen som för tillfället syns på skärmen ska beräknas och renderas! Detta är inte så lätt som det låter eftersom en terräng är som ett stort rutnät av trianglar som man inte bara kan klippa i hur som helst.
CULLING är A och O i spelprogrammering eftersom det är avgörande för om ett spel kommer bli spelbart i slutändan.
Den teknik jag ska använda för culling heter Quad-Tree culling, dvs terrängen kommer från början dela upp sig i 4 mindre terräng-partitioner som i sin tur delar upp sig i 4 partitioner var så det blir 16, som i sin tur delar sig osv.
Till slut kommer terrängen bestå av en jäkla massa små partitioner i lämplig storlek.
Varför? JO istället för en stor terräng så skapar jag en massa mindre terräng-partitioner som är självtänkande men ändå sammarbetar med varnadra. Varje partition ska känna av om den befinner sig i synfältet och beräkna sig själv om den gör det. Annars ska den INTE beräkna sig själv.
Resultatet blir att bara de partitioner som finns i synfältet kommer beräkna sig själva och skapa en terräng inte EXISTERAR bakom kameran. Coolt va? Det är inget som en spelare märker med är fullständigt nödvändigt för att ett spel ska fungera
läs mer om quadtree-culling: http://en.wikipedia.org/wiki/Quadtree
måndag 27 oktober 2008
En intelligent terräng
Det var ett tag sen jag skrev. Under de senaste tiden har jag jobbat på att utvecklat min terräng rejält.
En rödfärgad terräng är inte speciellt snyggt utan jag har utvecklat mer realistiska terräng-material såsom berg och gräs, Sådana material ligger som en yta på terrängen och kallas texturer
Min terräng är helt och hållen ritat med triangle-strip som grund, triangle-list skulle vara enklare men tar mer plats i index-bufferten. Här är strukturen för min terrain-vertex. Den har för tillfället givetivs en vector3 position i värld-matrisen, en textur-koordinat.
Jag tog bort stödet för normaler eftersom terrängen ska vara statisk, ev läsa in normaler från en normalmap.
Arrayen med vertexellement är nödvändig för till ex vertex-deklaration, och när vertexen ska läsas i en ström.
den har också en statisk variabel för sin egen storlek i bytes.
public struct TerrainVertex
{
public Vector3 Position;
public Vector2 TextureCoordinate;
public static readonly VertexElement[] VertexElements =
{
new VertexElement(0,0,VertexElementFormat.Vector3,VertexElementMethod.Default,VertexElementUsage.Position,0),
new VertexElement(0,sizeof(float)* 3,VertexElementFormat.Vector2,VertexElementMethod.Default,VertexElementUsage.TextureCoordinate,0)
};
public static readonly int SizeInBytes = sizeof(float) * (3 + 2 );
}
eftersom terrängen kommar ha mellan 6 till 10 texturer (om jag får bestämma) med olika blendweights så är det inte att föredra att kasta runt massa texturer i parametrar. jag har därför också skapat en enklare textur inehållande terrängen alla material:
//En struktur för ett material med 4 texturer;
public struct TerrainMaterial
{
public Texture2D texture1;
public Texture2D texture2;
public Texture2D texture3;
public Texture2D texture4;
public Texture2D mipMap1;
public float scale;
}
En rödfärgad terräng är inte speciellt snyggt utan jag har utvecklat mer realistiska terräng-material såsom berg och gräs, Sådana material ligger som en yta på terrängen och kallas texturer
Min terräng är helt och hållen ritat med triangle-strip som grund, triangle-list skulle vara enklare men tar mer plats i index-bufferten. Här är strukturen för min terrain-vertex. Den har för tillfället givetivs en vector3 position i värld-matrisen, en textur-koordinat.
Jag tog bort stödet för normaler eftersom terrängen ska vara statisk, ev läsa in normaler från en normalmap.
Arrayen med vertexellement är nödvändig för till ex vertex-deklaration, och när vertexen ska läsas i en ström.
den har också en statisk variabel för sin egen storlek i bytes.
public struct TerrainVertex
{
public Vector3 Position;
public Vector2 TextureCoordinate;
public static readonly VertexElement[] VertexElements =
{
new VertexElement(0,0,VertexElementFormat.Vector3,VertexElementMethod.Default,VertexElementUsage.Position,0),
new VertexElement(0,sizeof(float)* 3,VertexElementFormat.Vector2,VertexElementMethod.Default,VertexElementUsage.TextureCoordinate,0)
};
public static readonly int SizeInBytes = sizeof(float) * (3 + 2 );
}
eftersom terrängen kommar ha mellan 6 till 10 texturer (om jag får bestämma) med olika blendweights så är det inte att föredra att kasta runt massa texturer i parametrar. jag har därför också skapat en enklare textur inehållande terrängen alla material:
//En struktur för ett material med 4 texturer;
public struct TerrainMaterial
{
public Texture2D texture1;
public Texture2D texture2;
public Texture2D texture3;
public Texture2D texture4;
public Texture2D mipMap1;
public float scale;
}
tisdag 21 oktober 2008
HöjdMapp

Jag har även skapat en funktion för att räkna ut höjpunkter på min terräng utifrån en höjdmapp d.v.s. en vanlig bildfil där varje pixel motsvarar en vertex i terrängen. pixeln's ljusstyrka bestämmer sedan höjden där. färgen vit (255,255,255) är hösta punkt och svart (0,0,0) är lägsta. Här använder jag en egenskriven shader som ger färg till terrängen utifrån höjd-skillnad. fullkommligt värdelös shader men ändå:P
Nosie shaded

Min noise-terräng med standard-Shader. En sak att tillägga är att jag även skapat en funktion som räkanar ut normalen för varje vertex d.v.s. riktingen dit vertexen pekar. Normalen behövs för att beräkna en enkel sljussättning och är beräknad på kors-produkten mellan "kanterna" på varje triangel. Korsprodukten är en funktion som är super som jag inte orkar förklara här för min blogg skulle bli oändlig men läs om den här: http://en.wikipedia.org/wiki/Cross_product
Lite kullar i landskapet
Ett landskap
Sen senaste gången jag skrev har jag JOBBAT 66 H på motorn. Min första kamera är klar och fungerar bra. Jag har dessutom skapat en början på min s.k. "Terräng-Motor" som kommer ligga till grund till mycket av 3D-motorn. Jag skanckade tidigare om att en triangel uppbyggd av 3 Vertex med 3 coordinater var.
Terräng-motorns uppgift är att utifrån en längd och en bredd skapa ett "rutnät" med massor av trianglar som tillsammans ska bilda ett vackert lanskap med kullar berg och dalar!
1: Jag började med en ekvation för att placera ut mina Vertices i ett rutnät utifrån en höjd och bredd
2: Utifrån mina vertex skapade jag ett s.k. Index. Ett index är en massa siffror som härleder till mina vertex och som hjälper grafik-enheten i datorn att behandla mina data.
3: All data för för jag sedan över till grafik-enheten's internminne med en s.k VertexBuffert för mina Vertices och en IndexBuffert för min Indices. Anlendningen är att grafik-kortet behöver dessa data för att skapa mina trianglar och om de redan ligger på grafik-kortet blir det väldigt lätt-tillgängla och hela processen går snabbare! Tänk dig själv behöva springa ner till hemköp och köpa en penna varje gång du skulle skriva nåt istället för att bara öppna skrivbords-lådan?
4: Jag har en funktion som i princip startar igen precis när den tagit slut. Positionerar jag ut mina vertex och indices från buffertarna på min World-Matrix,
5: Varje vertex flyger iväg i en ström till en "Shader" som "färglägger" dom försig. Som ett rullband i en leksaksfrabrik med bollar som ska färgläggas! Jag ger även instruktioner om hur stor varje Vertex är i bytes för att veta precis var på strömmen en vertex slutar och nästa börjar.
6: Varje vertex blir positionerad utifrån min Kameras Projection-Matrix och min View-matrix.
Detta placera dom på en 2d-skärm fast skapar känslan av en 3d-Värld!
Resultatet ser ni här. Jag har inte angivit någon speciell färg än så jag renderar d.v.s ritar dem ihåliga i s.k. wireframe-stadium.
Terräng-motorns uppgift är att utifrån en längd och en bredd skapa ett "rutnät" med massor av trianglar som tillsammans ska bilda ett vackert lanskap med kullar berg och dalar!
1: Jag började med en ekvation för att placera ut mina Vertices i ett rutnät utifrån en höjd och bredd
2: Utifrån mina vertex skapade jag ett s.k. Index. Ett index är en massa siffror som härleder till mina vertex och som hjälper grafik-enheten i datorn att behandla mina data.
3: All data för för jag sedan över till grafik-enheten's internminne med en s.k VertexBuffert för mina Vertices och en IndexBuffert för min Indices. Anlendningen är att grafik-kortet behöver dessa data för att skapa mina trianglar och om de redan ligger på grafik-kortet blir det väldigt lätt-tillgängla och hela processen går snabbare! Tänk dig själv behöva springa ner till hemköp och köpa en penna varje gång du skulle skriva nåt istället för att bara öppna skrivbords-lådan?
4: Jag har en funktion som i princip startar igen precis när den tagit slut. Positionerar jag ut mina vertex och indices från buffertarna på min World-Matrix,
5: Varje vertex flyger iväg i en ström till en "Shader" som "färglägger" dom försig. Som ett rullband i en leksaksfrabrik med bollar som ska färgläggas! Jag ger även instruktioner om hur stor varje Vertex är i bytes för att veta precis var på strömmen en vertex slutar och nästa börjar.
6: Varje vertex blir positionerad utifrån min Kameras Projection-Matrix och min View-matrix.
Detta placera dom på en 2d-skärm fast skapar känslan av en 3d-Värld!
Resultatet ser ni här. Jag har inte angivit någon speciell färg än så jag renderar d.v.s ritar dem ihåliga i s.k. wireframe-stadium.
måndag 13 oktober 2008
En första början
Det är ju en fördel om man kan förflytta sig i sin 3d-miljö så steg ett blir att skapa en "kamera" dvs en visuell effekt av att man "förflyttar sig" över världen.
Jag har altså skapat denna kamera utifrån matriser. Vi kan säga att en matris i stort sett är en liten finurlig tabell med i detta fall 12 tal fördelat på 4 rader och 4 columner. Med detta 4x4 matrix kan utföra beräkningar och magiskt :)
Min "kamera" är igentligen en blandning utav 3 st 4x4 matriser,
en matris som skapar mitt unika kameraperspektiv min "projection matrix"
en matris för kamerans vy, min "View matrix"
och en matrix för kamerans position och orientering i min värld, min "World Matrix"
Jag har sedan lagt till nödvändiga funktioner för att påverka kamerans position och riktning mha tangentbordet, för att fritt kunna förflytta min "kamera" över världen. :D
Efter jag skapat det grundläggande funktionerna för initsiering, uppdatering av logisk data, och funktion för uppdatering av bildskärmen, skapar jagen nu klass Camera och ett tillhörande Interface ICamera, fördelen med att låta kameraklassen ärva från ett interface är att jag kan implentera hur många kameror jag vill utan andra klasser som uppdateras i kameran påverkas!
Så länge den nya kameran förljer kriterierna för interfacet.
Interfacet deklarerar variabler:
public interface ICamera
{
Matrix ViewMatrix { get;}
Matrix ProjectionMatrix { get;}
Vector3 Position { get;}
}
det räcker för tillfället ;)
Min första kamera kommer fungera som en flygande FPSkamera och följa musen och tangenterna WASD.
Interfacet ICamera skapa jag dessutom som en "komponent" som blir åtkomlig från spelets basklass. Det gör det lättare att kasta runt adressen till kameran till alla objekt som kommer behöva den för att räkna ut hur den ska ritas.
Jag har altså skapat denna kamera utifrån matriser. Vi kan säga att en matris i stort sett är en liten finurlig tabell med i detta fall 12 tal fördelat på 4 rader och 4 columner. Med detta 4x4 matrix kan utföra beräkningar och magiskt :)
Min "kamera" är igentligen en blandning utav 3 st 4x4 matriser,
en matris som skapar mitt unika kameraperspektiv min "projection matrix"
en matris för kamerans vy, min "View matrix"
och en matrix för kamerans position och orientering i min värld, min "World Matrix"
Jag har sedan lagt till nödvändiga funktioner för att påverka kamerans position och riktning mha tangentbordet, för att fritt kunna förflytta min "kamera" över världen. :D
Efter jag skapat det grundläggande funktionerna för initsiering, uppdatering av logisk data, och funktion för uppdatering av bildskärmen, skapar jagen nu klass Camera och ett tillhörande Interface ICamera, fördelen med att låta kameraklassen ärva från ett interface är att jag kan implentera hur många kameror jag vill utan andra klasser som uppdateras i kameran påverkas!
Så länge den nya kameran förljer kriterierna för interfacet.
Interfacet deklarerar variabler:
public interface ICamera
{
Matrix ViewMatrix { get;}
Matrix ProjectionMatrix { get;}
Vector3 Position { get;}
}
det räcker för tillfället ;)
Min första kamera kommer fungera som en flygande FPSkamera och följa musen och tangenterna WASD.
Interfacet ICamera skapa jag dessutom som en "komponent" som blir åtkomlig från spelets basklass. Det gör det lättare att kasta runt adressen till kameran till alla objekt som kommer behöva den för att räkna ut hur den ska ritas.
söndag 12 oktober 2008
Hur ritar man i 3 dimensioner?
Tänkt dig en bild du ritat i datorn. den är alltid rektangulärt formad. Tänk dig att man delar bilden längst diagonalen och får en .... Triangel!
en triangel är enkelt sagt grunden till att rita i 3-d. Varför just triangel? Av trianglar kan man skapa vad som helst! Du kan skapa till exempel en raktangel.
varje triangel har i sin tur 3 punkter som definierar rektangelns hörn. Skulle man rita en triangel i en graf skulle varje punkt ha två koordinater, en -X och en -Y koordinat.
När man skapar en vision av 3D måste man ha en till axel på grafen, en -Z axel! För att rita en triangle i en 3D-graf behöver altså varje punkt av trianglen ha 3 koordinater!
En exempel triangel, varje nummer motsvarar en koordinat i ordningen X,Y,Z:
(0,0,0)
(5,10,-4)
(10,0,-2)
i en 3D -graf motsvarar detta en triangel med sin högsta punkt 10 lite snett lutad bakåt i en 3D-graf! Detta motsvaras av tre punkter som i 3D-språk kallas VERTEX. Varje vertex har i sin tur en position med tre koordinater. En sådan position kallas VEKTOR. Dessa ord kommer jag använda framöver.
Tänk dig sen att man skapar flera tusen trianglar med 3 koordinater för att skapa en 3-dimisionell figur! Dvs ALLT i en 3D motor kommer ritas på en 3D-graf av just BARA trianglar sammansatta till olika former,
Jag lovar, till och med den rundaste boll i FIFA 08 är gjord av kantiga men ack så användbara trianglar med tre vektorer!
Så långt har jag kommit hittils
När jag skriver detta är jag precis klar med en "grund" till motorn. Jag har i princip gjort så att jag kan "rita" det jag vill på skärmen. Samt en viualisering av att skärmen faktiskt blir 3-dimisionell! Nu ska jag börja med steg 3.
Vad ska en 3d-motor innehålla?
Först och främst, för att någonting ska kunna visas på datorskärmen behöver man någonting som "ritar" upp det. Sånt sker inte automatiskt utan det får man skriva själv. Det är ju en fördel i ett spel att man ser något på skärmen och inte bara en tom bildskärm.
Nummer två: bildskämen är platt som en pankaka, MEN spelet måste ju ha ett djup. Man ska kunna se en massa Rum, och gubbar som springer runt och kanske ett snyggt landskap med träd. Hur skulle det se ut om allt skulle vara platt? Man måste skapa en "mekanism" som ger spelaren en Vision att han faktiskt befinner sig i ett lanskap som sträcker sig flera mil bårt, och inte framför en platt skärm. Denna "vision" är grunden till 3D-grafik. En dataskärm har bara 2 dimensioner dvs bredd och höjd, men man skapar visionen av att det finns 3-dimensioner! Vi lurar spelaren öga att 3-dimensioner existerar fast han bara sitter framför en platt skärm!
C# är ett .NET baserat programmeringsspråk och använder MANAGED DirectX för att kommunicera med grafik-enheten. Fördelen med ramverket: .NET är att det används även på konsolen Xbox360! i form av compact .NET framework! För eventuella framtida bruk kommer jag kunna använda 3d-motorn även på XBox.
Förutom C# kommer jag använda ett ramverk som heter XNA. XNA är skapat av Microsoft och ger massor av behändiga hjälpverktyg för användaren som gör att kommunikationen till DirectX lite lättare.
För att kunna ge instruktioner till grafik-enheten måste jag lära mig ett till programmeringsspråk: HLSL (High Level Shader Language). Skillnaden är att C# ger instruktioner till datorns processor (CPU) medans HLSL ger instruktioner direkt till Grafik-kortets processor (GPU). mer om detta senare ;)
Nummer två: bildskämen är platt som en pankaka, MEN spelet måste ju ha ett djup. Man ska kunna se en massa Rum, och gubbar som springer runt och kanske ett snyggt landskap med träd. Hur skulle det se ut om allt skulle vara platt? Man måste skapa en "mekanism" som ger spelaren en Vision att han faktiskt befinner sig i ett lanskap som sträcker sig flera mil bårt, och inte framför en platt skärm. Denna "vision" är grunden till 3D-grafik. En dataskärm har bara 2 dimensioner dvs bredd och höjd, men man skapar visionen av att det finns 3-dimensioner! Vi lurar spelaren öga att 3-dimensioner existerar fast han bara sitter framför en platt skärm!
C# är ett .NET baserat programmeringsspråk och använder MANAGED DirectX för att kommunicera med grafik-enheten. Fördelen med ramverket: .NET är att det används även på konsolen Xbox360! i form av compact .NET framework! För eventuella framtida bruk kommer jag kunna använda 3d-motorn även på XBox.
Förutom C# kommer jag använda ett ramverk som heter XNA. XNA är skapat av Microsoft och ger massor av behändiga hjälpverktyg för användaren som gör att kommunikationen till DirectX lite lättare.
För att kunna ge instruktioner till grafik-enheten måste jag lära mig ett till programmeringsspråk: HLSL (High Level Shader Language). Skillnaden är att C# ger instruktioner till datorns processor (CPU) medans HLSL ger instruktioner direkt till Grafik-kortets processor (GPU). mer om detta senare ;)
En 3d-motor i detalj
Meningen med den här bloggen är den ska ska vara läsbar och intressant för både vana programmerare och människor som inte har en susning om vad 3d-grafik igentligen är.
Därför kommer jag skriva lite mer detaljerat om vad jag gjort i Blå färg. Meningen är att man ska kunna läsa bloggen och det mesta, altså VAD som händer även om den blå texten förklara i detalj VARFÖR någonting händer så som det gör
Därför kommer jag skriva lite mer detaljerat om vad jag gjort i Blå färg. Meningen är att man ska kunna läsa bloggen och det mesta, altså VAD som händer även om den blå texten förklara i detalj VARFÖR någonting händer så som det gör
lördag 11 oktober 2008
Ett evighets-arbete
Vanligtvis när man bygger en 3D-spelsmotor är man upp till flerar hundra personer som arbetar parrallellt med projektet i flera år. I detta fall kommer jag vara helt själv. Det funkar det med men det kommer som sagt bli ett "evighets-arbete"
Jag har beräknat att arbeta med projektet i ca 3-4 h varje dag på vardagarna och 12-18 h varje helg.
Jag har beräknat att arbeta med projektet i ca 3-4 h varje dag på vardagarna och 12-18 h varje helg.
Ok, kul men vad är en 3D-motor?
En 3d-motor är en slags ”motor” som ligger till grund i t.ex. alla dagens Tv-spel. och Data – spel. Jämför med motorn i en bil. Hur en bil än ser ut, snygg, stor, liten, ful så måste ALLA bilar ha en motor som sköter allt funktionellt, cylindrar, bränsletank, bromsar, ljuslyktor, högtalar-system, elektronik, förgasare m.m. Det finns så mycket mer i en bil än det vi ser. Så är också fallet med en 3D-motor. Utan en 3D-motor skulle INGET kunna hända i ett spel, ingen skulle synas på skärmen inga ljud skulle spela upp. Och massor, massor av små funktioner som spelare inte ens tänker på men som måste finnas där för att spelet ska fungera korrekt!
Jag ska bygga en 3D-motor
Hej!
Jag heter Carl-Johan Kihl och är 19 år, som projektarbete i skolan ska jag bygga en egen 3D-motor i programmerings-språket C# (C-sharp). Syftet med projektet är att på egen hand skapa en fullt fungerande 3D-motor som jag kommer kunna använda för framtida bruk, till exempel i 3d-visualiseringar eller varför inte ett massivt online-spel som kommer gör revolution i hela världen?
Jag heter Carl-Johan Kihl och är 19 år, som projektarbete i skolan ska jag bygga en egen 3D-motor i programmerings-språket C# (C-sharp). Syftet med projektet är att på egen hand skapa en fullt fungerande 3D-motor som jag kommer kunna använda för framtida bruk, till exempel i 3d-visualiseringar eller varför inte ett massivt online-spel som kommer gör revolution i hela världen?
Prenumerera på:
Inlägg (Atom)

