AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Andorra 2D und Frage
Thema durchsuchen
Ansicht
Themen-Optionen

Andorra 2D und Frage

Ein Thema von Sphinx2k · begonnen am 13. Mai 2009 · letzter Beitrag vom 14. Okt 2009
Antwort Antwort
Sphinx2k

Registriert seit: 13. Mai 2009
6 Beiträge
 
#1

Andorra 2D und Frage

  Alt 13. Mai 2009, 16:29
Hallo,
Ich hab ein Delphi Programm geschrieben was unter anderem ein Netzwerkzeichenfunktion enthält. Funktionierte auch sehr gut nur das die Zeichenfläche von 2000x2000 Pixel nicht die kleinste ist und ich mittlerweile einige Funktione habe die erfordern das ganze Bild neu zu Zeichnen. Die Standard Delphi Canvas Funktionen wurden mit aber mittlerweile zu langsam, bzw die CPU auslastung war ungebefriedigend. Andorra 2D scheint mir die Lösung zu sein.
Also Programm genommen und umgebaut auf Andorra Funktioniert soweit allerdings nicht mit 100% der Funktionen die ich hatte.

Die Ursprungsfunktion war diese:
1. Eine Liste mit der Grafikobjekten wurde durchgegangen und diese auf meinen Backbuffer gezeichnet.
2. Dann hatte ich noch einen Overlay Buffer der Bereiche verdecken soll vom Bild. Alles wurde schwarz überdeckt nur die Bereiche die vom Admin Weiss gezeichnet wurden waren dann vom Hintergrund sichtbar. Also letztendlich eine Maske mit Löchern durch die durchgeschaut werden konnte.
3. Dieser wurde dann mit TransparentBlt auch auf den Backbuffer gezeichnet und der dann natürlich angezeigt.

So mit Andorra hab ich direkt angefangen das nach den Tutorials auf der Seite umzustellen. Es funktioniert alles aus Schritt 1. so wie erhofft. Bei schritt 2 hänge ich schon an der durchführung. Am wenigsten Aufwand währe es wenn ich auch mit Andorra eine zweite (Unsichtbare)Zeichenfläche hätte auf der ich eben diese Maske zusammensetzen und anschliessend auf die erst erstellte Zeichnung legen kann, mit entsprechend angegebener Transparentfarbe.

Es klappt aber irgendwie nicht, hab mir mit
Delphi-Quellcode:
AdSurface: TAdTextureSurface;
//und im Form1.Create Teil
AdSurface := TAdTextureSurface.Create(AdDraw);
AdSurface.SetSize(2000, 2000);
Eine Surface angelegt. Zum einen klappt es anscheinend nicht mit dem Drauf zeichnen und dann Transparent anzeigen nicht wirklich. Hier währe ich für einen ersten Tipp dankbar welche Funktion die Surface mit Transparenten bereichen ausgibt.
Zum anderen bekomme ich Grafikfehler angezeigt. Allerdings nur wenn ich eine SetSize größe von über 1000x1000 wähle. Entweder es Funktionert generell nicht mit einer so großen Surface, ich muss es mit OpenGL Modus anstelle von DirectX versuchen oder es ist einfach ein Bug.

Hoffe jemand hat eine idee was machen kann um dieses Problem zu umschiffen ohne meine Komplette Draw funktion umbauen zu müssen die ja an sich wenn auch langsam Funktioniert.


-----EDIT -----
Ok mit OpenGL Funktioniert es auf jeden fall. Auch funktioniert es wenn ich meine Zeichenfläche auf 2048x2048 vergrößere und eben diese Surface auch auf 2048 setze.
Nach etwas Probieren kapiere ich auch den zusammenhang. Ich darf keine große wählen die großer als mein Zeichenbereich ist, und muss das nächst kleinere auf dem Binär System Basierenden wert nehmen der Rein past.
Also bei 1023 dürfte ich maximal 512 als wert wählen.

Gut damit ist das eine Problem gelöst ob das jetzt 48 Pixel größer ist macht keinen unterschied für mich. Bleibt nur noch die Frage wie ich das Transparent zeichne.
  Mit Zitat antworten Zitat
Benutzerbild von igel457
igel457

Registriert seit: 31. Aug 2005
1.622 Beiträge
 
FreePascal / Lazarus
 
