Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Phili

unregistriert

1

07.08.2006, 11:41

Post Processing Effects: Cartoon-Grafiken Teil 1

Warnung:
-Der Quellcode dieses Tutorials ist nciht zum kopieren sondern zum verstehen und dann selber schreiben da. Deswegen fehlen auch Fehlerabfragen und ähnliches
-Den Post Processing Effect, den ich in diesem Tutorial erstelle habe ich selbst entwickelt->er ist auch ncith gerade perfekt, sollte aber in erta zeigen, wie sich soetwas verwirklichen lässt.
-Über die ganaue Implentierung muss sich jeder selbst gedanken machen. z.B hat jeder seine eigene Device der Engine, bei mir ist es eben die PH3DDev und auch Shader benutzt jeder anders. Deswegen habe ich auch manche Funktionen, die sich z.B. mit dem Laden von Shadern befassen nicht gezeigt.

So wird dass dann am Ende ungefär aussehen:
http://img152.imageshack.us/my.php?image=autocartoonzg2.png
Kann allerdings mit leichten Variationen am Shader in Teil 2 noch um einiges schöner werden!

So, dann mal los. Ich binn mir sicher, dass ich mir soeben die Hälfte der antworten auf dieses Tutorial erspart habe :D . Wie könnte man also Cartoongrafiken darstellen? Das naheliegendste wäre doch, das Bild zu rendern, in dem Gerenderten Bild scharfe Kanten zu finden und dann die scharfen Kanten mit schwarz nachzuziehen. Aber wie lässt sich sowas in D3D bewältigen?
Nun, wir rendern erst alles auf eine Textur. Dann nehmen wir die Textur und stellen sie als großes Viereck auf dem gesamten Bildschirm dar. Und wenn wir nun beim dartellen des Bildes einen bestimmten PixelShader benutzen, dann haben wir den gewollten Effekt.

Also machen wir uns ne Klasse für Post Processing Effects:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class PH3DPostProcessing
{
public:
    public:
    int PixelShaderNr;                        
    IDirect3DTexture9 *RenderTarget;
    IDirect3DSurface9 *RenderTargetSurface;   
    IDirect3DSurface9 *OldRenderTarget;
    PH3DTransformedVertex Mod[6];
    void Laden(char *filename);
    void Erstellen();
    void Darstellen1();
    void Darstellen2();
};

Ich denke die vielen Kommentare ersparen uns eine weitere beschreibung-alles wirklich interessante spielt sich in den Darstellen-Funktionen ab.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void PH3DPostProcessing::Erstellen()
{
float Width=(float)PH3DDev.pp.BackBufferWidth;
    float Height=(float)PH3DDev.pp.BackBufferHeight;

    PH3DDev.D3DDev->CreateTexture(PH3DDev.pp.BackBufferWidth, PH3DDev.pp.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET, 
        PH3DDev.pp.BackBufferFormat, D3DPOOL_DEFAULT, &RenderTarget, NULL);
    RenderTarget->GetSurfaceLevel(0, &RenderTargetSurface);
    PH3DDev.D3DDev->CreateRenderTarget(PH3DDev.pp.BackBufferWidth, PH3DDev.pp.BackBufferHeight, PH3DDev.pp.BackBufferFormat,
        PH3DDev.pp.MultiSampleType, PH3DDev.pp.MultiSampleQuality, FALSE, &RenderTargetSurface, NULL);

    Mod[0].Position=Vektor3(0,     0,      1); Mod[0].Textur=Vektor2(0, 0);
    Mod[1].Position=Vektor3(Width, 0,      1); Mod[2].Textur=Vektor2(0, 1);
    Mod[2].Position=Vektor3(0,     Height, 1); Mod[1].Textur=Vektor2(1, 0);
    Mod[3].Position=Vektor3(0,     Height, 1); Mod[3].Textur=Vektor2(0, 1);
    Mod[4].Position=Vektor3(Width, 0,      1); Mod[4].Textur=Vektor2(1, 0);
    Mod[5].Position=Vektor3(Width, Height, 1); Mod[5].Textur=Vektor2(1, 1);
    for(int i=0; i<6; i++) Mod[i].ExtraPos=1.0f;
}

Wie oben zu sehen erstellen wir erst das RenderTarget und den ZBuffer, beides Texturen auf deren Surface später gerendert wird. Das laden des gewünschten Shader-Effekts werde ich hier ncith xtra besprechen. Das Viereck besteht aus Vertizies folgender struktur:

C-/C++-Quelltext

1
2
3
4
5
6
struct PH3DTransformedVertex
{
    PHMAVektor3 Position;
    float ExtraPos;
    PHMAVektor2 Textur;
};

Um den Effekt jetzt Darzustellen wird am anfang der Szene das Standart-RenderTarget und der Standart-ZBuffer gespeichert und unser neuer eingesetzt. Dann rufen wir ganz normal BenginSzene und Clear auf und rendern unsere Szene.

C-/C++-Quelltext

