Du setzt die Ziel-Textur als Ausgabe-Framebuffer und renderst dann dort hinein als würdest du auf den Bildschirm malen. Im Falle deiner Heightmap könntest du also entsprechend viele "Vierecke" (in Form von je 2 Dreiecken bzw. eines langen Trianglestrips pro Zeile) zeichnen deren Farbwert du dann in deinem Pixelshader ermittelst.
Zu Shadern generell:
Du kannst pro Zeichenaufruf jeweils einen Pixel und Vertexshader aktivieren und brauchst immer beide. Natürlich kannst du in einem der beiden einfach einen 5-Zeiler schreiben, wenn du dort nichts besonders anstellen willst.
Was die Objekte anbelangt: Da gibt's verschiedene Ansätze. Prinzipiell kannst du pro "Objekt" mehr oder minder unendlich viele Shader verwenden, sprich reflektierende Motorhaube und ebenfalls leicht reflektierende Fenster mit Refraction-Effekt etc. pp.., musst es halt nur in einzelnen Aufrufen dann Stück für Stück zeichnen.
Ich persönlich habe es so gelöst, dass ich einen ziemlich langen Vertex und Fragment-Shader habe, die jeweils alles können, sprich von einem direkten Licht bis hin zu 8 lokalen, mit Reflektion oder ohne, mit Schatten oder ohne etc. pp. und habe quasi jeden dieser Effekte in einen #IFDEF-Block gepackt. Wenn ich dann ein Material bei der Ausgabe das aller erste mal nutze, wird anhand der Effekte, die genutzt werden, dessen eine Flag-ID errechnet. Gibt es diesen Shader (diese ID) bereits in meiner Shader-Liste, wird er benutzt, wenn nicht, werden die dafür nötigen #defines am Anfang des Fragment/Vertex-Shader-Quelltextes eingefügt die Shader compiliert und zur Shader-Sammlung hinzugefügt.
Ob das nun das gelbe vom Ei ist, sei mal dahin gestellt, aber so hat man einen eigentlich sehr gut wartbaren Alleskönner-Code der darüber hinaus auch seine sehr gute Performance-Liefert, da bis auf wenige Uniforms, um die man halt nicht ganz herum kommt, fast keine Ifs oder für den Compiler nicht vorhersehbare For-Schleifen mehr vorhanden sind.
LG
Alyx