#2

Re: Andorra 2D und Frage

  Alt 13. Mai 2009, 17:09
Bei manchen Grafikkarten können Offscreen-Surfaces maximal so groß wie der Framebuffer sein.

Du musst die Texture-Surfaces "Clearen". Verwende dafür einen 32-Bit Farbwert zum Beispiel Ad_ARGB(0, 255, 255, 255). Dann erhälst du eine transparente Zeichenfläche.

Was sind das für Objekte, die du zeichnest?

Zu 2.: Suchmal nach dem Stichwort "Stenil-Buffer" und schau dir die zugehörige Demo von Andorra 2D an.
Andreas
"Sollen sich auch alle schämen, die gedankenlos sich der Wunder der Wissenschaft und Technik bedienen, und nicht mehr davon geistig erfasst haben als die Kuh von der Botanik der Pflanzen, die sie mit Wohlbehagen frisst." - Albert Einstein
  Mit Zitat antworten Zitat
Sphinx2k

Registriert seit: 13. Mai 2009
6 Beiträge
 
#3

Re: Andorra 2D und Frage

  Alt 13. Mai 2009, 17:33
Das ganze mit dem Stencil Buffer habe ich mir auch schon angeschaut aber noch stehe ich etwas auf dem Schlauch. In der Demo die dabei ist wird erst mal einmal der vordergrund erstellt und anschliessend nur das vom Hintergrund angezeigt was in den "Löchern" zu sehen ist. Würde im Endeffekt bedeuten das ich meinen Ganzen Code umbauen müsste.

Aber irgendwie leuchtet mir der Code dort zwar halbwegs ein aber wie ich das auf meinen anpasse leuchtet mir noch gar nicht ein. Gibt es eine möglichkeit eine Scene in einer TAdImage Variable abzulegen und den Stencil Buffer Vorgang danach wie in der Demo anzuwenden oder denke ich einfach grade um eine Ecke zu viel. Irgendwie komme ich nicht weiter bei der überlegung ohne die Scenen irgendwie zwischen zu speichern.

Das ganze ist ein Programm mit dem wir Rollenspiele über Internet spielen.
Die Objekte die gezeichnet werden sind nix besonderes Rechtecke, Kreise, Text, Bilder aus JPG Dateien. Das ganze eben über Netzwerk mit der möglichkeit diese Grafiken jederzeit noch einmal zu verschieben. (Bis jetzt alles über PaintBox.Canvas eingesetzt)
Wenn also eine Karte dort eingeladen wird soll es möglich sein das der Spielleiter diese eben überdecken kann das nich jeder alles sehen kann, und dann eben entsprechend bereiche Aufdecken je nach bedarf. Klappt ja auch wunderbar bis eben auf die doch recht hohe CPU last beim neu Zeichnen des Bildes.
  Mit Zitat antworten Zitat
Sphinx2k

Registriert seit: 13. Mai 2009
6 Beiträge
 
#4

Re: Andorra 2D und Frage

  Alt 14. Mai 2009, 22:12
Ok nach einigem rumprobieren und noch mal Dokumentation schmöckern hab ich es jetzt zumindest in nem kleinen Testaufbau zum Funktionieren bekommen. Der Trick war für mich zu Kapieren das eine Surface auch wie eine Textur verwendet werden kann.

EDIT
Hab es jetzt in meinem Programm so umgesetzt und es Funktioniert wie gehofft bis auf einen Punkt der mit sicherheit nur eine Einstellungsfrage ist.
Jemand der als Admin Autorisiert ist soll natürlich alles sehen können was auf dem Zeichenbereich liegt, muss aber natürlich wissen was die normalen Benutzer sehen und was nicht.
Bis jetzt war es so das ich beim Admin einfach das ganze Halbtransparent gemacht hab, und eben 100% Transparent dort wo alle etwas sehen können. Das möchte ich jetzt wieder erreichen.
Wie müsste ich den unten stehenden Code ändern damit alles was "nicht sichtbar" ist halbtransparent wird und alles was sichtbar ist 100% transparent?
Ich vermute mal das es hiermit zusammen hängt SetStencilOptions(0, $FFFF, asfLessThan); Oder doch ganz wo anders.
Vieleicht hat ja noch jemand eine idee oder einen Tipp.
EDIT

