PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Rasterization Rules, OpenGL vs. Direct3D


Coda
2005-06-26, 22:56:48
Ich muss 2D Elemente in einen Viewport rendern und das ganze möglichst API unabhängig.

In Direct3D zumindest muss ich alle 2D Dinge um -0.5px verschieben, damit es funktioniert, wie sieht das bei OpenGL aus?

ScottManDeath
2005-06-27, 00:15:24
AFAIK nicht um 0.5 Pixel verschieben. Jedenfalls hab ich das nicht gemacht und es ging. =)


// projection ist identity, w, h sind die dimensionen
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0f,w,0.0f,h,-1.0f,1.0f);

// bedeckt jeden Pixel
glBegin(GL_QUADS);
glVertex2i(0,0);
glVertex2i(w,0);
glVertex2i(w,h);
glVertex2i(0, h);
glEnd();



Hat damit nichts direkt zu tun, aber:
Allerdings steht im Fragmentshader als gl_FragCoord.xy alles um +vec2(0.5,0.5) verschoben drinne. Pixel (1,1) -> Pixel(1.5,1.5).

Coda
2005-06-27, 00:41:21
Bitte sagt mir nicht, dass OpenGL andere Regeln definiert...

ScottManDeath
2005-06-27, 01:58:37
http://www.opengl.org/resources/faq/technical/transformations.htm ca 1/3 scrollen unter 9.030


Da steht ein Offset von 0.375 in xy Richtung drinne.

Xmas
2005-06-27, 03:44:40
"A fragment is located by its lower left corner, which lies on integer grid coordinates. Rasterization operations also refer to a fragment’s center, which is offset by (1/2, 1/2) from its lower left corner (and so lies on half-integer coordinates)."

"Fragment centers that lie inside of this polygon are produced by rasterization."

zeckensack
2005-06-27, 15:09:25
Ich muss 2D Elemente in einen Viewport rendern und das ganze möglichst API unabhängig.

In Direct3D zumindest muss ich alle 2D Dinge um -0.5px verschieben, damit es funktioniert, wie sieht das bei OpenGL aus?Definiere "2D Dinge".
Wenn du mit Pixel-Koordinaten arbyten willst, darfst du Polygone (Tris, Quads) nicht verschieben.

Linien und Punkte dagegen solltest du um 1/2 verschieben.

Die Info aus FAQ 9.030 halte ich für irreführend und unpraktikabel. Unter anderem wird damit ein sauberes Verhalten bei Auflösungänderung verhindert, Texturfilter!=GL_NEAREST funktionieren damit nicht wie man sich das erwarten würde etc. Unter "exact pixelization" stelle ich mir was anderes vor.

Coda
2005-06-27, 15:13:42
2D Dinge ala textured quads.

Transformationsmatrix ist so eingestellt (orthographisch) dass die Koordinaten den Pixelkoordinaten entsprechen.

Und in D3D muss ich das es richtig aussieht wenn ich von (20,20)-(40,40) ein Quad zeichnen will (19.5,19.5)-(39.5,39.5) nehmen.

zeckensack
2005-06-27, 15:25:28
2D Dinge ala textured quads.

Transformationsmatrix ist so eingestellt (orthographisch) dass die Koordinaten den Pixelkoordinaten entsprechen.

Und in D3D muss ich das es richtig aussieht wenn ich von (20,20)-(40,40) ein Quad zeichnen will (19.5,19.5)-(39.5,39.5) nehmen.Oh weh ;(

Nur damit wir uns vollends verstehen:
Wenn du in OpenGL ein Rechteck von (20;20) bis (40;40) zeichnest, ist es
a)exakt (dh zB dass beliebiges AA für dieses Rechteck nichts bewirkt)
b)genau 20 Pixel breit und 20 Pixel hoch
edit:
und
c)eine 20x20-(NPOT-)Textur mit Texturkoordinaten von genau (0;0) bis genau (1;1) wird pixelexakt auf das Rechteck abgebildet, egal welche Filter-/Clamp-Modi eingestellt wurden

Coda
2005-06-27, 15:34:30
Was ein Quark hat sich da MS bloß wieder ausgedacht.

Demirug
2005-06-27, 15:38:43
MS definiert eben den Pixelmittelpunkt als 0;0. Macht ja durchaus auch Sinn

