shader game of life

Aus DGL Wiki
Version vom 27. März 2009, 22:43 Uhr von Dj3hut1 (Diskussion | Beiträge) (Erstellung)

(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche

Game of Life

Zurück zur Shadersammlung

Beschreibung Autor Version
Simuliert das altbekannte Game Of Life. dj3hut1 1.0

Bilder

Szene aus 'Game of Life'.

Beschreibung

Ein Fragmentshader wird dazu benutzt, um das 'Game of Life' zu simulieren.

Dazu wird zuerst eine Textur erstellt, die zufällig 'lebende'( weiß ) oder 'tote' ( schwarz ) Zellen enthält. Diese Textur repräsentiert die Anfangspopulation.

In jedem ( Render- )schritt wird die nachfolgende Population berechnet. Abhängig davon, wieviel tote oder lebendige Nachbarzellen eine Zelle hat, wird entschieden ob die Zelle 'stirbt', am Leben bleibt oder eine neue Zelle geboren wird.

Hat eine lebende Zelle 2 oder 3 Nachbarn überlebt sie, hat sie weniger als 2 verhungert sie, hat sie mehr als 3 stirbt sie wegen Überbevölkerung.

Wenn eine leere Zelle von 3 lebendigen Zellen umgeben ist, wird dort eine neue Zelle 'geboren'.

In jedem Renderschritt wird nun also die Textur an den Fragmentshader übergeben ( gezeichnet auf einem Quad ) und dort wird dann die nächste Generation berechnet und auf den Bildschirm geschrieben ( mit glFinish ). Mittels glCopyTexImage2D können die Daten wieder in die Textur geschrieben werden.

Besondere Vorraussetzungen

OpenGL 2.0.

Code

Vertexshader

void main()
{
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

Fragmentshader

uniform sampler2D Texture0;

float SIZE = 64.0;

int lookup( in float x, in float y )
{
    vec2 tc;
    tc.x = x/SIZE;
    tc.y = y/SIZE;
	
    vec4 col = texture2D(Texture0, tc);
	
    if ( col.r == 1.0 )
        return 1;
		
    return 0;
}

void main()
{
    float x = gl_FragCoord.x;
    float y = gl_FragCoord.y;
    int neighbours = 0;
	
    //Nachbarn berechnen
    if ( x > 0 && y > 0 ) neighbours += lookup( x - 1, y - 1 );
    if ( y > 0 ) neighbours += lookup( x, y - 1 );
    if ( x < SIZE - 1 && y > 0 ) neighbours += lookup( x + 1, y - 1 );
    if ( x > 0 ) neighbours += lookup( x - 1, y );
    if ( x < SIZE - 1 ) neighbours += lookup( x + 1, y );
    if ( x > 0 && y < SIZE - 1 ) neighbours += lookup( x - 1, y + 1 );
    if ( y < SIZE - 1 ) neighbours += lookup( x, y + 1 );
    if ( x < SIZE - 1 && y < SIZE - 1 ) neighbours += lookup( x + 1, y + 1 );
	
    //eigener Zustand
    int self = lookup( x, y );
	
    gl_FragColor = vec4(0);
	
    //hier wird entschieden, ob die Zelle lebt
    if ( neighbours == 3 || ( neighbours == 2 && self == 1 ) )
    {
        gl_FragColor = vec4(1);
    }
}