Hier mal der komplette code aus meinem Test Programm vieleicht hab ich ja immer noch etwas zu Kompliziert, aber wenn nicht hilft es vieleicht jemand anderem der so ein Problem hat wie ich.

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, AdDraws, AdClasses, AdTypes, ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    AdDraw:TAdDraw;
    AdSurf1, AdSurf2: TAdTextureSurface;
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  AdDraw := TAdDraw.Create(Panel1);
  AdDraw.DllName := 'AndorraDX93D.dll';
  if AdDraw.Initialize then
  begin
    AdSurf1:=TAdTextureSurface.Create(AdDraw);
    AdSurf1.SetSize(256,256);

    AdSurf2:=TAdTextureSurface.Create(AdDraw);
    AdSurf2.SetSize(256,256);

  end
  else
  begin
    ShowMessage(AdDraw.GetLastError);
    halt;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  AdDraw.Free;
  AdSurf1.Free;
  AdSurf2.Free;
end;


procedure TForm1.Timer1Timer(Sender: TObject);
begin

if AdDraw.CanDraw then
begin
  AdDraw.ClearSurface(clBlack);

  AdDraw.BeginScene;
 
  //Die Zeichenfläche an sich auf der sich die Grafik hinter der Maske befindet
  if AdSurf1.CanDraw then begin
    AdSurf1.ClearSurface(Ad_ARGB(255,255,255,255));
    with AdSurf1.Canvas do begin
      Pen.Color:=Ad_ARGB(255,0,0,255);
      Brush.Color:=Ad_ARGB(255,0,0,255);
      Ellipse(10,10,30,30);
      Circle (70,70,50);
      Release;
    end;
  end;

  // Das ist meine "Lochmaske" die vor dem Bild steht
  if AdSurf2.CanDraw then begin
    AdSurf2.ClearSurface(Ad_ARGB(0,255,255,255));
    with AdSurf2.Canvas do begin
      Pen.Color:=Ad_ARGB(255,0,0,0);
      Brush.Color:=Ad_ARGB(255,0,0,0);
      Rectangle(20,20,60,60);
      Rectangle(60,65,65,195);
      Release;
    end;
  end;

  //Enable stencil buffer and alpha masking
  AdDraw.Options := AdDraw.Options + [aoStencilBuffer, aoAlphaMask];

   //Increment the stencil buffer value for a pixel, if a pixel is set there
  AdDraw.AdAppl.SetStencilOptions(0, $FFFF, asfAlways);
  AdDraw.AdAppl.SetStencilEvent(asePass, asoIncrement);

  AdSurf2.Image.Draw(AdDraw,0,0,0);

  //Only draw a pixel, if the stencil value is larger than zero
  AdDraw.AdAppl.SetStencilOptions(0, $FFFF, asfLessThan);
  AdDraw.AdAppl.SetStencilEvent(asePass, asoKeep);
  AdDraw.Options := AdDraw.Options - [aoAlphaMask];

  AdSurf1.Image.DrawEx(AdDraw, AdRect(0, 0, 256, 256), AdRect(0, 0, 256, 256), 0, 0, 0, 255, bmAlpha);


  AdDraw.Options := AdDraw.Options - [aoStencilBuffer];

  AdDraw.EndScene;
  AdDraw.Flip;
end;

end;

end.
  Mit Zitat antworten Zitat
Progman

Registriert seit: 31. Aug 2007
Ort: 99974 MHL
695 Beiträge
 
Delphi 10.1 Berlin Starter
 
#5

Re: Andorra 2D und Frage

  Alt 14. Okt 2009, 12:44
Ich hab das jetzt nur mal überflogen und würde sagen, um etwas halbtransparent zu machen, sollte in z.B. Ad_ARGB(0,255,255,255) die erste Zahl (hier 0 = transparent) einen Wert zwischen 0 und 255 haben, wobei 255 für keine Transparenz steht. Also mal experimentieren mit Werten so um 100 bis 150
Edit: Sorry, hab nicht aufs Datum geschaut
Karl-Heinz
Populanten von Domizilen mit fragiler, transparenter Aussenstruktur sollten sich von der Translation von gegen Deformierung resistenter Materie distanzieren!
(Wer im Glashaus sitzt sollte nicht mit Steinen werfen)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:17 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz