Videos der PDC 2009 online
26.11.2009 17:57
Für alle die der diesjährigen PDC nicht persönlich beiwohnen konnten, stehen jetzt Videos der Sessions online zur Verfügung. Zwei Sessions, Advanced Graphics Functionality Using DirectX und Modern 3D Graphics Using Windows 7 and Direct3D 11 Hardware, von Michael Oneppo geben Einblick in die neuen Möglichkeiten von Windows 7 und DirectX 11.
Videos der PDC 2009 Sessions
UnrealEngine 3 und CryENGINE 3 kostenlos
19.11.2009 11:57
Kürzlich hat Epic Games seine UnrealEngine 3 für nicht kommerzielle Projekte zum kostenlosen Download bereitgestellt. Nun zieht auch das Frankfurter Studio Crytek nach und veröffentlichte seine CryENGINE 3. Crytek möchte seine Engine u.a. Universitäten anbieten. Interessenten müssen sich auf der Website der CryENGINE bewerben.
Unreal Developer Kit Download
CryENGINE 3 Bewerbung
Neues Buch zum Thema XNA Framework
09.11.2009 09:23
Seit langer Zeit ist mein Buch "Spieleentwicklung mit dem Microsoft XNA Framework" angekündigt. Oft wurde es aufgrund chronischen Zeitmangels verschoben. Nun kann ich endlich mitteilen, dass das Buch in den Druck gegangen ist. Das heißt, das Buch wird Ende November bei
entwickler.press
erhältlich sein. Dem Buch liegt keine CD-Rom bei. Stattdessen werden die Beispielprojekte im Laufe dieses Monats online zur Verfügung stehen.
Selbstverständlich möchte man nicht die Katze im Sack kaufen, weshalb Sie unter folgendem Link das Inhaltsverzeichnis des Buchs einsehen können.
Entwicklung mit dem Microsoft XNA Framework - Inhaltsverzeichnis
Wie immer begrüße ich Hinweise auf Fehler und sonstige Kritik. Letzteres wird selbstverständlich in einer evtl. 2. Auflage, sofern möglich, berücksichtigt.
Feature Levels
08.11.2009 13:43
Die Entwicklung von Computerspielen für Personal Computer gestaltet sich schwieriger als die Entwicklung für Konsolen, denn herrkömmliche Computer variieren sehr stark in deren Hard- und Softwareausstattung. Während bei Konsolen die Fähigkeiten der Grafikkarte bekannt sind, muss beim PC immer abgefragt werden, welche Features die Grafikkarte unterstützt. Infolgedessen bedarf es diverser Codepfade, um Effekte abgeschwächt auf älterer Hardware auszuführen oder ganz zu deaktivieren.
Unter DirectX 9 fragen Sie die Fähigkeiten der Grafikkarte über die CAPS (Capabilities) ab. Das DirectX SDK enthält eine vollständige Auflistung aller CAPS. Ausgedruckt bringt es die Liste auf mehrere A4-Blätter. Um jener Komplexität Herr zu werden, führte Microsoft mit DirectX 10.1 die sog. Feature Levels ein. Unter DirectX 11 existieren sechs Feature Levels, die die CAPS gruppieren.
Feature Level 11.0
Feature Level 10.1
Feature Level 10.0
Feature Level 9.3
Feature Level 9.2
Feature Level 9.1
In obiger Auflistung, von oben nach unten gesehen, repräsentiert jedes Feature Level ein Superset der darunterliegenden Ebene. Jetzt stellt sich die Frage, welchen Sinn die Feature Levels haben? Hauptsächlich sollen die Feature Levels die Entwicklung vereinfachen, indem die vielen Permutationen der CAPS in den Griff zu kriegen. Statt unzähliger CAPS gibt es nun eben maximal sechs Feature Levels die die Fähigkeiten der Grafikkarte beschreiben. Darüberhinaus vereinfachen die Feature Levels die Verwendung des API, denn Sie können ebenso ein Direct3D 11 Device auf Basis von Direct3D 9 Hardware erzeugen (gleiches gilt für ein Direct3D 10.1 Device auf Basis von Direct3D Hardware).
Das Feature Level 9.1 umfasst beispielsweise das Shader Model 2.0. Feature Level 9.2 beinhaltet alle Funktionen aus dem Feature Level 9.1. Darüberhinaus unterstützt das Feature Level 9.2 u.a. vier simultane Render Targets. Ab Feature Level 9.3 steht zum Beispiel das Shader Model 3.0 zur Verfügung.
Während bei Direct3D 10.1 beispielsweise für jedes Feature Level versucht werden muss ein Device zu erzeugen, genügt bei Direct3D 11 die Erzeugung des Device. Auf welchem Feature Level das Device basiert, gibt die D3D11CreateDevice()-Funktion zurück.
Folgendes Beispiel demonstriert die Vorgehensweise beim Erzeugen eines Direct3D 10.1 Devices.
const
D3D10_FEATURE_LEVEL1 pFeatureLevels[] =
{
D3D10_FEATURE_LEVEL_10_1,
D3D10_FEATURE_LEVEL_10_0,
D3D10_FEATURE_LEVEL_9_3,
D3D10_FEATURE_LEVEL_9_2,
D3D10_FEATURE_LEVEL_9_1,
};
const
D3D10_DRIVER_TYPE pDriverTypes[] =
{
D3D10_DRIVER_TYPE_HARDWARE,
D3D10_DRIVER_TYPE_WARP,
D3D10_DRIVER_TYPE_REFERENCE,
};
const
UINT iDriverCount = sizeof(pDriverTypes) /
sizeof(pDriverTypes[0]);
const
UINT iFeatureCount = sizeof(pFeatureLevels) /
sizeof(pFeatureLevels[0]);
for
(UINT iDriverType = 0; iDriverType < iDriverCount;
iDriverType++)
for
(UINT iFeatureLevel = 0; iFeatureLevel < iFeatureCount;
iFeatureLevel++)
{
hResult = D3D10CreateDevice1(pAdapter,
pDriverTypes[iDriverType], NULL,
D3D10_CREATE_DEVICE_BGRA_SUPPORT,
pFeatureLevels[iFeatureLevel],
D3D10_1_SDK_VERSION,
&_pD3D10Device);
if
(SUCCEEDED(hResult))
return
S_OK;
}
Unter Direct3D 11 wurde der Vorgang vereinfacht. Hier bedarf es lediglich der Iteration aller Device Types, bis schließlich ein Device erzeugt werden konnte.
const
D3D_FEATURE_LEVEL pFeatureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1,
};
const
D3D_DRIVER_TYPE pDriverTypes[] =
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
const
UINT iDriverCount = sizeof(pDriverTypes) /
sizeof(pDriverTypes[0]);
const
UINT iFeatureCount = sizeof(pFeatureLevels) /
sizeof(pFeatureLevels[0]);
for
(UINT iDriverType = 0; iDriverType < iDriverCount;
iDriverType++)
{
hResult = D3D11CreateDeviceAndSwapChain(NULL,
pDriverTypes[iDriverType], NULL,
D3D11_CREATE_DEVICE_DEBUG |
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
pFeatureLevels,
iFeatureCount,
D3D11_SDK_VERSION,
&_GraphicsDeviceManager.SwapChainDesc,
&_GraphicsDeviceManager.SwapChain,
&_GraphicsDeviceManager.GraphicsDevice,
&_GraphicsDeviceManager.FeatureLevel,
&_GraphicsDeviceManager.DeviceContext);
}
Blog reloaded
27.10.2009 19:33
Lange Zeit war sowohl meine Internetseite als auch mein Blog aufgrund technischer Schwierigkeiten offline. Umso glücklicher bin ich, Ihnen mein neuen Blog nun präsentieren zu koennen. Die Arbeiten an der Seite sind noch nicht vollständig abgeschlossen, weshalb es in nächster Zeit unter Umständen zu kurzfristigen Aussetzern kommen kann. Feedback zum Blog ist selbstverständlich willkommen!
Effect Pools im XNA Framework
15.07.2009 15:35
In der Regel verwenden Computerspiele unzählige Effekte. Dabei besitzen fast alle Effekte mindestens eine Hand voll gleicher Parameter (globale Variablen). Ein gutes Beispiel sind die Sicht- und Projektionsmatrizen. Die Anwendung muss nun für jeden Effekt dieselben Daten immer und immer wieder zuweisen.
Dem Problem begegnet man mit sog. Effect Pools. Alle Effekte die einem Effect Pool angehören können auf gemeinsam verwendete Variablen zugreifen. Als Konsequenz muss man nur noch einem Effekt die entsprechenden Parameter-Werte zuweisen und alle anderen Effekte übernehmen die Daten ebenfalls. Wenn man nun die Effekte über die Content Pipeline lädt, dann gehören diese automatisch einem statischen Effect Pool an. Gemeinsam verwendete Variablen kennzeichnen Sie in der Effekt-Datei mit dem Modifier shared.
shared
float3
LightPosition = 0.0f;
Per Default gehören alle Effekte, die Sie über die Content Pipeline laden also demselben Effect Pool an. Wie aber können Effekte unterschiedlichen Effect Pools zugewiesen werden? Wirft man einen Blick auf die Konstruktorüberladungen der Effect-Klasse, dann wird man eine Signatur finden, die eine GraphicsDevice-Instanz, den kompilierten Effekt-Code, Compiler-Optionen und einen Effect Pool entgegen nimmt. Jetzt gilt es nur noch den Code des kompilierten Effekts zu ermitteln. Hierfür wird ein neuer Content Processor entwickelt, der das Resultat des Effect Importers entgegen nimmt, den Effekt kompiliert und den Code als byte-Array zurückgibt.
[ContentProcessor(DisplayName = "Plain Effect Processor")]
public
class PlainEffectProcessor : ContentProcessor
{
public
override
byte
[] Process(
EffectContent input, ContentProcessorContext context)
{
CompiledEffect oEffect = context.Convert(
input, "EffectProcessor");
return
oEffect.GetEffectCode();
}
}
Zur Laufzeit laden Sie das byte-Array und erzeugen eine neue Effect-Instanz:
m_oEffectPool =
new
EffectPool();
byte
[] oCompiledEffect =
this
.Content.Load("Effect1");
m_oEffect1 =
new
Effect(
this
.GraphicsDevice, oCompiledEffect, CompilerOptions.None, m_oEffectPool);
XNA Game Studio 3.1 ist erschienen
12.06.2009 13:11
Es ist soweit, Microsoft geht mit dem XNA Game Studio 3.1 in die fünfte Runde. Mit der neuen Version können Sie Avatars rendern und animieren. Es existiert eine Möglichkeit die Sprachkommunikation zu erhalten, auch wenn der Freund einen anderen Titel spielt. Außerdem wurde das XNA Framework um eine Videoplayback-Funktionalität erweitert, damit Logos oder sonstige Inhalte dargestellt werden können. Eine genaue Beschreibung der neuen Features ist in der Dokumentation des XNA Game Studio 3.1 oder alternativ auf der Website des Creators Club zu finden.
XNA Game Studio 3.1
Kamerawackeln als Post Processing Effect
26.05.2009 17:57
Jeder aktuelle Spieletitel setzt Post Processing Effects ein, um dem Spiel eine gewisse Note zu verleihen oder besonders spektakuläre Spezialeffekte umzusetzen. Allerdings muss ein derartiger Effekt nicht immer sehr aufwändig sein, um dem Spiel zu einem besseren "Feeling" zu verhelfen. Ein Kamerawackler, der zum Beispiel eingesetzt werden kann, wenn der eigene Panzer getroffen wurde unterstützt die Action eines Spiels. Ein Kamerawackeln lässt sich sehr leicht als Post Processing Effect realisieren.
Zur Realisierung des Effekts muss die Szene in einem Render Target vorliegen, dass wir als Textur an einen Shader geben können. Der Pixel Shader macht nichts anderes, als die Texturkoordinaten zu verzerren, so dass die komplette Szene auf einer Ellipse bewegt wird. Die Translation muss nur schnell genug stattfinden, damit die Verzerrung als Kamerawackeln erscheint. Wie folgt sieht der Pixel Shader aus:
float
fTime;
uniform
extern
texture
ScreenTexture;
sampler
ScreenS = sampler_state
{
Texture = <ScreenTexture>;
};
float4
PixelShaderFunction(
float2
oTexCoord : TEXCOORD0) : COLOR0
{
return
tex2D
(ScreenS,
oTexCoord +
float2
(cos(fTime * 1000.0f) * 0.01f,
sin(1.0f + (1.5f - fTime) * 1000.0f) * 0.0005f) * fTime);
}
Der Pixel Shader addiert zu den Texturkoordinaten einen zweiten Vektor. Jener Vektor errechnet sich aus der Kosinus- und Sinusfunktion, um eine Kreisbewegung zu erzeugen. Die Variable fTime wird von der Anwendung hereingegeben und geht gegen 0. Somit nimmt das Kamerawackeln gegen Ende stetig ab. Da die Zeit in Sekunden angegeben wird, skaliert der Pixel Shader die Zeit mit einem Faktor von 1000. Die Ellipse entsteht dadurch, dass die Kosinus- und Sinusfunktion unterschiedlich skaliert wird.
Die Technique sieht folgendermaßen aus:
technique
{
pass
P0
{
PixelShader =
compile
ps_2_0 PixelShaderFunction);
}
}
Die Szene wird mit einem BasicEffect-Objekt gerendert:
oSpriteBatch.Begin(SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.None);
oEffect.Parameters["fTime"].SetValue(m_fTime);
oEffect.Begin();
oEffect.CurrentTechnique.Passes[0].Begin();
oSprite.Draw(oTexture,
new
Rectangle(0, 0,
this
.GraphicsDevice.Viewport.Width,
this
.GraphicsDevice.Viewport.Height), Color.White);
oSprite.End();
oEffect.CurrentTechnique.Passes[0].End();
oEffect.End();
Im nächsten Blogeintrag werden wir uns dann einer kleinen Druckwelle für zweidimensionale Spiele widmen. Diese kann ebenfalls mit einer Sinusfunktion realisiert werden und erweckt dennoch Eindruck beim Benutzer.
Clip Distances
14.03.2009 11:24
In vielen Situationen, zum Beispiel beim Rendern von Wasseroberflächen, müssen diverse Objekte in der virtuellen Welt geclippt werden. Beispielsweise wird Clipping eingesetzt, wenn Sie die Umgebung rendern, die in der Wasserspiegelung sichtbar ist. Die Geometrie unterhalb der Wasseroberfläche ist für die Reflektion irrelevant.
In älteren DirectX-Versionen kommen Clip Planes zum Einsatz, um Geometrie ober- oder unterhalb dieser Ebene zu entfernen. Clip Planes waren Bestandteil der Fixed Function Pipeline. Demzufolge ist diese Technik dem Rotstift verfallen. In DirectX 10 existieren Clip Distances. Vertex oder Geometry Shader weisen einer Ausgabe die Semantik SV_ClipDistance[n] zu, wobei n entweder 0 oder 1 ist.
Für jeden Vertex berechnen Sie einen Wert, den die Grafikkarte über die Primitive hinweg interpoliert. Alle Pixel, deren „Distanz“ unter 0 liegt werden verworfen. Clip Planes simulieren Sie mit folgender Ebenengleichung:
Ax + By + Cz + D = 0
Die Koeffizienten A, B und C repräsentieren die Normale der Clip Plane. D ist die Distanz von der Ebene zum Koordinatenursprung, sprich: Zum Beispiel die Höhe des Wasserspiegels. Wenn Sie die Schnittebene in Weltkoordinaten definieren, dann müssen Sie die Vertices vorher ebenfalls in Weltkoordinaten überführen, bevor Sie die Komponenten x, y und z in die Gleichung einsetzen. Insgesamt bringt ein Register der Grafikkarte bis zu vier float-Werte unter. Demnach dürfen Sie bis zu acht Kriterien mit den Clip Distances angeben.
Um Clip Distances zu verwenden, definierten Sie für die Vertex Shader-Ausgabe eine Struktur wie folgende:
struct
VertexShaderOutput
{
//...
float
Distance : SV_ClipDistance0;
};
Der Vertex Shader selbst, kann beispielsweise wie folgt aussehen. Hierbei gilt es zu beachten, dass die Ebene in Weltkoordinaten spezifiziert wird.
VertexShaderOutput VS_TerrainWithClipping(VertexShaderInput oInput)
{
VertexShaderOutput oOutput = (VertexShaderOutput)0;
float4
oPosition =
mul
(oInput.Position, World);
oOutput.Distance = ClipPlaneNormal.x * oPosition.x + ClipPlaneNormal.y *
oPosition.y + ClipPlaneNormal.z * oPosition.z + Distance;
return
oOutput;
}
Den Vektor ClipPlaneNormal und die Distanz übergibt die Anwendung dem Shader.
Archiv
November
October
July
Alle
Dokumente
Keine
RSS 2.0