DGL
https://delphigl.com/forum/

Terrain Shader GPU4
https://delphigl.com/forum/viewtopic.php?f=20&t=9429
Seite 1 von 2

Autor:  Dropye [ Do Aug 26, 2010 20:19 ]
Betreff des Beitrags:  Terrain Shader GPU4

Hi

aus gründen der geschwindigkeit und auch weil es schöner aussieht *g möchte ich meine heightmaps demnächst mit dem o.g. shader aus der shadersammlung rendern

den shader einlesen die variablen suchen und alles ist kein problem das funktioniert allerdings habe ich ein paar fragen zur nutzung

als erstes die alphamap, wie soll die aussehen? verschieden farbig oder einfach in 3 ebenen? und welches format? das steht ja alles nicht dabei

desweiteren ist 1 VBO 65x65 gefordert, auch da war das erstellen nicht das problem nur wie soll ich die daten ablegen?

ich möchte hierbei ersteinmal die einfachere variante über den hauptspeicher nehmen also müsste ich dem vbo eigentlich ein 2 dimensionales array geben indem nur x und y koordinaten gespeichert sind von einem 65x65 feld oder?

ich hoffe ihr konntet mir folgen :)

lg

Autor:  Coolcat [ Do Aug 26, 2010 21:29 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

Zitat:
als erstes die alphamap, wie soll die aussehen? verschieden farbig oder einfach in 3 ebenen?

Die Farbkanäle der Alphamap steuern wie stark welche Textur benutzt wird. Rot ist die erste Textur, Grün die zweite und Blau die dritte. Die Farben sollten sich in jedem Pixel zu 1.0 (bzw. 255) addieren.

Zitat:
also müsste ich dem vbo eigentlich ein 2 dimensionales array geben indem nur x und y koordinaten gespeichert sind von einem 65x65 feld oder?

Richtig. Im Shader wird die Position einer Ecke des 65x65 Blocks auf die 3D-Vertices addiert um die richtige Position zu erhalten. Wie du das in den VBO bekommst ist relativ egal. Ggf. schaust du dir das VBO-Tutorial an.

Autor:  Dropye [ Fr Aug 27, 2010 14:25 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

ah, super

ich habe heute leider keine möglichkeit mehr das zu testen aber ich werde das übers wochenende machen danke dir :)

Autor:  Dropye [ So Aug 29, 2010 00:05 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

so ich hab jetzt weitergeschrieben

ich habe nun ein kleines record geschrieben wo die x und y koordinaten der einzelnen punkte liegen (bzw eig sind es ja x und z)

Code:
  VertexPos = record
    X : Double;
    Y : Double;
  end;


dazu habe ich ein array eingefügt das genau 65x65 groß ist

Code:
const
  MapSize = 65;
[..]
  TMapManager=class
    MapDaten : array of array of VertexPos;
[...]


befüllt wird die sache in einer schleife die einfach ihren zählwert an das array weitergiebt

Code:
procedure TMapManager.GetMapCoords;
var x,y : Integer;
begin
  SetLength(MapDaten, MapSize+1);
  for x := 0 to MapSize do
    SetLength(MapDaten[x], MapSize+1);

  for x := 0 to MapSize do
    for y := 0 to MapSize do begin
      MapDaten[x,y].X := X;
      MapDaten[x,y].Y := y;
    end;


danach kommt der interessant teil ich erstelle ein VBO weise ihm alles nötige zu und kopiere meine "MapDaten" in das VBO

Code:
procedure TMapManager.CreateVBO;
begin
  glGenBuffers(1, @Map_VBO);
  glEnableClientState(GL_VERTEX_ARRAY);
  glBindBuffer(GL_ARRAY_BUFFER, Map_VBO);
  glBufferData(GL_ARRAY_BUFFER, SizeOf(MapDaten), @MapDaten, GL_STATIC_DRAW);
end;



nun habe ich also einen shader der bereits über alle texturen verfügt und ein vbo 65x65 mit x und y(z) koordinaten
nur gibt es allerdings nichts womit ich dem shader sagen könnte nimm das vbo als punkte zum renden

also ich mein selbst wenn ich rein die rendere vbo procedure nehme passiert nichts
also ich hab derzeit den befehl drin aber machen tut er nich viel^^

Code:
  glInterleavedArrays(GL_V2F, SizeOf(VertexPos), @Map_VBO);
  glDrawArrays(GL_Quads, 0, MapSize);


wie gesagt seh ich leider nix, und die fps von rund 5k lassen auch nicht vermuten das er irgendwo bzw auch nur versucht etwas zu zeichnen

Autor:  sharkman [ So Aug 29, 2010 06:37 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

Naja, mit
Code:
glDrawArrays(GL_Quads, 0, MapSize);
zeichnest du das zeug natürlich als Quads. Dann müssen in deinem VBO aber auch quads sein. Warum du aber nichts siehst, weiß ich auch nicht. Wenn das Zeug 64*64 groß wäre, na gut, aber so müsste zumindest irgendwo am Rand was sein... :idea: ähm, was nimmt dein shader als Input? Wenn der jetzt nämlich points will, und du gibst ihm Quads, wird der nicht viel Ahnung haben, was er damit machen soll.

mfg

sharkman

Autor:  Dropye [ So Aug 29, 2010 09:03 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

nunja aber auch wenn ich schreibe

glDrawArrays(GL_points, 0, MapSize);

dann sagter einfach nix, und in welcher form der shader die punkte haben will? keine ahnung der shader will die ja gar nicht haben das is ja das was ich nicht verstehe

Autor:  Coolcat [ So Aug 29, 2010 09:35 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

Code:
VertexPos = record
    X : Double;
    Y : Double;
  end;

Die Grafikkarte kann nur floats, dürfte einer der Gründe sein warum du nix siehst.

Der andere Grund ist das bei glInterleavedArrays die letzten beiden Argumente 0 sein sollten. Wenn ein VBO gebunden ist (über glBindBuffer) , wird dieses als Quelle für Vertexdaten benutzt. In diesem Fall wird das letzte Argument von glInterleavedArrays als Offset interpretiert, deine Daten liegen am Anfang des Buffers, also sollte der Offset 0 sein. Genauso liegen deine Daten direkt hintereinander im Buffer, daher kann auch der stride 0 sein. (du kannst auch die Vertexgröße nehmen, sollte äquivalent sein)

Letztlich musst du irgendwie eine Fläche von 64x64 Quads rendern bei denen die Vertexkoordinaten eben einfach der X/Z-Position entsprechen. Ich verwende zusätzlich zum VBO noch ein IBO (IndexbufferObject) um zu sagen welche Vertices zusammen Dreiecke bilden.

Code:
#define TERRAIN_LEAFSIZE 64

// create vertex buffer object
   {
      glGenBuffers(1, &m_vboLeaf);
      glBindBuffer(GL_ARRAY_BUFFER, m_vboLeaf);
      int m_verts = TERRAIN_LEAFSIZE+1;
      int data_size = m_verts*m_verts*2*sizeof(float);
      glBufferData(GL_ARRAY_BUFFER, data_size, NULL, GL_STATIC_DRAW);
      float* data = (float*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
      int pos = 0;
      for (int y=0; y<m_verts; ++y) {
         for (int x=0; x<m_verts; ++x) {
            data[pos++] = x;
            data[pos++] = y;
         }
      }
      glUnmapBuffer(GL_ARRAY_BUFFER);
   }


   // create index buffer object
   {
      glGenBuffers(1, &m_iboLeaf);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_iboLeaf);
      int m_verts = TERRAIN_LEAFSIZE+1;
      int data_size = TERRAIN_LEAFSIZE*TERRAIN_LEAFSIZE*2*3*sizeof(GLushort);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, data_size, NULL, GL_STATIC_DRAW);
      GLushort* data = (GLushort*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
      int pos = 0;
      for (int y=0; y<TERRAIN_LEAFSIZE; ++y) {
         for (int x=0; x<TERRAIN_LEAFSIZE; ++x) {
            data[pos++] = (x+0) + (y+0) * m_verts;
            data[pos++] = (x+0) + (y+1) * m_verts;
            data[pos++] = (x+1) + (y+1) * m_verts;
            data[pos++] = (x+1) + (y+1) * m_verts;
            data[pos++] = (x+1) + (y+0) * m_verts;
            data[pos++] = (x+0) + (y+0) * m_verts;
         }
      }
      glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
   }




Zitat:
dann sagter einfach nix, und in welcher form der shader die punkte haben will? keine ahnung der shader will die ja gar nicht haben das is ja das was ich nicht verstehe

Wenn man Shader benutzt ist es sinnvoll zu wissen wie die Rendering-Pipeline funktioniert. Der Vertexshader erhält sämtliche Vertices die du der Grafikkarte zum rendern gibst und modifiziert diese. Es spielt hier keine Rolle ob du Punkte, Linien oder Dreiecke renderst. Mit Quads kann die Grafikkarte allerdings gar nicht umgehen, diese werden durch Dreiecke emuliert.
Erst im Primitive-Assembly-Schritt werden die einzelnen Vertices zu Linien oder Dreiecken zusammengesetzt. Wenn es einen Indexbuffer gibt kommt dieser auch erst hier zum tragen. Bei der Rasterisierung wird dann die Linie oder das Dreieck in Pixel zerlegt und für jedes Fragment (Pixel) der Fragmentshader aufgerufen.
Bild

Autor:  Dropye [ So Aug 29, 2010 15:18 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

Zitat:
Die Grafikkarte kann nur floats, dürfte einer der Gründe sein warum du nix siehst.


floats sind doch gebrochene zahlen? Double sind auch gebrochene zahlen also eigentlich müsste das gehen

hab aber jetzt mal TGLFloat genommen

ich hab mal getestet wenn ich den shader nicht erstelle sehe ich meine dreiecke

diese zeichne ich gerade in einer schleife selber als 65x65 block

erstelle ich den shader aber so seh ich nix, aber ich hab mir mal gedanken gemacht über die variablen die ich übergebe könnte da ein fehler liegen?

den seit dem ich alles etwas geordnet und umgeschrieben habe sagt opengl das der vorgang nicht gültig wäre

ich such die variablen im allgemeinen so

Code:
  HeightMap := glGetUniformLocation(SelShader, 'heightmap');
  Layer0 := glGetUniformLocation(SelShader, 'Layer0');
  Layer1 := glGetUniformLocation(SelShader, 'Layer1');
  Layer2 := glGetUniformLocation(SelShader, 'Layer2');
  alpha := glGetUniformLocation(SelShader, 'alpha');
  leafmin := glGetUniformLocation(SelShader, 'leafmin');


und neue werte übergebe ich so

Code:
  glUniform1f(MapShader.Layer0, MapLayer0);
  glUniform1i(MapShader.Layer1, MapLayer1);
  glUniform1i(MapShader.Layer2, MapLayer2);
  glUniform1i(MapShader.HeightMap, HeigthMap);
  glUniform1i(MapShader.alpha, AlphaMap);
  glUniform2i(MapShader.leafmin, 0,0);


is das erstmal so richtig?

Autor:  Coolcat [ So Aug 29, 2010 15:30 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

Zitat:
floats sind doch gebrochene zahlen? Double sind auch gebrochene zahlen also eigentlich müsste das gehen

Floats sind 4 Byte groß, während Doubles die doppelte Genauigkeit haben und daher 8 Byte groß sind. glBufferData führt keine implizite Typkonvertierung durch sondern kopiert die Daten einfach nur so wie sie sind in den Buffer. Folglich wird dann ein Double als 2 Floats interpretiert, was natürlich Unsinn ist.

Code:
  glUniform1f(MapShader.Layer0, MapLayer0);
  glUniform1f(MapShader.Layer1, MapLayer1);
  glUniform1f(MapShader.Layer2, MapLayer2);
  glUniform1f(MapShader.HeightMap, HeigthMap);
  glUniform1f(MapShader.alpha, AlphaMap);
  glUniform2f(MapShader.leafmin, 0,0);

Zunächst einmal muss der Shader bereits aktiv sein, weil sonst nicht klar ist auf welchen Shader sich die glUniform*-Aufrufe beziehen. Also ein glUseProgram(SelShader) einbauen.

Des weiteren handelt es sich bei den Samplern NICHT um die OpenGL-ID der Texturen, sondern um die Nummer der Texturunit auf der die Textur gebunden ist. Also 0 für die erste Texturnunit, 1 für die zweite usw....siehe glActiveTexture.

Autor:  Dropye [ So Aug 29, 2010 15:48 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

das kapier ich nicht oO also das mit den textureinheiten

aber ich hab den opengl fehler wegbekommen indem ich nu schreibe

statt glUniform1f gluniform1i

und anstatt die textureid von opengl anzugeben soll ich also eine zahl angeben, einfach hochzählen in der reihenfolge wie ich sie auch eingelesen habe?

Autor:  Coolcat [ So Aug 29, 2010 16:18 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

Einfach so:
Code:
HeightMap := glGetUniformLocation(SelShader, 'heightmap');
  Layer0 := glGetUniformLocation(SelShader, 'layer0');   // Layer kleingeschrieben!!!
  Layer1 := glGetUniformLocation(SelShader, 'layer1');   // Layer kleingeschrieben!!!
  Layer2 := glGetUniformLocation(SelShader, 'layer2');   // Layer kleingeschrieben!!!
  alpha := glGetUniformLocation(SelShader, 'alpha');
  leafmin := glGetUniformLocation(SelShader, 'leafmin');

glUseProgram(SelShader);
glUniform1i(MapShader.Layer0, 0);
glUniform1i(MapShader.Layer1, 1);
glUniform1i(MapShader.Layer2, 2);
glUniform1i(MapShader.HeightMap, 3);
glUniform1i(MapShader.alpha, 4);
glUniform2i(MapShader.leafmin, 0,0);

glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, MapLayer0);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, MapLayer1);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, MapLayer2);
glActiveTexture(GL_TEXTURE0 + 3);
glBindTexture(GL_TEXTURE_2D, HeigthMap);
glActiveTexture(GL_TEXTURE0 + 4);
glBindTexture(GL_TEXTURE_2D, AlphaMap);

Autor:  Dropye [ So Aug 29, 2010 16:39 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

ach ja da wir ja im c artigen code waren kommts ja auf groß und kleinschreibung an :D an sowas denkt man nicht gleich wenn man lange mit delphi arbeitet

ok zu dem code wenn ich das richtig sehe sage ich also dem programm das er eine Bestimmte Textureinheit verwenden soll und binden dann die textur an diese einheit

ok das hab ich so, verändert hat sich allerdings nichts

Autor:  Coolcat [ So Aug 29, 2010 17:27 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

Zitat:
ok das hab ich so, verändert hat sich allerdings nichts

Also ohne mehr Infos kann ich dir nicht helfen. Was ist den jetzt der aktuelle Zustand?

Tipp:
Lass den Shader erstmal einfach nur eine Farbe ausgeben die sich vom Hintergrund (und allem anderen) unterscheidet. Dann weißt du ob zumindest der Vertexshader richtig arbeitet.

Autor:  Dropye [ So Aug 29, 2010 18:54 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

ok also ich habe den shader nun so eingekürzt das er die vielen dreiecke die ich zeichne alle in einer vorgegebenen Farbe einfärbt, das sieht nun so aus und funktioniert einwandfrei

Code:
//fragment shader
Uniform vec4 Farbe;
void main()
{
    gl_FragColor = Farbe;
}

//vertexshader
void main()
{
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
   gl_FrontColor = gl_Color;
}




den stand des terrain shaders hab ich dir mal hier reingestellt damit ich hier nicht riesig lang im forum posten muss

http://nopaste.info/09f38d5bba.html

ich habe den code so sortiert das alles in der reihenfolge steht wie es auch passiert, ich kann beim besten willen kein fehler mehr finden

Autor:  Coolcat [ So Aug 29, 2010 19:03 ]
Betreff des Beitrags:  Re: Terrain Shader GPU4

Du schreibst die Vertexdaten in XZ....der Shader erwartet aber XY:
Code:
glVertex3f(x,0,y);

Seite 1 von 2 Alle Zeiten sind UTC + 1 Stunde
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/