Direct3D9 - Texturfilter?



  • Ich such jetzt schon seit mehreren Tagen den Fehler und verlier langsam den Verstand... 😞

    Erstmal ein Screenshot vorneweg: http://bloody-blades.de/images/lmstage1buglmcoords.jpg

    Wie man hinten sieht, stimmen die Lightmaps nicht. Ich habe schon sehr viel ausprobiert und die Texturkoordinaten müssen (eigentlich) stimmen, davon geh ich jetzt aus.

    Nun kam ich auf die Idee, dass es mit dem Texturfilter zu tun haben könnte. Ich hatte schonmal einen Bug, als ich Texturen ohne Filter geladen habe, dass dann sowas rauskam: http://bloody-blades.de/images/filterbug.jpg
    Seitdem lade ich mit D3DX_FILTER_BOX und das Problem besteht nicht mehr.

    Bloß da ich die Lightmaps generieren muss und nicht laden kann, kann ich auch keinen Filter angeben. Da ist mir die Funktion D3DXFilterTexture() aufgefallen...

    Mein Code zum Generieren von Lightmaps sieht momentan so aus:

    for (int i = 0; i < this->numLightmaps; i++) {
    		// Create texture
    		if (FAILED(D3DXCreateTexture(Direct3D::Instance().GetDevice(), 128, 128, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &this->lightmaps[i])))
    			return false;
    
    		// Lock it
    		if ((this->lightmaps[i]->LockRect(0, &lockedTexture, NULL, D3DLOCK_DISCARD)) == D3DERR_INVALIDCALL)
    			return false;
    
     		// Write data
     		BYTE* textureData = reinterpret_cast<BYTE*>(lockedTexture.pBits);
    
     		for (int y = 0; y < 128; y++) {
     			for (int x = 0; x < 128; x++) {
    
    				// [...] Textur mit Daten füllen
    			}
     		}
    
    		// Unlock it
    		this->lightmaps[i]->UnlockRect(0);
    
    		// Filter texture
    		if (FAILED(D3DXFilterTexture(this->lightmaps[i], NULL, 0, D3DX_FILTER_BOX)))
    			return false;
    

    Vielleicht sind die Samplerstates noch relevant:

    // Trilinear filtering
    	Direct3D::Instance().SetSamplerState(0, D3DSAMP_MINFILTER, (DWORD)D3DTEXF_LINEAR);
    	Direct3D::Instance().SetSamplerState(0, D3DSAMP_MAGFILTER, (DWORD)D3DTEXF_LINEAR);
    	Direct3D::Instance().SetSamplerState(0, D3DSAMP_MIPFILTER, (DWORD)D3DTEXF_LINEAR);
    
    	Direct3D::Instance().SetSamplerState(1, D3DSAMP_MINFILTER, (DWORD)D3DTEXF_LINEAR);
    	Direct3D::Instance().SetSamplerState(1, D3DSAMP_MAGFILTER, (DWORD)D3DTEXF_LINEAR);
    	Direct3D::Instance().SetSamplerState(1, D3DSAMP_MIPFILTER, (DWORD)D3DTEXF_LINEAR);
    

    Mir gehen langsam halt einfach die Ideen aus, woran es liegen kann und deswegen wollt ich mal fragen, ob's was damit zu tun haben kann?

    Mir ist auch aufgefallen, dass das Problem nur bei Lightmaps auftritt, die in der ersten Stage liegen. (Stage?). Also alle anderen Lightmaps werden wunderbar gerendert. Irgendwie is das alles seltsam 😕

    Vielleicht hat ja jemand ne Idee ????

    Vielen Dank,
    Tim



  • mipmaps vergessen?



  • Die generiert er doch.

    Aber kann es sein, dass diese Texturen ungewöhnliche Formate haben?
    Dann wäre es möglich, dass D3DX sie anpasst ...

    Ansonsten vielleicht falsche Texturkoordinaten?



  • TomasRiker schrieb:

    Ansonsten vielleicht falsche Texturkoordinaten?

    Dass er Texturkoordinaten anstelle von Lightmap nimmt, kann ich ausschließen. Dann würds nochmal viel schlimmer aussehen 😛 (getestet!)
    Und die Daten müssen eigentlich korrekt sein, ich les sie einfach aus und änder sie nirgends.

    Edit: Vorallem ist es Fakt, dass das Problem nur bei Lightmaps auftritt, die die erste Stage sind. D.h. ja, dass es eigentlich irgendwas mit meinen Renderstates etc. zu tun haben muss...

    TomasRiker schrieb:

    Aber kann es sein, dass diese Texturen ungewöhnliche Formate haben?
    Dann wäre es möglich, dass D3DX sie anpasst ...

    Wie meinst du das? Die Daten liegen in einem [128][128][3] Byte Array vor (RGB).
    Hier der komplette Code:

    bool Q3Map::GenerateLightmaps(BSP3FileLightmap *fileLightmaps) {
    
    	if (fileLightmaps == NULL)
    		return false;
    
    	this->lightmaps = new PDIRECT3DTEXTURE9[this->numLightmaps];
    
    	/*
    	** Create lightmaps in Direct3D
    	*/
    	D3DLOCKED_RECT lockedTexture;
    	float r,g,b;
    	float gamma = 2.5;
    
    	for (int i = 0; i < this->numLightmaps; i++) {
    		// Create texture
    		if (FAILED(D3DXCreateTexture(Direct3D::Instance().GetDevice(), 128, 128, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &this->lightmaps[i])))
    			return false;
    
    		// Lock it
    		if ((this->lightmaps[i]->LockRect(0, &lockedTexture, NULL, D3DLOCK_DISCARD)) == D3DERR_INVALIDCALL)
    			return false;
    
     		// Write data
     		BYTE* textureData = reinterpret_cast<BYTE*>(lockedTexture.pBits);
    
     		for (int y = 0; y < 128; y++) {
     			for (int x = 0; x < 128; x++) {
    
    				r = fileLightmaps[i].lightmap[y][x][0];
    				g = fileLightmaps[i].lightmap[y][x][1];
    				b = fileLightmaps[i].lightmap[y][x][2];
    
    				r*=gamma/255.0f;
    				g*=gamma/255.0f;
    				b*=gamma/255.0f;
    
    				//find the value to scale back up
    				float scale=1.0f;
    				float temp;
    				if(r > 1.0f && (temp = (1.0f/r)) < scale) scale=temp;
    				if(g > 1.0f && (temp = (1.0f/g)) < scale) scale=temp;
    				if(b > 1.0f && (temp = (1.0f/b)) < scale) scale=temp;
    
    				// scale up color values
    				scale*=255.0f;		
    				r*=scale;
    				g*=scale;
    				b*=scale;
    
    				textureData[(y * lockedTexture.Pitch) + (x * 4) + 0] = (BYTE)b;
      				textureData[(y * lockedTexture.Pitch) + (x * 4) + 1] = (BYTE)g;
      				textureData[(y * lockedTexture.Pitch) + (x * 4) + 2] = (BYTE)r;
      				textureData[(y * lockedTexture.Pitch) + (x * 4) + 3] = (BYTE)0; 
    			}
     		}
    
    		// Unlock it
    		this->lightmaps[i]->UnlockRect(0);
    
    		// Filter texture
    		if (FAILED(D3DXFilterTexture(this->lightmaps[i], NULL, 0, D3DX_FILTER_BOX)))
    			return false;
    
     		// Save lightmap to file
     		//char file[20];
      	//	sprintf_s(file, "blub%d.jpg", i);
      	//	D3DXSaveTextureToFile(file, D3DXIFF_JPG, this->lightmaps[i], NULL);
    
    	}
    
    	/*
    	** Generate white texture
    	*/
    	// Create texture
    	if (FAILED(D3DXCreateTexture(Direct3D::Instance().GetDevice(), 1, 1, 1, D3DUSAGE_DYNAMIC, D3DFMT_R8G8B8, D3DPOOL_DEFAULT, &this->whiteTexture)))
    		return false;
    
    	// Lock it
    	if ((this->whiteTexture->LockRect(0, &lockedTexture, NULL, D3DLOCK_DISCARD)) == D3DERR_INVALIDCALL)
    		return false;
    
    	// Write data
    	BYTE* textureData = reinterpret_cast<BYTE*>(lockedTexture.pBits);
    
    	textureData[0] = 255;
    	textureData[1] = 255;
    	textureData[2] = 255;
    	textureData[3] = 255;
    
    	// Unlock it
    	this->whiteTexture->UnlockRect(0);
    
    	// Filter texture
    	D3DXFilterTexture(this->whiteTexture, NULL, 0, D3DX_FILTER_BOX);
    
    	return true;
    }
    


  • Wie sieht denn dein Vertexformat aus?
    Und welche Texture-Stage-States setzt du? Insbesondere D3DTSS_TEXCOORDINDEX.



  • Mein Vertex Format schaut so aus:

    class VBufferVertex {
    public:
    	Vector3f position;
    	Vector3f normal;
    	Vector2f textureCoords;
    	Vector2f lightmapCoords;
    };
    
    DWORD FVF = ( D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX2 );
    

    Hier noch ein Auszug aus meiner SetStageRenderStates() Methode, die vor jeder Stage aufgerufen wird:

    // Textures	
    	if (stage->textureType == TEXTYPE_MAP) {
    		Direct3D::Instance().SetTextureState(0, D3DTSS_TEXCOORDINDEX , (DWORD)0);
    		Direct3D::Instance().SetTexture(0, stage->textures[0]);
    
    	} else if (stage->textureType == TEXTYPE_LIGHTMAP || stage->textureType == TEXTYPE_WHITEIMAGE) {
    		Direct3D::Instance().SetTextureState(0, D3DTSS_TEXCOORDINDEX , (DWORD)1);
    		Direct3D::Instance().SetTexture(0, stage->textures[0]);
    
    	} else if (stage->textureType == TEXTYPE_ANIMMAP) {
    		Direct3D::Instance().SetTextureState(0, D3DTSS_TEXCOORDINDEX , (DWORD)0);
    		int texureIndex = (int)((BSP3Face::GetGlobalFaceTimer().GetElapsedSeconds() * stage->animFrequency)) % stage->numTextures;
    		Direct3D::Instance().SetTexture(0, stage->textures[texureIndex]);
    	}
    	else {
    		return false;
    	}
    

    (stage->textureType ist auf jeden Fall richtig gesetzt)



  • Direct3D::Instance().SetTextureState(0, D3DTSS_TEXCOORDINDEX , (DWORD)1);
    

    meinst du IDirect3DDevice9::SetTextureStageState ?



  • hellihjb schrieb:

    Direct3D::Instance().SetTextureState(0, D3DTSS_TEXCOORDINDEX , (DWORD)1);
    

    meinst du IDirect3DDevice9::SetTextureStageState ?

    Jap is genau das selbe; nur wird vorher geschaut, ob der selbe Wert für den State schon gesetzt wurde und ggf. verworfen. Hier aber liegt der Fehler sicher nicht.



  • Könnte es nicht doch evtl. sein, dass irgendwo ein State gesetzt wird, ohne dass deine Kapselung es mitbekommt? Dann würde sie später denken, es habe sich nichts geändert und deine State-Changes verwerfen.



  • TomasRiker schrieb:

    Könnte es nicht doch evtl. sein, dass irgendwo ein State gesetzt wird, ohne dass deine Kapselung es mitbekommt? Dann würde sie später denken, es habe sich nichts geändert und deine State-Changes verwerfen.

    Ich habe mir den gesamten Code nochmal angeschaut und nichts gefunden. Und ansonsten wäre deine Kapselung in deinem Buch genauso fehlerhaft 😛



  • Hab den Fehler gefunden... man bin ich doof...

    Es lag an 'einer falschen Lightmaptextur, da ich den Shader eines Faces nicht kopiert hab. Beim Laden der Shadertexturen und Lightmaps wurde dann die Lightmap im globalen Shaderarray überschrieben. Ergo hat sie dann nur für das letzte Face gestimmt.

    Naja jetzt gehts 🙂

    Vorher

    nachher


Anmelden zum Antworten