Direct3D - Vertices - Texturalphablending - Farbverlauf?!



  • Hi!
    Ich bastle gerade an einer Spriteklasse für einige 2D - Spiele;
    In diesem Fall ist es eine Klasse für ein Partikelsystem..besser gesagt um zu testen wie Pointlists funktionieren und wie ich das am Besten in mein Spiel einbauen kann!
    Das Problem ist, dass die Texturen ihre Farben wirklich extrem verändern, was wohl an dem liegt:

    device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
        device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
    

    ➡ Resultat ist dass der Punkt ( eine 128 x128 Pixel Textur, die eben wie ein Punkt aussieht) bei blauer HintergrundFarbe einen hellen Blauton annimmt; Aber die Farbe soll ja gleich bleiben und sich nicht verändern!->Dies funktioniert nur bei schwarzen Hintergrund (was wohl daran liegt dass die Backroundcolor der Textur schwarz ist), was aber nicht so toll ist, weil ich das Partikelsystem ja für alle verschiedenen Hintergrundfarben verwenden möchte!

    CPP (Wichtigste Methoden):

    inline DWORD FtoDW( FLOAT f ) { return *((DWORD*)&f); }
    
    void cVSprite::init(LPDIRECT3DDEVICE9 dev, LPCSTR Path, float set_x, float set_y){
    
    x=set_x;
    y=set_y;
    device=dev;
    
    strcpy(FileName,Path);
    
    D3DXIMAGE_INFO ImgInfo;
    D3DXGetImageInfoFromFile(FileName,&ImgInfo);
    size_x=ImgInfo.Width;
    size_y=ImgInfo.Height;
    
    square[0]=set_vertex(x,y,0,		           D3DCOLOR_ARGB(255,0,0,0),0,0);
    square[1]=set_vertex(x+size_x,y,0,		   D3DCOLOR_ARGB(255,0,255,0),0,0);
    square[2]=set_vertex(x+size_x*2,y,0,	   D3DCOLOR_ARGB(255,0,255,0),0,0);
    square[3]=set_vertex(x,y+size_y,0,	       D3DCOLOR_ARGB(255,0,255,0),0,0);
    square[4]=set_vertex(x+size_x,y+size_y,0,  D3DCOLOR_ARGB(255,0,255,0),0,0);
    square[5]=set_vertex(x+size_x*2,y+size_y,0,D3DCOLOR_ARGB(255,255,0,0),0,0);
    
    D3DXCreateTextureFromFile(device,FileName,&lpTexture);
    
    device->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SELECTARG1);
    
    device->SetTexture(0,lpTexture);
    
    device->SetRenderState( D3DRS_POINTSPRITEENABLE, TRUE );
    device->SetRenderState( D3DRS_POINTSCALEENABLE,  TRUE );
    device->SetRenderState( D3DRS_POINTSIZE,     FtoDW(50.00f) );
    
    device->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
    device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
    device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
    
    device->CreateVertexBuffer(sizeof(square),
    						   D3DUSAGE_WRITEONLY,
    						   D3D_CUSTOMVERTEX,
    						   D3DPOOL_MANAGED,
    						   &VB_TRIANGLE,
    						   NULL);
    
    VB_TRIANGLE->Lock(0,0,(void**)&VertexBufferStart,0);
    memcpy(VertexBufferStart,square,sizeof(square));
    VB_TRIANGLE->Unlock();
    device->SetFVF(D3D_CUSTOMVERTEX);
    
    device->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
    
    device->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
    
    }
    void cVSprite::draw(){
    
    device->SetStreamSource(0,VB_TRIANGLE,0,sizeof(CUSTOMVERTEX));
    device->DrawPrimitive(D3DPT_POINTLIST,0,6);
    
    }
    
    CUSTOMVERTEX cVSprite::set_vertex(float set_x,float set_y,float set_z, DWORD set_color,float set_tu,float set_tv){
    
    CUSTOMVERTEX vertex;
    
    vertex.x=set_x;
    vertex.y=set_y;
    vertex.z=set_z;
    vertex.rhw=1;
    vertex.color=set_color;
    vertex.tu=set_tu;
    vertex.tv=set_tv;
    
    return vertex;
    
    }
    

    HEADER (VOLLSTÄNDIG):

    #if !defined(MY_VSPRITE_H)
    #define MY_VSPRITE_H
    
    #include <windows.h>
    #include <d3d9.h>
    #include <d3dx9.h>
    #include <vector>
    #include "global.h"
    #include "Direct3d.h"
    
    using namespace std;
    
    #define D3D_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)
    
    struct CUSTOMVERTEX{
    
    	float x,y,z,rhw;
    	DWORD color;
    	float tu,tv;
    
    };
    
    const int vertices_num=6;
    
    class cVSprite{
    
    	float x,y,size_x,size_y;
    	LPDIRECT3DDEVICE9 device;
    	CUSTOMVERTEX square[vertices_num];
    	LPDIRECT3DVERTEXBUFFER9 VB_TRIANGLE;
    	LPDIRECT3DTEXTURE9 lpTexture;
    	char FileName[1024];
    	BYTE *VertexBufferStart;
    
    public:
    
    		cVSprite(){};
    
    		void init(LPDIRECT3DDEVICE9 dev,LPCSTR Path,float set_x, float set_y);
    
    		void Set_Position(float set_x, float set_y);
    
    		void draw();
    
    		CUSTOMVERTEX set_vertex(float set_x,float set_y,float set_z, DWORD set_color,float set_tu,float set_tv);
    
    		void handle();
    
    		void xrotate();
    
    		void yrotate();
    
    		void rearrangevertices(float add_x,float add_y);
    };
    
    #endif
    

    Die Variablen tu und tv dürften bei einer POINTLIST anscheinend keinen Einfluss auf Direct3D haben aber ich habe sie daweil im Code gelassen.

    Das Alphablending sollte es mir lediglich ermöglichen eine Farbe beim Laden transparent zu machen damit bei der Punkt-Textur nur der Punkt dargestellt wird und nicht auch der schwarze Hintergrund. Ich hab in meinem schlauen Buch was von Alphakanal gelesen; leider hab ich kein Plan wie ich den festlegen kann! Bzw. wie ich diesen verwenden kann.
    Außerdem sollte es dann später möglich sein die Textur transparent darzustellen, bisher habe ich LPD3DXSPRITE, was mir dir ganze Arbeit abgenommen hat, allerdings möchte ich nun auf Vertices umsteigen weil die angeblich schneller sind. bzw. weil es dann nicht mehr so neue Materie ist wenn ich zum ersten Mal 3D Objekte erstellen möchte ... 🙂

    Hoffe ihr könnt mir (bei den verschiedenen Problemen) helfen!

    MfG Kuldren



  • also

    device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
    device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
    
    würde ich zu
    
    device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
    device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );	// oder so ähnlch heißt das
    

    Außerdem: Ein Sprite ist doch ein Rectheckiges Gebilde, wo eine Textur draufgemalt wird. Eine Pointlist ist aber etwas total anderes. die pointlist malt doch nur 6 punkte, trianglelist wäre doch für ein sprite besser geeignet...

    außerdem. Viel vom Initcode gehört eher in die Drawfunktion, also alle SetRenderState, SetTexture, SetTextureStageState usw.
    was is, wenn dein sprite nach etwas anderem gerendert wird, was die states verstellt hat? also-> direkt vorm malen einstellen. Weiterhin würde ich dir nich empfehlen, für jedes sprite einen eigenen vbuffer anzulegen, schlcutk performance, vor allem wenn du dann ganz viele sprites hast und die alle einen eigenen bufer haben. daraus folgen dann ganz viele aufrufe von drawprimitive und das schluckt massig performance.

    Hoffe, konnte dir helfen. Hab aber auch glaub ich dein Problem nicht direkt verstanden 🙂



  • Danke!
    Ich werd die Aufrufe da reinpacken...
    Aber einen Buffer für alle Sprites?`..ist dass dann nicht extrem "unübersichtlich"?

    ->Pointlist...Dieser Code soll für ein Partikelsystem sein..deshalb nur pointlist...aber sollte die Transparenz nicth auch dafür gelten?

    MfG Kuldren



  • Ich hab diese Zeilen nun eingefügt und getestet

    device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
    device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
    

    Ergebnis:
    Die Farben werden nicht mehr mit dem Hintergrund vermischt, allerdings wird die vollständige textur angezeigt..also mit dem schwarzen hintergrund!!
    Was natürlich schlecht ist..
    + wie man die Transparenz regelt weiß ich leider immer noch nicht...

    Die verschiedenen Aufrfe werde ich noch in die Draw Methode einfügen, aber in dem Bsp. wird sowieso nur in init etwas an den Preferences verändert!

    MfG Kuldren



  • Die Farben werden nicht mehr mit dem Hintergrund vermischt, allerdings wird die vollständige textur angezeigt

    vermischt werden die schon, naemlich so:
    vordergrund*alpha + hintergrund*(1-alpha)
    da deine textur aber keinen alpha-kanal hat, wird fuer alle pixel "1" angenommen, also hast du auch keine transparenz.
    in deinem fall waere zb ein alpha-verlauf von undurchsichtig (mitte) bis volltransparent (aussen) sinnvoll.

    Aber einen Buffer für alle Sprites?`..ist dass dann nicht extrem "unübersichtlich"?

    jeder draw-call hat gewissen overhead, was es ziemlich kostenintensiv macht, ein einzelnes polygon zu zeichnen.
    lies die gaengigen papers, dann verfuegst du auch ueber gaengiges wissen 🙂



  • Danke für den Link!

    vordergrund*alpha + hintergrund*(1-alpha)

    Die Formel hab ich auch in meinem Buch stehen, allerdings hab ich keine Ahnung ob die Textur nen Alphakanal hat...

    Kann ich der Textur im Programm einen Alphakanal verpassen oder muss der vorher festgelegt werden?...
    bzw...wie bekomm ich das am Besten hin? (auch der Alphaverlauf)

    MfG Kuldren



  • also, kommt drauf an, was die textur für ein format hat. bmp zB hat von haus aus kein alpha, tga dagegen shcon. wenn du bmp lädst wird alles alpha auf 1 bzw 255 gesetzt. bei tga steht der alpha-wert in der datei drin. Du kannst aber auch eine Farbe der textur ausblenden, indem du beim laden einen sogeneannten color-key angibst. also wenn du mittels d3dxcreatetexturefromfileex lädst. dann haben alle farben in der textur einen alphawert von 1, und nur der angegebenen colorkey einen wert ovn 0.

    btw.: auch partikelsysteme malt man nicht mit pointlists, sondern wie angesprochen mit polygonen. Rechtecke werden mit einer Textur überzogen, mit einer diffusen Farbe noch vermischt und schon hast du einen schönen partikel.
    Als textur bietet sich zB folgende Textur an:

    ein Quadrat, welches innen einen weißen kreis hat, der nach außen hin schwarz wird. mit verlauf natürlich. Jetzt kannst du auch bei deinen renderstates angeben, dass du die diffuse-komponenete deines materials/deiner customvertext-struktur mit der farbe der textur vermischst, mittels settexturestagestate(0, d3dts_colorop, d3dts_modulate) oder so ähnlich. Und den Alphawert für die Textur kannst du auch aus der Farbe dre Textur nehmen, ich weiß jetzt ncih genau den werd für das alphaop-renderstate, musst ma in die doku gucken und rumprobieren.

    +Hoff, konnte helfen 🙂
    maxi



  • bmp zB hat von haus aus kein alpha

    bmp kennt mittlerweile auch alpha - kann zb photoshop seit version 7 schreiben.
    die anwendungen sind sich untereinander allerdings nicht ganz einig, bei welchem format sie nun die transparenz oder einen zusaetzlichen kanal als alpha speichern/laden.



  • Danke für die Infos!

    btw.: auch partikelsysteme malt man nicht mit pointlists, sondern wie angesprochen mit polygonen.

    Ich hab mir das Partikelsystembeispiel in der Doku angesehen und da wird POINTLIST verwendet + funktionieren tuts ja auch...
    Allerdings ist daraus leider nicht ersichtlich wie das mit dem Alphablending funktioniert...

    ein Quadrat, welches innen einen weißen kreis hat, der nach außen hin schwarz wird. mit verlauf natürlich.

    Genau so sieht die Textur aus 🙂
    Ich werd gleich mal mit dem alphakanal rumprobieren...

    MfG Kuldren


Anmelden zum Antworten