Die Selektionsfunktion von OpenGL ist fehleranfällig und hinzu kommtm, daß sie auf nVidia-Karten mit aktuellen Treibern ziemliche Performanceschwankungen verursacht.
Hier wird eine alternative Methode vorgestellt. Sie wurde aus einem funktionierendem Projekt entnommen.
Sie wurde aber angepasst, um Allgemeingültigkeit wieder herzustellen.
procedure Render;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
Hauptklasse.Render(FALSE);
SDL_GL_SwapBuffers;
end;
procedure THauptklasse.Render(Picken:Boolean);
begin
for objekt:=0 To Pred(objekte.count) do
begin
if Picken then
begin
glDisable(GL_TEXTURE_2D);
glColor4b(objekt, 0, 0, 0); //Die Farbe wird in diesem Fall auf Rot geschreiben. Damit kann man 256 Objekte unterscheiden. Hat man mehr Objekte, kann man auch alle Farben verwenden.
//glbegin(GL_QUADS);
// Alles rendern.
//glend;
end else
begin
glEnable(GL_TEXTURE_2D);
//glbegin(GL_QUADS);
// Alles rendern.
//glend;
end;
end;
end;
Nun wird implementiert, daß beim Mausklick ein extra Rendervorgang angestossen wird, welcher
die zu unterscheidenden Objekte lediglich mit verschiedenen eindeutigen Farben rendert. Dieser Rendervorgang wird
nach dem Auslesen des Pickergebnisses sofort wieder überschrieben und bleibt damit unsichtbar.
Dazu brauchen wir folgende Methode, welche beim Mausklick diesen Rendervorgang anstoesst und und das Pickergebnis liefert.
function GetSelectBufferHit(mx,my:Integer) : Integer;
var DataBuffer : array [0..3]of Byte;
begin
Hauptklasse.Render(TRUE); // Im Pickmodus rendern //
glReadPixels(mx, game.SCREEN_HEIGHT-my, 1, 1, GL_RGB, GL_BYTE, @DataBuffer);
Result := DataBuffer[0];
end;
Die Methode GetSelectBufferHit wird dann im Klickevent gerufen. In SDL-Projekten sieht das etwa so aus:
procedure glHandleEvents;
var event : TSDL_Event;
hit:Integer;
begin;
// Verarbeiten der Events
while ( SDL_PollEvent( @event ) = 1 ) do
begin
case event.type_ of
// Maustaste wurde gedrückt
SDL_MOUSEBUTTONDOWN:
begin
Hit := GetSelectBufferHit(Event.button.x,Event.button.y);
//Die Nummer auf "Hit" ist unsere ID, welche wir beim Rendern auf die Objektfarbe gelegt hatten.
end;
...
end;