http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/gettingstarted/direct3dtextures/coordinates/mappingtexelstopixels.asp?frame=true

zeckensack
2005-06-27, 15:40:18
Was ein Quark hat sich da MS bloß wieder ausgedacht.Ich war eigentlich bis gerade eben davon überzeugt, dass die rasterization rules ab Direct3D 6 exakt mit denen von OpenGL übereinstimmen.

Bis Direct3D 5 hatte MS noch eigene Regeln, die aber herzlich wenig Sinn machten (da inhärent auflösungsabhängig). Das sollte aber wie gesagt längst Geschichte sein.

Ich bin jetzt auch leicht verwirrt, bzw frage mich was das soll :conf2:

Coda
2005-06-27, 15:43:05
Ich nehme alles zurück, bin selber doof. Ich habe die Matrix benützt die bei glOrtho(0,screen_width,screen_height,0,-1,1) rauskommt... wer entdeckt den Fehler :crazy:

zeckensack
2005-06-27, 15:44:49
MS definiert eben den Pixelmittelpunkt als 0;0. Macht ja durchaus auch Sinn

http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/gettingstarted/direct3dtextures/coordinates/mappingtexelstopixels.asp?frame=trueMacht wenig Sinn.
Um ein Texel in einer 4x1-Textur zu treffen muss man ja auch bei DXG auf (1/8+n/4;0.5) zielen, und nicht auf (n/4;0) -- interpoliert, oder direkt. Das sollte IMO schon bei Texeln und Pixeln gleich laufen.

Coda
2005-06-27, 16:05:55
Mhm ja, mit Supersampling muss ich trotzdem noch um -0.5 verschieben dass es kein Gematsche gibt. Fragt sich nur ob das mit OpenGL auch so ist...

ScottManDeath
2005-06-27, 16:14:52
Ich nehme alles zurück, bin selber doof. Ich habe die Matrix benützt die bei glOrtho(0,screen_width,screen_height,0,-1,1) rauskommt... wer entdeckt den Fehler :crazy:

Transponierte Matrix?

Z Range von GL -1...1 anstelle von DX 0....1 ?

zeckensack
2005-06-27, 16:15:50
Mhm ja, mit Supersampling muss ich trotzdem noch um -0.5 verschieben dass es kein Gematsche gibt. Fragt sich nur ob das mit OpenGL auch so ist...Supersampling vermatscht dir auch unter OpenGL die Texturen (aber es verschiebt wenigstens keine Geometrie).
Allerdings ist das nicht die Sorte Vermatschen, die man mit verschobenen Koordinaten ausgleichen könnte. Ich kapiere jetzt auch gerade nicht wie das gehen soll.

Bei 2x2 OGSS hast du auf einem (gewollten) Pixel immer vier Textursamples, dh auch immer Matsch. Du kannst IMO weder DXG noch OpenGL irgendwie dazu zwingen, dir für alle vier Subpixel das gleiche Textursample zu geben.

Äääää, doch, mit dem "nearest"-Filter :redface: :conf2:

zeckensack
2005-06-27, 16:48:29
Ich nehme alles zurück, bin selber doof. Ich habe die Matrix benützt die bei glOrtho(0,screen_width,screen_height,0,-1,1) rauskommt... wer entdeckt den Fehler :crazy:Ich jedenfalls nicht. IMO ist das genau richtig.
(0;0) ist dann zwar oben links statt unten links, aber das wolltest du wohl auch so haben ... denke ich mal.

Coda
2005-06-27, 16:51:33
glOrtho(0,screen_width-1,screen_height-1,0,-1,1); :rolleyes:

Bei 640x480 geht es von 0-639 bzgl 0-479...

zeckensack
2005-06-27, 17:09:56
glOrtho(0,screen_width-1,screen_height-1,0,-1,1); :rolleyes:

Bei 640x480 geht es von 0-639 bzgl 0-479...Nö, eben nicht.
Die Pixelmittelpunkte sind ein Stück weiter innen, und von denen gibt's nur 640x480, ja.
Aber Pixelkanten gibt es 641x481. Die linke untere Ecke ist (-1;-1), die rechte obere Ecke ist (+1;+1). Und wenn du Quads zeichnest, dann tust du das zwischen Kanten, und nicht auf Mittelpunkten.

