PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : glViewport


Kennung Eins
2003-01-15, 19:44:52
Hallöchen,

ich hab grad ein kleines Problemchen mit glViewport.

Wenn ich das richtig verstanden habe, kann man damit sozusagen "Subfenster" in einem Renderbereich erstellen, so daß man in der Einen Region eben zB. einen Teil der Szene mit Flat Shading, im anderen Teil Gouraud Shading darstellen kann.

Ok, nun habe ich hier die Aufgabe, ein Fenster mit glViewport in zwei Teile zu teilen.
Links kommen durch Raycasting dargestellte Kugeln rein, rechts durch Gouraud Shading beleuchtete Kugeln.
So weit so gut.

Nun mach das glViewport aber irgendwie eine ganz seltsame Sache:
Ich rendere erst die Raycasting Geschichte. Wenn die fertig ist, erstelle ich das zweite glViewport rechts neben dem ersten.
Und in diesem Moment rutscht das Bild, was gerade links gerendert wurde, nach rechts in den anderen Viewport.

Warum macht das glViewport denn jetzt das, was es macht?

Vielleicht hat ja schon bei dieser Beschreibung jemand eine Idee, was mein Fehler sein könnte.
Wenn nicht, klamüser ich mal noch ein bisschen Quellcode zusammen.

Kennung Eins
2003-01-15, 21:09:23
hm ich hab eben mal das glViewport an ein paar anderen Stellen im Quellcode ausprobiert, und nun gehts ...

Xmas
2003-01-16, 00:19:14
Hmja, das ist eigentlich nicht so ganz im Sinne des Erfinders :|

glViewport erzeugt keinen Viewport, es verschiebt/vergrößert den Viewport (es gibt nur einen pro RC).
Die saubere Variante wäre, die Projektionsmatrix anzupassen und mit glScissor das Renderfenster innerhalb des Viewports zu begrenzen.


Wieso machst du eigentlich das Raycasting mit OpenGL?

zeckensack
2003-01-16, 07:11:40
1. Es gibt pro Fenster nur einen Backbuffer. Also darf man erst dann swappen, wenn man alle gewünschten Viewports fertig gezeichnet hat.

Also nicht
glViewPort...
draw_stuff();
SwapBuffers(display_context); //<- ganz schlecht
glViewPort...
draw_more_stuff();
SwapBuffers(display_context);

sondern
glViewPort...
draw_stuff();
glViewPort...
draw_more_stuff();
SwapBuffers(display_context);


2. Viewport!=rendering context. Sie haben keine eigenen voneinander getrennten Render States, sondern teilen alle Einstellungen (Matrizen, Blend Modes, Texturen, etc). Was du also im 'rechten' Viewport einschaltest, aber für den 'linken' nicht brauchst, mußt du auch immer wieder abschalten.

Kennung Eins
2003-01-16, 08:13:52
Ah, danke für die Aufklärung!
Ich dachte das wären dann 2 separate Render-Fenster.
Was für einen Sinn hat dann glViewport?

Wenn ich also nun mache glEnable(GL_LITHING), dann gilt das ja augenscheinlich für beide Viewports.
Denn wenn ich Licht anknipse, wird meine Raycast-Kugel komplett weiss, und sieht nur noch aus, wie ein flacher Kreis.

Andererseits, wenn ich kein Licht angeschaltet habe, ist meine durch gluSphere erzeugte Kugel komplett schwarz (ist ja schliesslich "Nacht") bzw komplett mit einer Farbe gefüllt.

Könnte man das irgendwie hinkriegen, daß beides zugleich (Raycasting + G. Shading) sichtbar ist?

Originally posted by Xmas
Wieso machst du eigentlich das Raycasting mit OpenGL? Das ist eine Aufgabe für die Uni :)

zeckensack
2003-01-16, 09:39:20
Originally posted by Kennung Eins
Ah, danke für die Aufklärung!
Ich dachte das wären dann 2 separate Render-Fenster.
Was für einen Sinn hat dann glViewport?glViewport steuert quasi die letzte Transformationsmatrix, obwohl's in der Praxis wesentlich einfacher implementiert wird.

Damit bestimmst du 'wohin' das ganze kommt. Wenn du dir im Gegensatz dazu glScissor anschaust, das nur bestimmte Teile durchläßt, dann sollte es klar werden.

Wenn du den Viewport änderst, dann bleibt das Koordinatenssystem zwar gleich, aber gilt danach nur noch bezogen auf den Viewport.

Mit glScissor bezieht sich das Koordinatensystem weiterhin auf's komplette Fenster (respektive auf den komplette Viewport), es wird lediglich ein Update der außerhalb gelegenen Bildbereiche verhindert.

