Registriert: So Jan 07, 2007 21:26 Beiträge: 130 Wohnort: mal hier mal da mal irgendwo
Hi,
dein Raytracer ist richtig geil!!!
Macht ein richtig sprachlos wenn man so sieht was du alles zusammen programmierst... Da fehlen ein Laien wie mir einfach die Worte.
Richtig gut find ich auch, dass du ein Tutorial bzw. eine Tutorialreihe erstellst
Das bringt mich aber auch schon zu meiner Frage. Und zwar verwendest du ja in deinem ersten Code-Beispiel
Code:
public struct Ray
{
public Vertex3 Origin;
public Vertex3 Direction;
public Vertex3 Evaluate (double t)
{
return Origin + t * Direction;
}
}
Vertex3, das wird ja ein struct oder eine Klasse sein. Und ich wollte halt mal sehen wie die aufgebaut ist (bzw den Quelltext von dieser sehen).
Weil ich würde liebend gerne auch einen Raytracer mit Anleitung deines Tutorials schreiben, jedoch fangen dort schon meine Probleme an.
Würde mich sehr freuen ;P
cuz bubble
_________________ Wenn Worte nichts als Worte sind, dann müssen's Steine sein! Solange - bis sie pleite sind - schmeißt Fensterscheiben ein! - Fidl Kunterbunt -
int roots = CalcQuadricRoots (a, b, c, out t1, out t2) ;
if (roots > 0)
return t1 >= 0 ? t1 : t2 ;
// kleinsterpositiver pos. Wert aus t1, t2
else
return -1; // Kein Schnittpunkt
}
Zumindest im Code ist es anscheinend eine Klasse, da hier auf DotDot zugegriffen wird, was wohl eher kein Feld sondern eher eine Methode ist.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Danke für die Blumen. Hab auch vor die Reihe bei Gelegenheit fortzusetzen
Code:
namespace GeometryMath
{
/// Defines a 3D Vertex3
public struct Vertex3
{
/// x,y,z Koordinates of Vertex
public double x, y, z;
/// Creates Vertex3 with given coordinates
public Vertex3(double px, double py, double pz)
/// Indexed acces to the three components of the Vertex3
public double this[int coordinate]
/// Gives the Vertex as an actual quaternion, i.e. the Vertex coordinates go to the imaginary components
/// of the Quaternion, while the real coordinate is zero.
public Quaternion EquivalentQuaternion()
/// The 2-Norm length of the Vertex = Sqrt(this^t*this)
public double Magnitude
{
get
{
return Math.Sqrt(x*x+ y*y + z*z);
}
}
/// Calculates this*this
public double DotDot
{
get
{
return x*x + y*y + z*z;
}
}
/// Returns the normalized Vector
public Vertex3 Normalized()
{
Vertex3 res = this;
res.Normalize();
return res;
}
/// Normalizes the Vertex inplace.
public bool Normalize()
/// Calculates DotProduct
public double Dot(Vertex3 v1)
{
return x * v1.x + y*v1.y + z*v1.z;
}
/// Cross product
public Vertex3 Cross(Vertex3 v1)
/// adds vectors
public Vertex3 Add(Vertex3 v1)
/// subtracts vectors
public Vertex3 Subtract(Vertex3 v1)
/// Scales the Vertex
public Vertex3 Scale(double lambda)
/// Adds to vertices
public static Vertex3 operator +(Vertex3 q1, Vertex3 q2)
/// Subtracts Vertices from another
public static Vertex3 operator -(Vertex3 q1, Vertex3 q2)
/// Builds inverse of Vertex
public static Vertex3 operator -(Vertex3 q1)
{
return q1.Scale(-1.0);
}
/// Returns the Vertex
public static Vertex3 operator +(Vertex3 q1)
{
return q1;
}
/// Calculates the dot Product
public static double operator *(Vertex3 q1, Vertex3 q2)
/// Scales the Vertex
public static Vertex3 operator *(double scale, Vertex3 q1)
return q1.Scale(scale);
/// Returns Vertex as string
public override string ToString()
{
return String.Format(CultureInfo.CurrentCulture, "({0}; {1}; {2})", x, y, z);
}
/// Returns whether the objects consists of real doubles or values of infty/nan, etc.
public bool RealDoubles
{
get
{
for (int i = 0; i < 3; i++)
{
if (double.IsInfinity(this[i]) || double.IsNaN(this[i])) {
return false;
}
}
return true;
}
}
}
}
Womit die Frage nach der Struktur geklärt sein müsste (ein paar Konstruktionsdetails hab ich entfernt, müsste aber alles wesentliche geblieben sein) - allerdings erlaubt C# auch methoden in structs - die werden dann halt von der Runtime fest hineinübersetzt. Nachdem sie nicht überschrieben werden können macht das auch Sinn und code der zusammengehört (also die funktionen die nur für das struct gedacht sind) kann so auch tatsächlich zusammengefasst werden... Und man könnte sonst Operatoren nicht überladen (jedenfalls nicht ala C#). Und die überladenen Ops haben das Programmieren des Raytracers in dieser Sprache irgendwie sehr freundlich und übersichtlich gestaltet.
Zuletzt geändert von Delphic am Mi Jun 24, 2009 11:40, insgesamt 2-mal geändert.
Registriert: So Jan 07, 2007 21:26 Beiträge: 130 Wohnort: mal hier mal da mal irgendwo
danke wirs geben ;P
kenne leute die sowas nich machen nur um einen zu ärgern aba ich muss auch ganz offen gestehen ...
Zitat:
warum bei einem Multiplikationsoperator auf den Quadratintegrierbaren Funktionen auf einem Messraum das Spektrum gleich dem wesentlichen Bild der Multiplikationsfunktion ist. Wenn ein element im Spektrum ist, so ists im Bild - das ist leicht, hab ich schon gebastelt (man negiert die folgerung und kanns dann einfach ausrechnen), aber anders rum, ists schwierig...
hab kein wort vertanden ;P
aba ich hab ja noch zeit um sowas zu verstehn ;P
cuz bubble
_________________ Wenn Worte nichts als Worte sind, dann müssen's Steine sein! Solange - bis sie pleite sind - schmeißt Fensterscheiben ein! - Fidl Kunterbunt -
benutzt du ja das struct bzw die klasse Vertex ... da ich leider noch nicht wirklich das alles mit vektoren und so verstehe liegen da schon meine probleme im tutorial (Vektorraum und was so dazu gehört kommt laut meinem tutor erst in der 13. Klasse und noch 2 jahre warten hab ich keine lust) also wollt ich fragen ob du mir vllt den quelltext von diesem struct zeigen könntest^^
hmm, dann bringt dir mein auszug erstmal noch nicht schrecklich viel, aber der code als solche wohl auch nicht. Das tolle an Vektorräumen ist aber, daß alles genau so läuft wie man erwartet (naja fast, aber im endlichdimensionalen ist alles prima ) Heisst, man versteht die Grundzüge auch recht stressfrei bevor man in der 13. Klasse ist und ein Mathestudium braucht man auch nicht anzugreifen. In jedem Fall ist es fast unumgänglich sich damit zu beschäftigen, wenn Du 3D Grafik machen willst. Am besten wird sein, wenn du Dir mal ein entsprechendes Buch ausleihst und Dich einliest. Kannstes ja erstmal mit dem Mathebuch zur Geometrie aus der 13. Klasse probieren (frech beim schulbibliothekar nachfragen) - dann solltest Du bereits das meiste stressfrei verstehen können. Nur die Bezeichnungen sind eventuell anders - ne Blick in die Wikipedia klärt einen dann meistens auf... Besonders die englische wiki ist in mathe sehr fit und damit auch im bereich Vektrorräumen/Geometrie.
Zitat:
hab kein wort vertanden ;P
Denk Dir nix Ist schon recht speziell was ich da mache. Hab übrigens ne Lösung gefunden
Zuletzt geändert von Delphic am Sa Jul 11, 2009 08:26, insgesamt 1-mal geändert.
Registriert: So Jan 07, 2007 21:26 Beiträge: 130 Wohnort: mal hier mal da mal irgendwo
Zitat:
beim schulbibliothekar nachfragen
du wirst es vllt nich glauben aber sowas ham wir nich ma .. (und unsere schule nennt sich mathematishc-naturwissenschaftlich-technisch erweitert)
ich hatte auch shcon ma direkt meinen Mathe Lehrer gefragt ... aba der darf mir das nich ausleihen weil die nur einen klassen satz ham und der wirklich jeden tach benutzt wird ...
warum ich dann aba nich ma nen buch inna mittagspause ham durfte weiß ich bis heute nich ;P
und inne uni kann ich auch noch nich ausleihen (anmeldung läuft noch^^)
cuz bubble
_________________ Wenn Worte nichts als Worte sind, dann müssen's Steine sein! Solange - bis sie pleite sind - schmeißt Fensterscheiben ein! - Fidl Kunterbunt -
Registriert: So Jan 07, 2007 21:26 Beiträge: 130 Wohnort: mal hier mal da mal irgendwo
naja meinte ja uni bibo ... aba da muss man halt erst angemeldet sein damit man die mitnehmen darf (also ausleihen)
genau so bei der stadtbibo
naja dann werd ich ma weiter googlen und mir das wiki durchlesen ;P
cuz bubble
_________________ Wenn Worte nichts als Worte sind, dann müssen's Steine sein! Solange - bis sie pleite sind - schmeißt Fensterscheiben ein! - Fidl Kunterbunt -
Registriert: So Jan 07, 2007 21:26 Beiträge: 130 Wohnort: mal hier mal da mal irgendwo
muahaha ich habs jetzte einiger maßen verstanden^^
und bin auch schon recht weit im tutorial (im ersten ;P)
aber hab doch doch noch ein paar problemchen gefunden ...
huhu
hab wieda nen bssl was gemacht ... und bin auf problemchen gestoßen
PSgn hab ich nich gefunden ... also einfach schnell selber deklariert und wollt fragen ob das so richtig is:
Code:
public int PSgn(double i)
{
if (i<0)
return -1;
else
return 1;
}
mein nächstes problem war dass ich nich wusste wohin mit ShootRay und RaytraceImage ... da hab ich dann wegen ner klasse/nem struct überlegt und bin hier drauf gekommen (hab in kommis nen paar probleme beschrieben)
Code:
public struct Camera
{
public Vertex3 Origin;
public int left,right,top,bottom;
public int widthpixels,heightpixels;
public int BackgroundColor;
public int[,] bild = new int[right-left,bottom-top]; /* <--ergibt Fehler: "Strukturen können keine Instanzfeldinizialisierer enthalten"
* vllt syntax-fehler? (hab mir mit nen 2d array gedacht den farbwert jedes pixels zu speichern)
* aber irgendwie gibs probleme mit dem name "bild"
*/
public double far,near;
public Sphere[] spheres;
public Ray ShootRay ( int x, int y )
{
Ray result = new Ray();
result.Origin = Position;
double xpart, ypart;
xpart=((double)x)/(double)widthpixels;
ypart=((double)y)/(double)heightpixels;
xpart = left + xpart * ( right - left);
ypart = top + ypart * (bottom - top);
result.Direction.Set(xpart,ypart,1.0);
result.Direction.Normalize(); //ich hab noch keinen brauchbaren quelltext zu dieser methode :(;P
return result;
}
public void RaytraceImage ()
{
int width = right - left;
int height = bottom - top;
for (int x = 0; x< width; x++)
for (int y = 0;y < height; y++)
{
Ray shoot = ShootRay(x,y);
double maxdist = double.MaxValue; //double.Infinity gabs net ... da hab ichs einfach damit probiert
ja und wollte halt fragen ob das bei deinem raytracer so ähnlich implementiert wurde ... oder halt ob das auch eine relativ leichte möglichkeit wäre
hoffe du kannst mir helfen :>
cuz bubble
_________________ Wenn Worte nichts als Worte sind, dann müssen's Steine sein! Solange - bis sie pleite sind - schmeißt Fensterscheiben ein! - Fidl Kunterbunt -
Zuletzt geändert von thebubble am Mi Nov 14, 2007 23:00, insgesamt 1-mal geändert.
Registriert: Mo Sep 02, 2002 15:41 Beiträge: 867 Wohnort: nahe Stuttgart
Diese Beiträge haben mich mal inspiriert, mich auch mal mit dem Thema auseinanderzusetzen und etwas auszuprobieren, wozu ich mit einigen Codebeispielen etwas größer ausholen muss. Sorry, falls es etwas arg lang wird; wenn ich übertrieben habe, kürze ich den Beitrag gerne noch...
Erstmal hab ich das erste Tutorial grob nach eigenen Vorstellungen interpretiert und mal mehr oder weniger Q&D (halt in Delphi und nicht in C#) drauf losgecodet.
Etwa sowas kam dabei raus:
Code:
[...]
for i :=0to767do
begin
P := Result.ScanLine[i];
for j :=0to1023do
begin
P^:= TracePixel((j-512)/512,(i-384)/512);
Inc(P);
end;
end;
end;
function TRaytracer.TracePixel(X, Y:Single): TRGBTriple;
const
Pos: TVector3f =(0.0,0.0,4.0);
r =1.0;
var
Ray: TVector3f;
a, b, c, q, Disk, x1, x2:Single;
begin
Ray[0]:= X;
Ray[1]:= Y;
Ray[2]:=1.0;
a := Scalar(Ray, Ray);
b :=-2*Scalar(Ray,Pos);
c := Scalar(Pos,Pos)-Sqr(r);
Disk :=Sqr(b)-4*a*c;
if Disk >=0then
begin
Disk :=Sqrt(Disk);
q :=-0.5*(b+psgn(b)*Disk);
x1 := q/a;
x2 := c/q;
if x2 < x1 then
x1 := x2;
Result := RGB(Trunc(16*x1),Trunc(16*x1),Trunc(16*x1));
end
else
Result := RGB(0,0,0);
end;
Das macht eigentlich genau das, was es soll, nämlich eine Kugel in Graustufen in der Mitte eines 1024x768 Bitmaps auszugeben. Die Ausgabe erspar ich euch einfach mal, die kann sich wohl jeder vorstellen.
Das ganze dauert in dieser Fassung bei mir (A64/3500+) etwa 110ms (mit Double 160ms), erlaubt also etwa 9 FPS. Ihr ahnt vielleicht schon, worauf ich hinaus will:
Ich hab mir dann mal eine Art Raytracing-Interface für OpenGL gebastelt; zunächst erstelle ich eine 32-bit-Bitmap:
Code:
bmp.Width:=1024;
bmp.Height:=768;
bmp.PixelFormat:= pf32bit;
for i :=0to bmp.Height-1do
begin
P := bmp.ScanLine[i];
for j :=0to bmp.Width-1do
begin
X := j;
Y := i;
P^.rgbBlue:= X div256;
P^.rgbGreen:= X mod256;
P^.rgbRed:= Y div256;
P^.rgbReserved:= Y mod256;
Inc(P);
end;
end;
bmp.SaveToFile(ToF);
Selbige wird auf ein Quad geklebt, das in einer Displaylist gezeichnet wird:
Code:
fList := glGenLists(1);
glNewList(fList, GL_COMPILE);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glClearColor(0,0,0,0);
glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
fShd.Activate('std');
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluOrtho2D(1,1,1,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
fTex.Bind('direction');
glBegin(GL_QUADS);
glTexCoord2i(0,0);
glVertex3f(-1,-1,0);
glTexCoord2i(1,0);
glVertex3f(+1,-1,0);
glTexCoord2i(1,1);
glVertex3f(+1,+1,0);
glTexCoord2i(0,1);
glVertex3f(-1,+1,0);
glEnd;
glEndList;
Beim Zeichnen wird selbige Liste dann einfach nur noch gecallt und der Buffer gewechselt. Der Shader, der durch fShd aktiviert wird, macht im Vertexteil nur ftransform(); und leitet die TexCoords weiter (was man sich wahrscheinlich auch sparen könnte).
Der Fragmentshader erledigt nun das hier:
Das Bild ist fast das gleiche, nur aus irgendeinem Grund ist alles ein paar Pixel nach links oben verschoben. Nun aber das sagenhafte Ergebnis auf meiner GF7900GT 512/AGP: 800 FPS, also etwa das 90fache...
Wenn GF7er-Grafikkarten bereits ohne SLI so optimiert sind, wäre es dann beim Ottonormal-Tracer performancetechnisch nicht wesentlich günstiger, auf der Grafikkarte zu raytracen? Oder hab ich hier irgendeinen Denkfehler? (Und sieht jemand den Grund, warum das GPU-Bild sich unterscheidet? )
die sache mit den grafikkarten ist, daß diese sowas 24x Parallel (und mehr - kenne mich bei neuen karten nicht mehr aus) rechnen können und ausserdem Vektoreinheiten bestehen, die auch noch die geometrie schneller berechnen können. Insofern sind sie verlässlich schneller, als eine standard CPU im ein-thread modus. Also wen wunderts, daß ein entsprechend optimierter Grafikprozessor schneller bei sowas ist, als ein All Purpose Prozessor? Spannend wird es aber bei entsprechend fortschrittlichen techniken - die lassen sich dann irgendwann verlässlich nicht mehr allein auf der karte durchrechnen - man teilt dann die last zwischen den prozessorarten auf - grafikkarte darf die langweiligen aber leicht parallelisierbaren sachen machen und die CPU die etwas anspruchsvolleren (sortieren, aufbereiten der daten für die karte, usw.).. Das klappt aber auch nicht bei allen darzustellenden Objekten gut. Ganz einfache analytische und besonders Polygone sind die metierts der Grafikkarte - kompliziertere analytische, wie etwa der blobtree (siehe projektthread) wehren sich mehr oder weniger erfolgreich gegen den einsatz von grafikkarten... Kommt halt immer drauf an, was das ziel des tracers ist, wie portabel und flexibel er sein muss, usw.. Es gibt da verschiedene Mischformen, etwa vekorPU+CPU/GPU+CPU/CPU/ raytracer... Alles da, je nach hardware, anforderungen und leidensdrang des entwicklers Und mein tracer ist z.B. lahm bei einfachen bildern, bei globaler beleuchtung ist er aber gar nicht mal soo schlecht dabei... kommt halt immer drauf an, was herauskommt. und grad wenn man seinen ersten tracer schreibt, weis man nicht wohin es sich entwickelt - konnte ich anfangs gar nicht abschätzen, daß er irgendwann globale beleuchtung rechen können sollte, und es war auch nicht geplant... es hat sich halt so entwickelt und ich hab zufällig eine webiste darüber entdeckt und mir gedacht, das will ich auch können - und dann hab ichs halt implementiert und da ist dann der tracer auf der CPU etwas überlegen, weil man da leichter drauf anpassen kann. hat man mehr erfahrung, ist die richtige mischung im aufteilen auf die verfügbaren prozessorarten sicher keine schlechte sache.
Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.