Klingt blöd, ist aber so X-D

zeckensack
2005-06-27, 17:18:59
Übungsaufgabe 0 ;)
Zeichne in einem 640x480 großen Viewport ein senkrechtes, 1x480 Pixel großes Rechteck gaaaaanz rechts.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,640.0,0.0,480.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glBegin(GL_QUADS);
glVertex2f(639.0f, 0.0f);
glVertex2f(640.0f, 0.0f);
glVertex2f(640.0f,480.0f);
glVertex2f(639.0f,480.0f);
glEnd();

Übungsaufgabe 1 :|
Fülle einen 640x480 großen Viewport mit 640 senkrechten, jeweils ein Pixel breiten Streifen. Diese Streifen sollen abwechselnd grün und rot sein.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,640.0,0.0,480.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

for (int i=0;i<640;++i)
{
if ((i&1)==0) glColor4ub(0,255,0,255);
else glColor4ub(255,0,0,255);

float x0=(float)i;
glBegin(GL_QUADS);
glVertex2f(x0 , 0.0f);
glVertex2f(x0+1.0f, 0.0f);
glVertex2f(x0+1.0f,480.0f);
glVertex2f(x0 ,480.0f);
glEnd();
}

Coda
2005-06-27, 17:33:04
Nach der D3D Doku sind aber die Pixelmittelpunkte relevant.

zeckensack
2005-06-27, 18:38:42
Nach der D3D Doku sind aber die Pixelmittelpunkte relevant.Ja, natürlich.
Wenn du aber ein Quad mit 0 Fläche zeichnest, kriegst du garnichts. Das muss schon mindestens ein Pixel breit und hoch sein. Gefüllt werden die Pixel, deren Mittelpunkte in dem Quad liegen, und das erreicht man indem man die Geometrie auf die Kantenkoordinaten setzt, die um diesen Mittelpunkt herum liegen. 640 Mittelpunkte => 641 Kanten.

Die Pixelmittelpunkte als Geometriekoordinaten zu verwenden ist pöhse. Mal ganz davon abgesehen dass deine interpolierten Texturkoordinaten dann um 1/2*n daneben liegen, reicht schon ein LSB an Rundungsfehler, um die Geometrie um einen ganzen Pixel verrutschen zu lassen. Und mit AA sieht's dann sowieso schweinisch aus.

Das ist bei DXG genau so wie bei OpenGL, nur mit dem Unterschied dass bei DXG der Koordinatenursprung für Geometrie auf einem Mittelpunkt liegt, und bei OpenGL auf einer Kante.

Coda
2005-06-27, 19:54:52
Naja, im Moment scheint es so zu klappen.

Ich habe im Moment nur eine Direct3D Backend DLL, insofern kann ich nicht überprüfen ob es mit OpenGL so auch funktioniert.

In den Semesterferien wird sich das hoffentlich ändern, allerdings ahne ich übles bezüglich dem GLSL Support von nVIDIA.

Demirug
2005-06-27, 20:15:00
In den Semesterferien wird sich das hoffentlich ändern, allerdings ahne ich übles bezüglich dem GLSL Support von nVIDIA.

Wieso?

Coda
2005-06-27, 20:22:50
Das geht doch durch den CG Compiler bei denen und ist mehr schlecht als recht gelöst. Bei dem Shadertest-Tool von 3DLabs fällt ja auch die Hälfte der Shader durch mit nVIDIA Karten.

Und der CG-Compiler war das letzte Mal als ich davon gelesen habe auch nicht gerade das Optimierungswunder.

Demirug
2005-06-27, 20:34:18
Das geht doch durch den CG Compiler bei denen und ist mehr schlecht als recht gelöst. Bei dem Shadertest-Tool von 3DLabs fällt ja auch die Hälfte der Shader durch mit nVIDIA Karten.

Und der CG-Compiler war das letzte Mal als ich davon gelesen habe auch nicht gerade das Optimierungswunder.

Für das Optimieren ist inzwischen sowieso der Treiber interne Optimizier zuständig und selbst der hat noch Zwischestufen. Eine davon ist eine weitere Shadersprache.

Coda
2005-06-27, 20:38:38
Auf Hochsprachenlevel hat man aber noch mehr Informationen zur Optimierung zur Verfügung.

Demirug
2005-06-27, 20:44:43
Auf Hochsprachenlevel hat man aber noch mehr Informationen zur Optimierung zur Verfügung.

Deswegen sieht ja das was der Cg Compiler rauswirft teilweise etwas merkwürdig aus. Das ist der Versuch die Informationen in den Assemblercode zu retten. Das fällt aber sowieso flach wenn man den Compiler benutzt der sich direkt im Treiber befindet. Dieser benutzt die entsprechenden Backend ja gar nicht.

Coda
2005-06-27, 21:05:27
Ich werde ja sehen wie die Performance im Gegensatz zu Direct3D + HLSL ist :)

ScottManDeath
2005-06-27, 21:07:41
Deswegen sieht ja das was der Cg Compiler rauswirft teilweise etwas merkwürdig aus. Das ist der Versuch die Informationen in den Assemblercode zu retten. Das fällt aber sowieso flach wenn man den Compiler benutzt der sich direkt im Treiber befindet. Dieser benutzt die entsprechenden Backend ja gar nicht.


Man kann sich vom NVIDIA GLSL Compiler (dem integrierten CG) den Assemblercode ausgeben lassen. Das war hilfreich um einige Bugs zu bestätigen. AFAIK wird dieser Assemblercode dann im Treiber weiter verarbeitet, so als ob CG ausserhalb sitzen würde. Man kann CG auch per Kommandozeilenparameter GLSL Code verarbeiten lassen.

@Coda

Hab jetzt einige Erfahrungen mit NVIDIAs GLSL Compiler sammeln können. Im Großen und Ganzen hat es geklappt, allerdings solltest Du stehts aktuelle (Beta) Treiber haben da mir einige Bugs über den Weg gelaufen sind die mir auch von einem nv Menschen bestätigt wurden. Im aktuelleren Treiber waren sie dann meist gefixt.

Bsp: Wenn Du im Fragmentshader Schleifen verwendest, musst Du aufpassen dass der Iterationszähler die 255 nicht überschreitet. Der Compiler schluckt das zwar, wenn Du mehr Iterationen hast, führt aber nur 255 aus. Entweder schachtelt man mehrere Schleifen oder man macht partielles loopunrolling wie ich. AFAIK noch nicht gefixt.

Mit MRT unter OpenGL ist es auch nicht so einfach. gl_FragData erzeugt eine Warnung wegen undefinierter Variable, allerdings sind der generierte ASM code ok und es funzt auch.


Dort steht dazu drinne:
http://developer.nvidia.com/object/nv_ogl2_support.html

NVemulate kann auch strenge Compilerwarnungen aktivieren, dann erkennt man die gröbsten Schnitzer....

Coda
2005-06-27, 21:23:44
Bsp: Wenn Du im Fragmentshader Schleifen verwendest, musst Du aufpassen dass der Iterationszähler die 255 nicht überschreitet. Der Compiler schluckt das zwar, wenn Du mehr Iterationen hast, führt aber nur 255 aus. Entweder schachtelt man mehrere Schleifen oder man macht partielles loopunrolling wie ich. AFAIK noch nicht gefixt.Ey, ich will meine GPU nicht als Streamprozessor missbrauchen, das ganze sollte noch mit FPS laufen nicht SPF :D

Für MRT habe ich zumindest im Moment auch noch keine Anwendung, aber wer weiß...

ScottManDeath
2005-06-27, 21:42:37
Ey, ich will meine GPU nicht als Streamprozessor missbrauchen, das ganze sollte noch mit FPS laufen nicht SPF :D

Für MRT habe ich zumindest im Moment auch noch keine Anwendung, aber wer weiß...

:whistle:


#ifdef WORKAROUND
gl_TexCoord[0].x = gl_MultiTexCoord0.x - 0.5;
gl_TexCoord[0].y = gl_MultiTexCoord0.y - 0.5;
gl_TexCoord[0].z = gl_MultiTexCoord0.x + 0.5;
gl_TexCoord[0].w = gl_MultiTexCoord0.y + 0.5;
#else
gl_TexCoord[0] = gl_MultiTexCoord0.xyxy + vec4(-0.5, -0.5, 0.5, 0.5);
#endif


Der Bug ist inzwischen gefixt.