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

1

19.06.2006, 20:46

SDL_Flip » tearing

Hallo Gemeinde.
Ich bin etwas gefrustet. Ich habe schon ettliche Stunden damit verbraten, eine Lösung zu finden, den VSync mittels SDL zu realisieren. Bislang ging ich aber davon aus, das die SDL keine vertikale synchronistation unterstützt und suchte deshalb nach alternativen.
Heute bin ich allerdings auf einen Auszug der SDL API gestossen:

SDL_Flip -- Swaps screen buffers.
On hardware that supports double-buffering, this function sets up a flip and returns. The hardware will wait for vertical retrace, and then swap video buffers before the next video surface blit or lock will return. On hardware that doesn't support double-buffering, this is equivalent to calling SDL_UpdateRect(screen, 0, 0, 0, 0)

Demnach müsste mittels SDL_Flip() eine vertikale synchronisation möglich sein! Nur bei mir scheint dies nicht zu funktionieren. Egal ob ich in den Grafikkarten-Treibern den VSync ein - oder ausschalte.

Ich hab ein kleines Test-Programm geschrieben, welches erstichtlich macht, ob eine vertikale synchronisation verhanden ist oder nicht.

Es würde mir helfen, wenn ihr mir eure Ergebnisse mitteilen könntet.
Wenn ihr das Programm startet, ist sofort ersichtlich ob der VSync funktioniert. Das Bild wechselt zwischen einer weissen und schwarzen Fläche und das ziemlich schnell. Ich denke jeder kennt den Tearing-Effect. Ist der wechseln "sauber" und ohne "Schnitzer", funktioniert der VSync.
Das kleine Programm findet ihr hier:
http://www.homepage.hispeed.ch/neptun/vsync.zip
Programm aus dem Verzeichniss starten und beenden mit ESC.(Fullscreen 800x600 32bpp)

Der Code ist aus relativ simpel:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <stdlib.h>
#include <stdio.h>

#include "include/SDL.h"

#ifdef _WIN32
#undef main
#endif

int main(int argc, char *argv[])
{
    SDL_Surface *screen, *bitmap, *newbitmap;
    SDL_Rect src, dst;
    SDL_Event event;
    Uint8 *keys;
    
    bool running;
    int resX = 800;
    int resY = 600;
    
    src.x = 0;
    src.y = 0;
    src.w = resX;
    src.h = resY;
    dst.x = 0;
    dst.y = 0;
    dst.w = resX;
    dst.h = resY;
    
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        fprintf(stderr, "SDL konnte nicht initialisiert werden: %s\n", SDL_GetError());
        exit(1);
    }
    
    atexit(SDL_Quit);

    if(!(SDL_VideoModeOK(resX, resY, 32, SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN)))
    {
        printf("Video-Modus wird nicht supportet!\n");
        exit(1);
    }
    
    screen = SDL_SetVideoMode(resX, resY, 32, SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN);
    if (screen == NULL)
    {
        fprintf(stderr, "Konnte Bildschirmmodus nicht setzen: %s\n", SDL_GetError());
        exit(1);
    }
    
    bitmap = SDL_LoadBMP("bw.bmp");
    if (bitmap == NULL)
    {
        fprintf(stderr, "Bitmap konnte nicht geladen werden: %s\n", SDL_GetError());
        exit(1);
    }

    newbitmap = SDL_DisplayFormat(bitmap);
    SDL_FreeSurface(bitmap);
        
    running = true;
    
    while(running)
    {
        while (SDL_PollEvent(&event))
        {
            switch(event.type)
            {
                case SDL_QUIT:
                    running = false;
                    break;
            }
        }
       
        keys = SDL_GetKeyState(NULL);

        if (keys[SDLK_ESCAPE])
        {
            running = false;
        }

        if(src.x == 0)
        {
        src.x = 800;
        }
        else
        {
            src.x = 0;
        }
    
        SDL_BlitSurface(newbitmap, &src, screen, &dst);
        SDL_Flip(screen);
    }
    
    SDL_FreeSurface(newbitmap);

    return 0;
}


Ich bin um jeden Ratschlag sehr dankbar!

Gruss neptun

Anonymous

unregistriert

2

19.06.2006, 20:57

letz make crossposte! make it!

3

20.06.2006, 01:01

Sry, fürs doppel Post - habs nicht gemerkt und danke fürs löschen.

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

4

20.06.2006, 01:15

kann mir jemad erklären was die vorteile von vertikaler synchro sind? hab das nie so ganz geschnitten..

ext

Treue Seele

  • Private Nachricht senden

5

20.06.2006, 01:42

Zitat von »"Spik)evil("«

kann mir jemad erklären was die vorteile von vertikaler synchro sind? hab das nie so ganz geschnitten..

steht doch im topic: kein "tearing"

6

20.06.2006, 03:16

Zitat von »"Spik)evil("«

kann mir jemad erklären was die vorteile von vertikaler synchro sind? hab das nie so ganz geschnitten..


Ich erkläre dir das gerne etwas ausführlicher. Kann ich nicht schlafen :)
Das Gedankenmodell, welches ich dir gleich erkläre ist etwas vereinfacht. In der Praxis kommen noch ein paar weitere Faktoren hinzu, da diese das Grundprinzip nicht beeinfluss lasse ich sie einfach Weg.

Im Videospeicher der Grafikkarte liegt ein Bereich, welcher das eigentlich Monitorbild repräsentiert. Die grösse dieses Speicherbereiches ist abhänging von der Farbtiefe und der Auflösung, welche man auf dem Monitor darstellen will. Der Monitor holt sich sozusagen seine "Infos" aus diesem Bereich.
Wollen wir nun eine Grafik auf dem Bildschirm bewegen, müssen wir folglich diesen Speichbereich verändern bzw. mit neuen Informationen füllen. Dies geschiet nicht simulation sondern sequenziell. Das heisst, das jedes Pixel der Reihe nach einen neuen Farbwert zugewiesen bekommt.
Der entscheidene Punkt ist, das dieser Bereich NIE gelöscht wird, sondern lediglich mit neuen Informationen überschrieben wird.
Stell dir vor es liegt also bereits ein fix-fertig gerendertes Bild im Speicher. Nun wird wieder damit begonnen den Speicherbereich mit den neuen, aktuellen Farbinformationen vom nächsten Bild zu füllen; Pixel für Pixel.
Etwa in der Mitte angelangt, holt sich der Monitor plötzlich das Bild!
Was stellt der Monitor nun dar? Richtig. Die obere Hälfte des Speichbereiches - folglich vom Monitorbild was wir sehen - ist bereits mit den neuen Pixelinformationen gefüllt; im unteren Teil allerdings liegen immernoch die Informationen vom alten Bild.
Dieser Effekt, welcher in der Praxis als "Schnitzer", "zerrissen" wargenommen wird, nennt man >>tearing<< (engl. zerreissen.)
Der Effekt lässt sich nicht immer gleich gut ausmachen. Bleib das Bild z.b stehen, kann man ihn garnicht wahrnehmen, da das alte Bild mit dem neuen identisch ist. Besonders störend wirkt dieser Effekt in schnellen Spielen, da bei diesen die Bildimformationen vom neuen Bild eine grosse Deifferenz zum alten Bild aufweisen. Aber auch bei Lichtquellen, die ihre intensität stark und schnell ändern (z.b ein flackerndes Kellerlicht), fällt dieser Effekt sofort störend auf.

Die Lösung ist einfach.
Wenn die Grafikkarte das sogenannte VSync Signal aussendet (Dies wird immer ausgesendet, auch wenn nicht danach synchronisiert wird), welches dem Monitor mitteilt, er solle zurück an den Anfang der ersten Bildzeile, wird die Zeit genutz und der Bildspeicher "geswapt".
So bekommt der Screen nie Informationen, welche verschiedene Bildinhalte vermischen.
Der Nachteil an der Sache ist, das ein Programm demnach nicht mehr Bilder darstellen kann, als der Monitor selbst. Wenn die Monitor Frequenz 85Hz ist, kann das Programm auch nicht schneller rendern als 85fps. (Womit wir schon bei einem der Nachteile der TfT's sind ^^). Besonders dumm ist diese Tatsache, wenn die CPU Leistung nicht reicht um ein Programm mit der nötigen fps darzustellen. Wenn der Monitor mit 60Hz arbeitet, das Programm aber nur 55 schafft, so wird nur jedes zweite Bild weitergegeben, foglich 30fps.

Wenn du dir mein Programm runterlädst, bekommst du ne kleine Demonstartion vom VSync.

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

7

20.06.2006, 08:28

super erklärung, danke. das prog schau ich mir mal an wenn ich aus der uni wieder da bin.

8

22.06.2006, 03:29

Schade das hier kein Feedback kommt, obwohl das ne Sache von 2min gewesen wäre.
Jedenfalls scheint das Problem an der SDL selbst zu liegen. Mit dem Flag SDL_OPENGLBLIT beim setzen des Video-Modus, kann man das Problem allerdings umgehen.
Im OpenGL redring Conntext greifen die Treibereinstellungen für VSync unter OpenGL.
Jedoch hab ich schon öfters gehört, das SDL_OPENGLBLIT nicht zu empfehlen sei. Die Performance ist dementsprechend schlecht.
Ausserdem wird diese Option in den neuen SDL Versionen auch nicht mehr vorhanden sein.

Danke fürs Interesse

Phili

unregistriert

9

22.06.2006, 15:01

@neptun

Ich schätz mal, das liegt daran, das in diesem Forum die wenigsten mit SDL arbeiten.

10

22.06.2006, 18:04

Das denk ich nicht.
Auch Leute die überhaupt keine Ahnung von der SDL haben, hätten mir helfen können das Problem einzugrenzen.

Werbeanzeige