1
2
3
4
5
6
7
void PH3DPostProcessing::Darstellen1()
{
    PH3DDev.D3DDev->GetRenderTarget(0, &OldRenderTarget);
    PH3DDev.D3DDev->SetRenderTarget(0, RenderTargetSurface);
    PH3DDev.D3DDev->BeginScene();
    PH3DDev.D3DDev->Clear(0, 0, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0, 1, 1);
}

Wenn der Render Vorgang abgeschlossen ist, nehmen wir Darstellen2 um die Szene abzuschließen, den Effekt zu wirken und das ganze darzustellen

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
IDirect3DSurface9 *Surf;
    RenderTarget->GetSurfaceLevel(0, &Surf); //Zwischenspeicher

    PH3DDev.D3DDev->StretchRect(RenderTargetSurface, NULL, Surf, NULL, D3DTEXF_LINEAR); //Gerenderte Szene kommt in unsere Textur

    PH3DDev.D3DDev->EndScene();
    PH3DDev.D3DDev->SetRenderTarget(0, OldRenderTarget);
    PH3DDev.D3DDev->BeginScene();
    PH3DDev.D3DDev->Clear(0, 0, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0, 1, 1);
    PH3DDev.D3DDev->SetTexture(0, RenderTarget);
    PixelShaderPool.Shader[PixelShaderNr].Darstellen();
    PH3DDev.D3DDev->SetFVF(D3DFVF_XYZRHW|D3DFVF_TEX1);
    PH3DDev.D3DDev->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, Mod, sizeof(PH3DTransformedVertex));
    PH3DDev.D3DDev->EndScene();
    PH3DDev.D3DDev->Present(0, 0, 0, 0);

Wir beenden Die Szene, die auf die Textur gerendert wurde, Setzen wieder das normale Rendertarget und den ZBuffer und beginnen die eigentliche Szene und leeren erneut das RenderTarget udn den ZBufffer.
Dann setzen wir die Textur auf die wir vorher gerendert hatten als Textur für unseren PixelShader, setzen unseren Effekt in Form eines PixelShaders und stellen das Viereck dar.

Phili

unregistriert

2

07.08.2006, 15:22

ich muss noch nen kleinen Nachtrag bringen: offenbar macht das erstellen eines Extra ZBuffers auf manchen Grafkkarten Probleme. Sollte dieser Code also bei euch nicht funktionieren, so lasst den extra ZStencil-Buffer weg.

Phili

unregistriert

3

08.08.2006, 15:23

Ok, das Problem mit dem ZBuffer hab ich gelöst. Ich hab den neuen Code oben gepostet. Kommentare werde ich bald noch hineinschreiben.

Sicaine

unregistriert

4

10.08.2006, 17:18

Wie waers mit nem Beispielbild?

Phili

unregistriert

5

10.08.2006, 18:02

@Sicane
guck mal im 2. Teil

Sicaine

unregistriert

6

11.08.2006, 04:29

Naja das is ja wohl Teil 1 also der Start also will ich hier nen Screenshot und nich in Teil 2 nen Beispielprogramm oO

Phili

unregistriert

7

11.08.2006, 13:06

@sicane
ok, ok

8

11.08.2006, 18:12

Find es zwar schön das du dich bemühst Tutorials zu schreiben... ABER: DAS ist keine Comicgraphic... less dir mal nen paar Papers zu dem Thema durch...
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

Phili

unregistriert

9

11.08.2006, 19:03

Zitat

-Den Post Processing Effect, den ich in diesem Tutorial erstelle habe ich selbst entwickelt->er ist auch ncith gerade perfekt, sollte aber in erta zeigen, wie sich soetwas verwirklichen lässt.

War weniger als Anleitung zu Cartoon-Grafiken gemacht, als um zu zeigen, wie sich Post Processing Effects verwirklichen lassen. Ich hab meinen Shader für Cartoongrafiken allerdings auch bereits nen ganzes Stück hochpoliert-sieht schon 10*besser aus. :D

Ashnarott

Frischling

Beiträge: 57

Beruf: Student Maschinenbau

  • Private Nachricht senden

10

09.05.2008, 17:31

Hi,

ich habe das Tutorial versucht, aber erstmal ohne Shader. (Wollte halt testen ob es von Grundauf funktioniert).

Mein Problem ist jetzt.
Wenn ich die Textur auf das Viereck zeichnen will. Zeichnet er mir nur die Clearfarbe des vorherigen RenderTargets, aber nicht die Objekte. Weiß jemand was los ist? Ich hab auch schon das Surface und die Texture mit D3DXSaveSurfaceToFile/D3DXSaveTextureToFile gespeichert und dort waren die Objekte drin.

Lade ich eine normale Textur von einer Datei und lege diese übers Dreieck wird sie aber ganz normal gezeichnet.
Weißt jemand die Lösung??

P.S: Ich wusste nicht ob ich ein neues Thema aufmachen sollte, deshalb poste ich es jetzt erstmal hier ;)

Edit: Ich hab jetzt herrausgefunden das er mir die Objekte in den ersten paar Frames zeichnet dann aber nicht mehr. Ich werde daraus echt nicht schlau^^
Traue einem Computer, aber niemals seinen Programmierer!!!

Werbeanzeige