|
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
gombolo Mini JLI'ler
Anmeldedatum: 25.11.2006 Beiträge: 8
Medaillen: Keine
|
Verfasst am: 19.10.2007, 20:08 Titel: FVF: Vertexstruktur automatisieren |
|
|
-Habt ihr euch schon mal Gedanken gemacht wie man die Wahl der Struktur welche die Vertexinformationen speichert automatisieren kann?
-Braucht man eigentlich noch diese Strukturen wenn man doch Vertexshader hat?
API: DirectX |
|
Nach oben |
|
|
Dr. Best Senior JLI'ler
Alter: 34 Anmeldedatum: 17.06.2004 Beiträge: 269 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 19.10.2007, 22:13 Titel: |
|
|
Gedanken? Ja. Und noch einiges mehr . In meiner Engine habe ich eine Struktur für Vertexformate. Allerdings nicht mit FVF sondern mit DWORD Declarations. Für FVF lohnt es nicht, die sind einfach so simpel, dass man das mit einigen if-statements oder Schleifen schnell geregelt hat. Meine Struktur hat viele verschiedene Konstruktoren, um komfortabel Vertexformate verschiedener Komplexität zu generieren. Außerdem hat sie als Membervariablen ein Feld von DWORDs in die das generierte Vertexformat gespeichert wird und ein paar Membervariablen mit Zusatzinformationen. Hier ist einfach mal der Code dazu. Denn ich kann noch so viel reden, der Code sagt mehr .
CPP: | // This structure saves a vertex shader declaration. It has several constructors for
// commonly used vertex shader declarations.
struct SVSDeclaration{
// The default constructor creates a declaration with position, normal and one
// 2D texture coordinate set, all of them in stream 0
inline SVSDeclaration(){
pDwordDeclaration[0]=D3DVSD_STREAM(0);
pDwordDeclaration[1]=D3DVSD_REG(D3DVSDE_POSITION,D3DVSDT_FLOAT3);
pDwordDeclaration[2]=D3DVSD_REG(D3DVSDE_NORMAL,D3DVSDT_FLOAT3);
pDwordDeclaration[3]=D3DVSD_REG(D3DVSDE_TEXCOORD0,D3DVSDT_FLOAT2);
pDwordDeclaration[4]=D3DVSD_END();
ContainsWeights=false;
SoftwareVP=false;
}
// This constructor creates a declaration with position, possibly a normal and a
// 2D texture coordinate set
SVSDeclaration(bool Normal){
pDwordDeclaration[0]=D3DVSD_STREAM(0);
pDwordDeclaration[1]=D3DVSD_REG(D3DVSDE_POSITION,D3DVSDT_FLOAT3);
pDwordDeclaration[2]=D3DVSD_REG(D3DVSDE_NORMAL,D3DVSDT_FLOAT3);
pDwordDeclaration[2+Normal]=D3DVSD_REG(D3DVSDE_TEXCOORD0,D3DVSDT_FLOAT2);
pDwordDeclaration[3+Normal]=D3DVSD_END();
ContainsWeights=false;
SoftwareVP=false;
}
// This constructor creates a declaration with position, a normal if requested and
// the given multi dimensional texture coordinate sets
SVSDeclaration(bool Normal,WORD nDimensionTex0,WORD nDimensionTex1,WORD nDimensionTex2,WORD nDimensionTex3,WORD nDimensionTex4,WORD nDimensionTex5,WORD nDimensionTex6,WORD nDimensionTex7){
WORD pTexCoordDimension[8]={nDimensionTex0,nDimensionTex1,nDimensionTex2,nDimensionTex3,nDimensionTex4,nDimensionTex5,nDimensionTex6,nDimensionTex7};
pDwordDeclaration[0]=D3DVSD_STREAM(0);
pDwordDeclaration[1]=D3DVSD_REG(D3DVSDE_POSITION,D3DVSDT_FLOAT3);
pDwordDeclaration[2]=D3DVSD_REG(D3DVSDE_NORMAL,D3DVSDT_FLOAT3);
WORD iDestinationRegister=2+Normal;
for(UINT i=0;i<8;i++){
if(pTexCoordDimension[i]){
pDwordDeclaration[iDestinationRegister]=D3DVSD_REG(D3DVSDE_TEXCOORD0+i,pTexCoordDimension[i]-1);
iDestinationRegister++;
}
}
pDwordDeclaration[iDestinationRegister]=D3DVSD_END();
ContainsWeights=false;
SoftwareVP=false;
}
// This constructor creates a declaration with position, a normal if requested and
// the given multi dimensional texture coordinate sets
SVSDeclaration(bool Normal,const WORD* pTexCoordDimension){
pDwordDeclaration[0]=D3DVSD_STREAM(0);
pDwordDeclaration[1]=D3DVSD_REG(D3DVSDE_POSITION,D3DVSDT_FLOAT3);
pDwordDeclaration[2]=D3DVSD_REG(D3DVSDE_NORMAL,D3DVSDT_FLOAT3);
WORD iDestinationRegister=2+Normal;
for(UINT i=0;i<8;i++){
if(pTexCoordDimension[i]){
pDwordDeclaration[iDestinationRegister]=D3DVSD_REG(D3DVSDE_TEXCOORD0+i,pTexCoordDimension[i]-1);
iDestinationRegister++;
}
}
pDwordDeclaration[iDestinationRegister]=D3DVSD_END();
ContainsWeights=false;
SoftwareVP=false;
}
// This constructor creates a declaration with position, the given number of indexed
// weights, a normal if requested and the given multi dimensional texture coordinates
SVSDeclaration(bool Normal,WORD nSkinWeight,bool UseSoftwareVPForWeights,const WORD* pTexCoordDimension){
pDwordDeclaration[0]=D3DVSD_STREAM(0);
pDwordDeclaration[1]=D3DVSD_REG(D3DVSDE_POSITION,D3DVSDT_FLOAT3);
if(nSkinWeight){
pDwordDeclaration[2]=D3DVSD_REG(D3DVSDE_BLENDWEIGHT,nSkinWeight-1);
pDwordDeclaration[3]=D3DVSD_REG(D3DVSDE_BLENDINDICES,D3DVSDT_UBYTE4);
}
pDwordDeclaration[2+(nSkinWeight!=0)*2]=D3DVSD_REG(D3DVSDE_NORMAL,D3DVSDT_FLOAT3);
WORD iDestinationRegister=2+Normal+2*(nSkinWeight!=0);
for(UINT i=0;i<8;i++){
if(pTexCoordDimension[i]){
pDwordDeclaration[iDestinationRegister]=D3DVSD_REG(D3DVSDE_TEXCOORD0+i,pTexCoordDimension[i]-1);
iDestinationRegister++;
}
}
pDwordDeclaration[iDestinationRegister]=D3DVSD_END();
ContainsWeights=nSkinWeight!=0;
SoftwareVP=ContainsWeights && UseSoftwareVPForWeights;
}
// This constructor creates a declaration for a tweening shader with positions and
// normals in stream 0 and 1 and multi dimensional texture coordiantes in the given
// stage
SVSDeclaration(const WORD* pTexCoordDimension,WORD TextureCoordinateStage){
WORD nTextureCoordinate=0;
for(UINT i=0;i<8;i++){
nTextureCoordinate+=pTexCoordDimension[i]!=0;
}
pDwordDeclaration[0]=D3DVSD_STREAM(0);
pDwordDeclaration[1]=D3DVSD_REG(D3DVSDE_POSITION,D3DVSDT_FLOAT3);
pDwordDeclaration[2]=D3DVSD_REG(D3DVSDE_NORMAL,D3DVSDT_FLOAT3);
WORD iDestinationRegister=3;
WORD iTexCoordDestination=0;
if(TextureCoordinateStage==0){
iTexCoordDestination=iDestinationRegister;
iDestinationRegister+=nTextureCoordinate;
}
pDwordDeclaration[iDestinationRegister+0]=D3DVSD_STREAM(1);
pDwordDeclaration[iDestinationRegister+1]=D3DVSD_REG(D3DVSDE_BLENDWEIGHT,D3DVSDT_FLOAT3);
pDwordDeclaration[iDestinationRegister+2]=D3DVSD_REG(D3DVSDE_BLENDINDICES,D3DVSDT_FLOAT3);
iDestinationRegister+=3;
if(TextureCoordinateStage==1){
iTexCoordDestination=iDestinationRegister;
iDestinationRegister+=nTextureCoordinate;
}
if(iTexCoordDestination==0){
pDwordDeclaration[iDestinationRegister]=D3DVSD_STREAM(TextureCoordinateStage);
iDestinationRegister+=1;
iTexCoordDestination=iDestinationRegister;
iDestinationRegister+=nTextureCoordinate;
}
pDwordDeclaration[iDestinationRegister]=D3DVSD_END();
iDestinationRegister=iTexCoordDestination;
for(UINT i=0;i<8;i++){
if(pTexCoordDimension[i]){
pDwordDeclaration[iDestinationRegister]=D3DVSD_REG(D3DVSDE_TEXCOORD0+i,pTexCoordDimension[i]-1);
iDestinationRegister++;
}
}
ContainsWeights=false;
SoftwareVP=false;
}
// This constructor initializes this vertex shader declaration from a complete DWORD
// declaration
SVSDeclaration(const DWORD* pDwDeclaration,bool UseSoftwareVPForWeights){
ContainsWeights=false;
// Search for the end of the declaration, copy it and determine whether it
// contains weights
WORD oDwDeclaration=0;
do{
ContainsWeights=ContainsWeights || pDwDeclaration[oDwDeclaration]==D3DVSD_REG(D3DVSDE_BLENDINDICES,D3DVSDT_UBYTE4);
pDwordDeclaration[oDwDeclaration]=pDwDeclaration[oDwDeclaration];
oDwDeclaration++;
} while(pDwDeclaration[oDwDeclaration-1]!=D3DVSD_END() && oDwDeclaration<32);
if(oDwDeclaration>=32){
Error("Too long DWORD declaration passed to a constructor of SVSDeclaration.");
}
SoftwareVP=ContainsWeights && UseSoftwareVPForWeights;
}
// The comparsion operator returns true if the DWORD declarations are equal until
// the end and the boolean values are the same
bool operator== (const SVSDeclaration& rRHS) const{
WORD oDwDeclaration=0;
bool Equal=true;
do{
if(rRHS.pDwordDeclaration[oDwDeclaration]!=pDwordDeclaration[oDwDeclaration]){
Equal=false;
break;
}
oDwDeclaration++;
} while(rRHS.pDwordDeclaration[oDwDeclaration-1]!=D3DVSD_END() && pDwordDeclaration[oDwDeclaration-1]!=D3DVSD_END() && oDwDeclaration<32);
return ContainsWeights==rRHS.ContainsWeights && SoftwareVP==rRHS.SoftwareVP && Equal;
}
DWORD pDwordDeclaration[32];
bool ContainsWeights;
bool SoftwareVP;
}; |
_________________
Ich bin da, wer noch? |
|
Nach oben |
|
|
Fallen JLI MVP
Alter: 40 Anmeldedatum: 08.03.2003 Beiträge: 2860 Wohnort: Münster Medaillen: 1 (mehr...)
|
Verfasst am: 19.10.2007, 22:15 Titel: |
|
|
FVF sind die alte Variante vertexstrukturen zu beschreiben die neuere sind VertesDeclarations:
Zitat: | A FVF code describes the contents of vertices stored interleaved in a single data stream. It generally specifies data to be processed by the fixed function vertex processing pipeline. This is an older-style vertex declaration; to see the current vertex declaration style, see D3DVERTEXELEMENT9. |
http://msdn2.microsoft.com/en-us/library/bb206335.aspx
Und der vertexshader braucht diese Informationen um zu wissen was ein Positionswert, Texturkoordinate, Farbe, etc. ist.
Habt ihr euch schon mal Gedanken gemacht wie man die Wahl der Struktur welche die Vertexinformationen speichert automatisieren kann?
Ja dies ist sogar recht einfach:
Zuerst erstelle ich mir eine InfoStruktur für das vertexformat, dies sieht ungefähr so aus:
Zu beachten ist hier das die einzelnen Werte bestimmt geordnet sein sollte da es sonst bei bestimmten Rechnerkonfigurationen zu Problemen kommen könnte, näheres dazu kannst du den FVF Spezifikationen entnehmen (Position, Normal, PrimaryColor, SecondaryColor, Texturecoordinates, sollte AFAIk die grundlegende Ordnung sein).
CPP: | // ganz simpel
struct r_VertexInfo
{
r_VertexInfo()
: mi_Size(0)
, mi_PositionOffset(-1)
, mi_NormalOffset(-1)
, mi_ColorOffset(-1)
{
for (int i=0; i<max_texturecoordinates; ++i)
mi_TextureCoordinateOffset[i] = -1;
}
int mi_Size;
int mi_PositionOffset;
int mi_NormalOffset;
int mi_ColorOffset;
int mi_TextureCoordinateOffset[max_texturecoordinates];
}; |
Bei dir im Code kannst du dann die Struktur ganz einfach füllen und die Offsetdaten relativ einfach bei dem auffüllen der Vertexdclarations benutzen:
CPP: | #define OffsetOf(type, element) (size_t)(unsigned long)&(((type *)0)->element)
...
struct r_Vertex
{
float mf_Position[3]; //x,y,z
float mf_Normal[3]; //x,y,z
float mf_Texcoordinate[2]; //u,v
};
...
r_VertexInfo lr_VertexInfo;
lr_VertexInfo.mi_size = sizeof(r_Vertex);
lr_VertexInfo.mi_PositionOffset = OffsetOf(r_Vertex, mf_Position);
lr_VertexInfo.mi_NormalOffset = OffsetOf(r_Vertex, mf_Normal);
lr_VertexInfo.mi_TextureCoordinateOffset[0] = OffsetOf(r_Vertex, mf_Texcoordinate); |
Das auffüllen der VertexDeclaration müsstest du anschliessend noch selbst übernehmen:
http://msdn2.microsoft.com/en-us/library/bb147299.aspx
(Habe dazu grade den Code nicht parat, aber komplex war er nicht.)
Edit: Hier mal fix zusammen gebastelt, vermutlich gehts nicht aber so ungefähr könnte es aussehen:
CPP: | LPDIRECT3DVERTEXDECLARATION9 CreateVertexDeclaration(r_VertexInfo& ar_Info)
{
std::vector<D3DVERTEXELEMENT9> lk_Elements;
if (ar_Info.mi_PositionOffset >= 0)
{
D3DVERTEXELEMENT9 lr_Element = {0, ar_Info.mi_PositionOffset, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0};
lk_Elements.push_back(lr_Element);
}
if (ar_Info.mi_NormalOffset >= 0)
{
D3DVERTEXELEMENT9 lr_Element = {0, ar_Info.mi_NormalOffset, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0};
lk_Elements.push_back(lr_Element);
}
...
lk_Elements.push_back(D3DDECL_END());
D3DVERTEXELEMENT9 lr_Decl_ = new D3DVERTEXELEMENT9[lk_Elements.size()];
for (unsigned int i=0; i<lk_Elements.size(); ++i)
lr_Decl_[i] = lk_Elements[i];
LPDIRECT3DVERTEXDECLARATION9 lr_VertexDeclaration_;
lr_D3DDevice_->CreateVertexDeclaration(lr_Decl_ , lr_VertexDeclaration_);
delete [] lr_Decl_;
return lr_VertexDeclaration_;
} |
_________________ "I have a Core2Quad at 3.2GHz, 4GB of RAM at 1066 and an Nvidia 8800 GTS 512 on Vista64 and this game runs like ass whereas everything else I own runs like melted butter over a smokin' hot 18 year old catholic schoolgirl's arse." |
|
Nach oben |
|
|
gombolo Mini JLI'ler
Anmeldedatum: 25.11.2006 Beiträge: 8
Medaillen: Keine
|
Verfasst am: 20.10.2007, 09:10 Titel: |
|
|
Oh toll. Das muss ich mir jetzt genauer durchlesen. Danke für die Informationen. |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|