Variablen in HLSL



  • TGGC schrieb:

    Die Pflanzen wurden nie langsam gezeichnet - es wurde erwartet, das sie unrealistisch schnell gezeichnet werden. Geht ja jetzt schon wieder los, "kann ich nicht einfach irgendein Flag setzen?!". Ja klar, ATI und nVidia haben da doch dieses "SCHNELL_RENDERN_FUER_ISHILDUR" Flag, das man nur auf true setzen muss. Bevor ich dann jemanden Tips gebe, moechte ich erstmal mitteilen, er hat falsche Erwartungen.

    Wenn das schneller sein soll (warum ueberhaupt, 80fps ist doch ok), hilft nur prinzipiell weniger rendern und zwar weniger Pixel (das es nicht an Vertices on/offscreen liegt wurde ja genug breitgewalzt, keine Ahnung warum das immer noch in Frage steht). Und dann muss man halt sich der moeglichen Einschraenkungen klar werden, die sich daraus ergeben muessen:
    - weniger Aufloesung (aka "SCHNELL_RENDERN_FUER_ISHILDUR" Flag)
    - weniger Pixel pro Tri
    - weniger Tris
    - Pixel, die nicht gezeichnet werden (und daher auch nirgendswo mehr durchscheinen koennen)

    Entweder gibts also gezeichnete Pixel, die am Ende unsichtbar sind oder die Optik auf dem Screen muss sich aendern. f'`8k

    Wunderbar, dann sind wir ja sowieso die ganze Zeit schon einer Meinung 😉
    War nur nicht ganz so einfach das aus deinen Postings rauszulesen...


  • Mod

    wenn du schon tage dran sitzt, hast du sicherlich schonmal einen gpu profiler laufen lassen, was genau ist das bottleneck laut profiler?

    ohne dieses wissen waere jegliche optimierung ein schuss ins blaue und per try&error zu optimieren koennte dich tage ohne fortschritt kosten... emm.

    :schland:



  • @dot
    Nein der Pixelshader ist nicht sehr komplex (habe auch mal die Beleuchtung abgeschaltet, aber das hat lediglich vielleicht 5fps ausgemacht).

    Das hier ist der Code für die Bestimmung der Positionen der Planzen:

    // check if we are almost at the bottom
     if(this->vcCnt.Y < 3000.0f){
      // declare and init local scope parameters
      float32 aPrm[4] = {this->hmSef->GetMapSize(),this->hmSef->GetMapSize()/2.0f};
    
      // lock the instance buffer
      uint32               sIns = this->cFlo*sizeof(FloraInstanceVertex);
      FloraInstanceVertex *pIns = 0x00;
      this->vbIns->Lock(0,sIns,reinterpret_cast<void**>(&pIns),D3DLOCK_DISCARD);
    
      // start a loop for walking each row
      for(uint32 i=0;i<96;++i){
       // start a loop for walking each column
       for(uint32 k=0;k<96;++k){
        // the plants have to be aligned within a fixed grid to give the
        // player the illusion that they do not move together with the camera
        float32 x = 20.0f*floorf((this->vcCnt.X-960.0f+20.0f*k)/20.0f);
        float32 z = 20.0f*floorf((this->vcCnt.Z-960.0f+20.0f*i)/20.0f);
    
        // add some spatial distortions (use the x and z coordinates within the cartesion space
        // as seed (this way the plants will always have the same distortions even if the camera moves)
        srand(static_cast<int32>(x*SEAFLOOR_SIZE+100*z));
        x += -20.0f+10.0f*(rand()/static_cast<float32>(RAND_MAX));
        z += -20.0f+10.0f*(rand()/static_cast<float32>(RAND_MAX));
    
        // finally setup the current instance
        pIns[i*96+k].Position = Vector3(x,this->hmSef->GetHeight(x,z),z);
        pIns[i*96+k].Texture  = Vector2(0.33f*floorf(3.0f*(rand()/static_cast<float32>(RAND_MAX))),0.0f);
        pIns[i*96+k].Normal   = this->hmSef->GetNormal(x,z);
       }
      }
    
      // unlock the instance buffer
      this->vbIns->Unlock();
    

    Vielleicht hast du eine Idee, wie man dies sortieren könnte?
    Ich habe lange versucht, mit dem Front und Right Vektor der aktiven Kamera zu arbeiten, aber dabei entstand ein Aliasing durch die Eingliederung der Pflanzen in das fixe räumliche Raster.

    @TGGC
    Ich hatte vor einigen Posts auf freundliche Weise versucht, dir mitzuteilen, dass ich wenig übrig habe für deine selbstinszenierenden Posts die an Überheblichkeit wohl kaum mehr zu überbieten sind, daher sage ich es nun etwas deutlicher: Du hörst dich für mich an wie ein unangenehmes Rauschen in meiner Kommunikationsleitung mit Dot...



  • @rapso
    Naja, Tage sitze ich noch nicht drann, es handelt sich eher um Stunden, aber dein Vorschlag hört sich absolut vernünftig an. Kannst du mir einen GPU Profiler nennen, mit dem du gute Erfahrungen gemacht hast? Dann mache ich mich gleich an die Arbeit! 🙂



  • Für dich wäre dann wohl der da interessant: http://developer.amd.com/gpu/perfstudio/Pages/default.aspx

    Wenn du deinen Shader mal nur auf die Texturierung und sonst nichts beschränkst, wieviel Geschwindigkeit lässt sich dadurch gewinnen?



  • @Dot
    Hmmm auf der Website steht Direct3D10, 10.1, 11 oder OpenGl3.0?? Wir arbeiten mit Direct3D9...

    Das andere probiere ich gleich aus mom...



  • Naja, vielleicht 10fps, höchstens....
    Texture Lookups hat er offenbar gar nicht gerne, der Rest scheint ihm ziemlich egal zu sein, habe sogar noch per Pixel lighting auf den Pflanzen.

    // ##################################### define all needed functions #####################################
    // ******************************************* function "main" *******************************************
    void main(out Output Out,in float2 Tex:TEXCOORD0,in float3 Normal:TEXCOORD1,in float3 Lgt:TEXCOORD2,in float Fog:TEXCOORD3,in float Blend:TEXCOORD4){
     // simply compute the taking the fog into account
     float4 cOut = tex2D(FloraSampler,Tex);
    
     float3 cClr = clamp(dot(Lgt,Normal),0.2f,1.0f)*0.4f*cOut.rgb;
     float  cBld = lerp(cOut.a,0.0f,saturate(Blend));
     Out.Color   = lerp(float4(cClr,cBld),FogColor,saturate(Fog));
    }
    // *******************************************************************************************************
    // #######################################################################################################
    

    Ist ein riesen Hack ich weiss, ich schreibs dann schön, wenns funktioniert :p



  • Oh, sry, ich ging davon aus dass es (wie sein NVIDIA Äquivalent) auch D3D9 unterstützt...

    Was die Sortierung anbelangt, nimm doch einfach den Abstand zur Kamera?



  • Funktioniert das Nvidia Teil auch (zuverlässig) mit ATI Karten? Habe eben ein ATI Teil drinnen...



  • @Dot

    Was die Sortierung anbelangt, nimm doch einfach den Abstand zur Kamera?

    Ja weisst du die Koordinaten der Pflanzen sind eben nirgends gespeichert, die werden in jedem Frame (abhängig von der aktiven Kameraposition) berechnet (in einem 96x96 Quadrad mit der Kameraposition als Zentrum). Eigentlich bewegen sich die Pflanzen mit der Kamera mit (aber weil diese in einem fixen Raster angeordnet sind, bemerkt man es nicht).

    Irgendwie kann ich mir grad nicht vorstellen, wie man das sortieren kann, aber vermutlich sehe ich einfach den Wald vor lauter Bäume nicht 🙂



  • Ishildur schrieb:

    Funktioniert das Nvidia Teil auch (zuverlässig) mit ATI Karten? Habe eben ein ATI Teil drinnen...

    Deswegen hab ich ja das ATI Ding gepostet 😉
    Probieren kannst dus aber ja aber mal: http://developer.nvidia.com/object/nvperfhud_home.html



  • Hat leider nix funktioniert... 😞



  • Ishildur schrieb:

    @TGGC
    Ich hatte vor einigen Posts auf freundliche Weise versucht, dir mitzuteilen, dass ich wenig übrig habe für deine selbstinszenierenden Posts die an Überheblichkeit wohl kaum mehr zu überbieten sind, daher sage ich es nun etwas deutlicher: Du hörst dich für mich an wie ein unangenehmes Rauschen in meiner Kommunikationsleitung mit Dot...

    Jo, bloed wenn man auf eine Wahrheit hingewisen wird, die einem nicht gefaellt. Dann noch viel Spass beim flags setzen. f'`8k

    Gruß, TGGC (der kostenlose DMC Download)



  • schon wieder dieses Rauschen in der Leitung...



  • @Dot
    Vielleicht lässt sich dies ausbauen:

    Ich habe diesen Code:

    pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,12,0,6);
    

    Zu diesem erweitert

    // render into the zbuffer
     pDev->SetRenderState(D3DRS_ZFUNC,D3DCMP_LESS);
     pDev->SetRenderState(D3DRS_COLORWRITEENABLE,0x00);
     pDev->SetPixelShader(this->psDsc->GetShader());
     pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,12,0,6);
    
     // render into the color buffer
     pDev->SetRenderState(D3DRS_COLORWRITEENABLE,0x0f);
     pDev->SetRenderState(D3DRS_ZWRITEENABLE,false);
     pDev->SetPixelShader(this->psFlo->GetShader());
     pDev->SetRenderState(D3DRS_ZFUNC,D3DCMP_LESSEQUAL);
     pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,12,0,6);
    

    Resultat, die Framerate hat sich verdoppelt. Allerdings scheint das Z-Buffering zu ungenau zu sein, er zeichnet die Planzen nicht mehr korrekt (es hat Artefakte, die vermutlich durch ein Z-Fighting des zweiten Renderpasses mit dem ersten entsteht).

    Was ich bräuchte wär eine Toleranz Zone, also nicht einfach D3DCMP_LESSEQUAL, sondern so ala: "Wenn der aktuelle Z-Wert kleiner als ist als der existierende + 2.0f, dann gilt der Test als bestanden".

    Ich habe leider kein entsprechendes RenderState in Direct3D gefunden, gibt es vielleicht eine Möglichkeit, dies zu umgehen? Habe mir auch überlegt, nach dem ersten Renderpass sämtliche Werte im ZBufer manuell mit 2.0f zu subtrahieren, aber das wäre dann vermutlich wieder zu langsam....


  • Mod

    Ishildur schrieb:

    @rapso
    Naja, Tage sitze ich noch nicht drann, es handelt sich eher um Stunden, aber dein Vorschlag hört sich absolut vernünftig an. Kannst du mir einen GPU Profiler nennen, mit dem du gute Erfahrungen gemacht hast? Dann mache ich mich gleich an die Arbeit! 🙂

    nimm was du hast
    http://blogs.msdn.com/b/manders/archive/2006/12/15/a-painless-introduction-to-pix-for-windows.aspx

    btw. wir haben hier eine grossartige editierfunktion, man muss nicht zwingend mehrmals posten 😉

    :schland:

    (edit: tolleranz zone heisst Bias bei d3d)



  • @rapso u. Dot

    Mit DepthBiasing funktioniert es nun, allerdings ist die Framerate wieder dort wo sie vor dieser Modifikation war. Ich hab hier mal das Ganze Zeugs:

    // disable mipmap filtering and backface culling
      pDev->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_NONE);
      pDev->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
    
      // enable alpha testing
      pDev->SetRenderState(D3DRS_ALPHATESTENABLE,true);
      pDev->SetRenderState(D3DRS_ALPHAFUNC,D3DCMP_GREATER);
      pDev->SetRenderState(D3DRS_ALPHAREF,0xf0);
    
      // render into the zbuffer
      pDev->SetRenderState(D3DRS_COLORWRITEENABLE,0x00);
      pDev->SetPixelShader(this->psDsc->GetShader());
      pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,12,0,6);
    
      // render into the color buffer
      pDev->SetRenderState(D3DRS_COLORWRITEENABLE,0x0f);
      pDev->SetRenderState(D3DRS_DEPTHBIAS,1);
      pDev->SetRenderState(D3DRS_ZWRITEENABLE,false);
      pDev->SetPixelShader(this->psFlo->GetShader());
      pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,12,0,6);
    
      // finally restore all render states  
      pDev->SetRenderState(D3DRS_ALPHAREF,0x00);
      pDev->SetRenderState(D3DRS_ALPHATESTENABLE,false);
      pDev->SetRenderState(D3DRS_ZWRITEENABLE,true);
      pDev->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
      pDev->SetRenderState(D3DRS_DEPTHBIAS,0);
    
      // restore the previous stream frequency settings
      pDev->SetStreamSource(1,0x00,0,0);
      pDev->SetStreamSourceFreq(0,1);
      pDev->SetStreamSourceFreq(1,1);
    

    psDsc (Pixelshader Discard) ist folgendermassen definiert:

    sampler2D FloraSampler: register(s0); // the flora sampler
    
    float4 main(float2 Tex:TEXCOORD0):COLOR0{
     return tex2D(FloraSampler,Tex);
    }
    

    Könnte man da noch was vereinfachen oder ist dies so OK? Mir fällt auf, dass wenn ich AlphaTesting generell abschalte, läuft es mit 3 facher Geschwindigkeit, was mich nun ein wenig irritiert, weil mit dieser Technik sollten die Anzahl der Write Operations in den Framebuffer ja mit sowie ohne Alphatesting identisch sein?



  • Ishildur schrieb:

    Ja weisst du die Koordinaten der Pflanzen sind eben nirgends gespeichert, die werden in jedem Frame (abhängig von der aktiven Kameraposition) berechnet (in einem 96x96 Quadrad mit der Kameraposition als Zentrum). Eigentlich bewegen sich die Pflanzen mit der Kamera mit (aber weil diese in einem fixen Raster angeordnet sind, bemerkt man es nicht).

    Ok, dann brauchst du im Idealfall ja gar nichts cullen und sortieren sondern kannst direkt die Positionen von vorne nach hinten (oder umgekehrt) generieren. Wie genau muss man sich überlegen. Mein erster Gedanke wäre jetzt einfach wie du es scheinbar schon versucht hast auf den Kamerabasisvektoren die Pflanzen generieren und das ganze auf dein Worldspaceraster runden. Wenn es da zu Aliasingeffekten kommt muss man sich was andres einfallen lassen. Man könnte auch versuchen die Pflanzen im Worldspace zu positionieren und z.b. entlang der Dimension in der die z-Achse der Kamera (View Vektor) die betragsmäßig kleinste Komponente hat zuerst laufen (das ist natürlich nicht ganz korrekt aber vielleicht schauts gut genug aus). Ansonsten halt die Positionen einfach mit einem normalen Sortierverfahren anhand ihres Abstands zur Kamera sortieren...

    Ishildur schrieb:

    Könnte man da noch was vereinfachen oder ist dies so OK? Mir fällt auf, dass wenn ich AlphaTesting generell abschalte, läuft es mit 3 facher Geschwindigkeit, was mich nun ein wenig irritiert, weil mit dieser Technik sollten die Anzahl der Write Operations in den Framebuffer ja mit sowie ohne Alphatesting identisch sein?

    Naja, wie schon gesagt drückt Alphatesting ziemlich auf die Fillrate (zusätzlicher Test für jedes Fragment). Würdest du Front to Back rendern könntest du evtl. noch ein bisschen was sparen aber generell ist Alphatesting halt leider nicht ganz gratis. Ich würde jetzt zwei Dinge versuchen: 1) Front to Back mit einem Z-Only Pass mit Alphatesting und drauf dann ein normaler Pass mit Alphablending und 2) Back to Front mit nur einem Pass und ohne Alphatesting. Wär mal interessant was da schneller läuft.



  • @dot

    wie du es scheinbar schon versucht hast auf den Kamerabasisvektoren die Pflanzen generieren und das ganze auf dein Worldspaceraster runden.

    Man kann sich das mit dem Aliasing vermutlich nur schwer vorstellen. Es wirkte sich folgendermasse aus: Solange man die Kamera still hatte bemerkte man nichts ungewöhnliches, doch sobal man die Kamera drehte, fing alles extrem an zu flackern, weil er ständig Planzen an einem Ort zeichnete, dann im nächsten Frame nicht mehr im übernächsten Frame wieder usw. Mann kann sich das so vorstellen:
    Man hat einen sehr niedrig aufgelösten Bildschirm und nun zeichnet man eine rotierende Linie (eben ohne Antialiasing), dann wird praktisch in jedem Frame ein anderer Pixel als Teil der Linie angenommen und völlig äquivalent ist es dann eben mit den Pflanzen passiert (Planze = gefüllter Pixel, World Space Raster = Bildschirm Raster Punkt).

    Ich kriege langsam den Eindruck das Alphatesting langsamer als Alphablending ist? Also ich erinnere mich noch Aussagen, wo empfohlen wurde Alphatesting IMMER zu aktivieren, um die VIEL teureren Alphablending Operationen zu sparen für Pixel, die ohnehin ganz oder fast ganz transparent sind...



  • Ishildur schrieb:

    Ich kriege langsam den Eindruck das Alphatesting langsamer als Alphablending ist? Also ich erinnere mich noch Aussagen, wo empfohlen wurde Alphatesting IMMER zu aktivieren, um die VIEL teureren Alphablending Operationen zu sparen für Pixel, die ohnehin ganz oder fast ganz transparent sind...

    Ja das deckt sich mit meiner Erfahrung (ich sagte ja schon dass Alphatesting ziemlich reinhauen kann). Das Problem ist dass die GPU evtl. Early-Z-Culling und Double-Speed Z-Only Rendering nicht verwenden kann wenn Alphatesting aktiv ist (ich gehe davon aus dass dein PixelShader weder die Tiefe von Pixeln modifiziert noch clip() verwendet, beides wäre der endgültige Todesstoß für diese beiden Optimierungen). Deswegen ja auch mein Rat anfangs es mal nur mit Alphablending zu versuchen. Wie gesagt interessant wäre jetzt noch die Performance von normalem Back-To-Front mit Alphablending...


Anmelden zum Antworten