Sowas zB macht man mit glScissor:

Kennung Eins
2003-01-16, 16:34:10
oki, das werd ich mal probieren!

so siehts momentan aus:

oben Licht aus
links Raycasting, rechts gluSphere
unten Licht an

Xmas
2003-01-16, 17:22:41
Originally posted by Kennung Eins
oki, das werd ich mal probieren!

so siehts momentan aus:

oben Licht aus
links Raycasting, rechts gluSphere
unten Licht an
Wie genau machst du denn das Raycasting?
Und es ist doch kein Problem das Licht zu jedem beliebigen Zeitpunkt ein- und auszuschalten.

Kennung Eins
2003-01-16, 17:35:56
Bisher mache ich es so:
procedure initSpheres;
var i:integer;
begin

num_spheres:=1;
setlength(spheres,1);

spheres[0].radius:=0.5;
spheres[0].mx:=0;
spheres[0].my:=0;
spheres[0].mz:=0;
spheres[0].r:=255;
spheres[0].g:=255;
spheres[0].b:=255;

end;

function intersection(x1,y1,z1,x2,y2,z2:real):integer;
var x3,y3,z3,r,
a,b,c,i,
farber,farbeg,farbeb,
u,
schnittX, schnittY, schnittZ,
normaleX, normaleY, normaleZ,
farbeFaktor:real;
j,ergebnis:integer;
begin
ergebnis:=0;
farbeFaktor:=1;

for j:=0 to NUM_SPHERES-1 do begin
x3:= spheres[j].mx;
y3:= spheres[j].my;
z3:= spheres[j].mz;
r:= spheres[j].radius;

a := sqr(x2 - x1) + sqr(y2 - y1) + sqr(z2 - z1);
b := 2* ( (x2 - x1)*(x1 - x3)
+ (y2 - y1)*(y1 - y3)
+ (z2 - z1)*(z1 - z3) ) ;
c := sqr(x3) + sqr(y3) +
sqr(z3) + sqr(x1) +
sqr(y1) + sqr(z1) -
2* ( x3*x1 + y3*y1 + z3*z1 ) - sqr(r) ;
i := b * b - 4 * a * c ;

b:= b/a;
c:= c/a;
a:= 1;

//Schnitt?
if(i>= 0.0) then begin
ergebnis:=j+1;
break;
end;
end;

result:=ergebnis;

if(ergebnis>0) then begin

ergebnis:=ergebnis-1;

//schnittpunkt berechnen
u:= (((-1)*b)/2) + sqrt(((b*b)/4)-c);
schnittX:= x1 + (u*(x2 - x1));
schnittY:= y1 + (u*(y2 - y1));
schnittZ:= z1 + (u*(z2 - z1));

//normalenvektor berechnen
normaleX:= (schnittX - x3) / r;
normaleY:= (schnittY - y3) / r;
normaleZ:= (schnittZ - z3) / r;

//winkel zwischen dem normalenvektor und dem strahl berechnen ( farbeFaktor=cos(alpha) )
farbeFaktor:= 0.0025*abs( (((x2 - x1)*normaleX)+((y2 - y1)*normaleY)+((z2 - z1)*normaleZ)) / ( sqrt(sqr((x2 - x1))+sqr((y2 - y1))+sqr((z2 - z1))) * sqrt(sqr(normaleX)+sqr(normaleY)+sqr(normaleZ)) ) );

//farbe berechnen und setzen
farbeR:=spheres[ergebnis].r*farbeFaktor;
farbeG:=spheres[ergebnis].g*farbeFaktor;
farbeB:=spheres[ergebnis].b*farbeFaktor;
glColor3f(farbeR, farbeG, farbeB);
end;
end;

procedure Draw;
var p:array[0..7] of real;
x,y,z,copx,copy,copz,fh,fw:real;
begin

glViewport( 0,0, 300,300);
glMatrixMode( GL_PROJECTION);
glLoadIdentity();

glClearColor( 0.4, 0.4, 0.4, 1); //grauer Hintergrund

fw:=300;
fh:=300;

copX := 0.0;
copY := 0.0;
copZ := 3.0;
x:=-1.0;
y:=-1.0;
z:=0;

glBegin( GL_POINTS);
repeat
repeat
if intersection(copX, copY, copZ, x, y, z)>0 then
glVertex3f(x, y, z);
y:=y+(2.0/fh);
until y>=1.0;
y:=-1;
x:=x+(2.0/fw);
until x>=1.0;
x:=-1;
glEnd;

SwapBuffers(wglGetCurrentDC);

end;