[DX9, HLSL]

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Droven
Beiträge: 25
Registriert: 05.03.2009, 08:48
Echter Name: David Lorenz
Wohnort: Dresden

[DX9, HLSL]

Beitrag von Droven »

Hi,

es geht um fogendes: ich lasse meine Objekte mit Hilfe eines Effektes rendern. In diesem wird gleich beleuchtet und einfaches Bump-Mapping(wenn vorhanden) angewendet.
Diese sieht so aus:

Code: Alles auswählen

//--------------------------
//--- Globals --------------
//--------------------------

float4x4 matWorldViewProj;
float3x3 matRotation;
float4x4    matWorldIT;
float4      negLightDir;
float4      LightAmb;
float4      LightDif;
float4      MatAmb;
float4      MatDif;
float4      MatSpec;
float4      CamView;
float       power;
bool        bump;
bool        noTextures;

texture tex0;
texture tex1;

sampler DiffuseTex = sampler_state
{
    texture = (tex0);
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

sampler BumpMapTex = sampler_state
{
    texture = (tex1);
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;

};
//--------------------------
//---  Vertex Shader -------
//--------------------------

struct VS_OUTPUT
{
    float4 vPos    : POSITION;
    float2 vTex0   : TEXCOORD0; 
    float3 vNormal : TEXCOORD1;
    float3 vReflect: TEXCOORD2;
   
};

VS_OUTPUT VS(float4 vPosition : POSITION,
             float3 vNormal   : NORMAL,
             float2 vTexCoord : TEXCOORD0)
{
    VS_OUTPUT OUT =(VS_OUTPUT)0; 
    OUT.vPos = mul(vPosition, matWorldViewProj);
    OUT.vNormal = mul(vNormal, matRotation);
    OUT.vTex0 = vTexCoord;
    //gespiegelte lichtrichtung berechnen
    float3 N,L,R,P;
    P = (float3) OUT.vPos;
    N = normalize(OUT.vNormal);
    L = -normalize(negLightDir);
    R = (-L+P+N)-P;
    OUT.vReflect = R;
    return OUT;
}

float4 PS(float2 vTex0 : TEXCOORD0, float3 vNormal : TEXCOORD1, float3 vReflect:TEXCOORD2) : COLOR
{
    //locals
    float3 N;
    float tempDot;
    //Normalisieren von vNormal
    float3 VVerNorm = normalize(vNormal);
    //BumpMap ergreifen
    if(bump == true)
    {
       float4 tn = tex2D(BumpMapTex, vTex0);
       //alle normalen berechnen
       N.x = 2.0f*tn.r -1.0f;
       N.y = 2.0f*tn.g -1.0f;
       N.z = 2.0f*tn.b -1.0f;
    }
    //Punktprodukt und vorher den LichtVector normalisieren
    float3 L = (float3)negLightDir;
    float3 LNorm = normalize(negLightDir);
    //einmal fürs selbstschatten
    float tempShade = dot(VVerNorm, LNorm);
    //und für das bumpMap
    if(bump == true) tempDot = abs(dot(N,LNorm));
    else tempDot = 1.0f;
    //glanzpunkte berechnen
    float3 CamViewNorm;
    float3 CV = (float3)CamView;
    float3 vRefNorm = normalize(vReflect);
    CamViewNorm = normalize(CV);
    float dotSpec = abs(dot(vRefNorm, CamViewNorm));
    float4 spec = MatSpec*pow(dotSpec, power)*tempShade;
    //texturfarbe
    float4 TexCol = tex2D(DiffuseTex, vTex0);
    if( (noTextures == true))
        {
            TexCol.r = 1.0f;
            TexCol.g = 1.0f;
            TexCol.b = 1.0f;
            TexCol.a = 1.0f;
            
        }
    //alle farben zusammensetzen
    return (MatAmb*LightAmb*TexCol)/3.0f+TexCol*MatDif*LightDif*tempDot*tempShade+spec;
}
//---------------------------
//--- Techniken -------------
//---------------------------

technique tec0
{
    pass p0
    {
        //Renderstates
        Lighting    = False;
        CullMode    = CCW;
        //Vertexshader
        VertexShader = compile vs_2_0 VS();
        //Pixelshader
        PixelShader  = compile ps_2_0 PS(); 
    }
}
Fogendes Problem tritt auf: bei einem Objekt mit einer einzigen Textur und einem BumpMap funktiont alles sehr gut. Wenn das Objekt aber mehrere Texturen hat, wird die aller erste auf alle Elemente des Objektes angewendet, die anderen werden nicht angezeigt.

Hier der Code für die Renderroutine:

Code: Alles auswählen

for(DWORD i = 0; i < m_anzahlMats; i++)
{
//....
          if(bumpMap[i])
	  {
			CalcAndCommitBumpMapData(sunlight, materialien[i]);
			if( (anz_Tex > 0) && (i < anz_Tex) )
				{
					if(textures[i])
						bumpMapping.GetEffect()->SetTexture("tex0", textures[i]);
				}
				bumpMapping.GetEffect()->SetTexture("tex1", bumpMap[i]);
				//zeichenvorgang
				bumpMapping.BeginEffect();
				for(DWORD j = 0; j < bumpMapping.GetNumPasses(); j++)
					{
						bumpMapping.BeginPass(j);
						HRESULT hr = mesh->DrawSubset(i);
						bumpMapping.EndPass();
					}
				bumpMapping.EndEffect();
		}//ende if(bumpMap[i])
}


In CalcAndCommitBumpMapData(sunlight, materialien); werden alle nötigen Daten an den Effekt gegeben.
Auch die Materialien scheinen sich nich zu ändern.

Hat jemand eine Lösung?

MfG Droven
Zuletzt geändert von Droven am 03.04.2009, 11:30, insgesamt 2-mal geändert.
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: [DX9, HLSL]

Beitrag von Aramis »

Code: Alles auswählen

if(textures[i])
Sicher dass textures für alle i's auf verschiedene, valide Texturen zeigt? Und dass anz_Tex garantiert richtig gesetzt ist?
Oder du kommst irgendwo außerhalb dieser Codestelle mit deinen Begin()/End()s durcheinander. Dann werden Statechanges u.U. auch nicht comitted.

PS: mit [ code = cpp ] (ohne Leerzeichen natürlich) kannst du syntax highlighting nutzen.
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: [DX9, HLSL]

Beitrag von kimmi »

Die DebugInfo von DirectX kann dir eventuell auch noch einige interessante Infos ueber einen eventuell vorhandenen Fehler liefern. Zieh da einfach mal Google zu Rate, wie man die benutzt. Wenn etwas in den States / woauchimmer in der D3D Pipeline schiefgeht, kommst du dem so am schnellsten auf die Schliche.

Gruss Kimmi
Droven
Beiträge: 25
Registriert: 05.03.2009, 08:48
Echter Name: David Lorenz
Wohnort: Dresden

Re: [DX9, HLSL]

Beitrag von Droven »

Hallo,

Die Debug Info von DirektX ist aktiviert und gibt nur Warnungen über das Ignonieren nicht gebrauchter Render- und Samplerstates aus, was schon immer der Fall bei Debuggen war:

Code: Alles auswählen

Direct3D9: (WARN) :Ignoring redundant SetSamplerState Sampler: 0, State: 13

Direct3D9: (WARN) :Ignoring redundant SetSamplerState Sampler: 0, State: 14

Direct3D9: (WARN) :Ignoring redundant SetSamplerState Sampler: 0, State: 25

Direct3D9: (WARN) :Ignoring redundant SetSamplerState Sampler: 0, State: 15

Direct3D9: (WARN) :Ignoring redundant SetSamplerState Sampler: 0, State: 16

Direct3D9: (WARN) :Ignoring redundant SetSamplerState Sampler: 0, State: 17

Direct3D9: (WARN) :Ignoring redundant SetSamplerState Sampler: 0, State: 18
...usw.


Ich habe den Algorithmus etwas verändert um die ganzen if-abfragen heraus zubekommen, dennoch müsste es aber nach meiner Ansicht nach trotzdem funktionieren.
Der Code:

Code: Alles auswählen

for(DWORD i = 0; i < m_anzahlMats; i++)
{					
	//Bumpmapping wenn vorhanden und unterstützt
	if(g_bDot3Mapping == TRUE)
	{
		//Textur an Effekt übergeben und zuvor Bump mapping berechnungen durchführen
		if(bumpMap[i])
		{
			drawn = TRUE;
			CalcAndCommitBumpMapData(sunlight, materialien[i]);
			if(textures[i])
			{
				bumpMapping.GetEffect()->SetTexture("tex0", textures[i]);
				bumpMapping.GetEffect()->SetBool("noTextures", false);
			}
			else
			{
				bumpMapping.GetEffect()->SetTexture("tex0", NULL);
				bumpMapping.GetEffect()->SetBool("noTextures", true);
			}
			bumpMapping.GetEffect()->SetTexture("tex1", bumpMap[i]);
			//zeichenvorgang
			bumpMapping.BeginEffect();
			for(DWORD j = 0; j < bumpMapping.GetNumPasses(); j++)
			{
				bumpMapping.BeginPass(j);
				HRESULT hr = mesh->DrawSubset(i);
				bumpMapping.EndPass();
			}
			bumpMapping.EndEffect();
	         }//ende if(bumpMap[i])
					
		else
		{	
			drawn = FALSE;
			bumpMapping.GetEffect()->SetTexture("tex1", NULL);
			//Alles an effect übergeben
			CalcAndCommitBumpMapData(sunlight, materialien[i]);
			if(textures[i])
			{
				bumpMapping.GetEffect()->SetTexture("tex0", textures[i]);
				bumpMapping.GetEffect()->SetBool("noTextures", false);
			}
			else
			{
				bumpMapping.GetEffect()->SetTexture("tex0", NULL);
				bumpMapping.GetEffect()->SetBool("noTextures", true);
			}
						
			//Beginne mit Effekt
			bumpMapping.BeginEffect();
			for(DWORD j = 0; j < bumpMapping.GetNumPasses(); j++)
			{
				bumpMapping.BeginPass(j);
				HRESULT hr = mesh->DrawSubset(i);
				bumpMapping.EndPass();
			}
			bumpMapping.EndEffect();
        	}//ende bumpmapping ist zwar vorhanden, es wurde aber keines geladen
	}// ende g_bDot3Mapping == TRUE
	//dann eben ohne bumpmapping
	else
	{
        	drawn = FALSE;
		bumpMapping.GetEffect()->SetTexture("tex1", NULL);
		//alles effect übergeben
		CalcAndCommitBumpMapData(sunlight, materialien[i]);
		//zeichenvorgang
		if(textures[i])
		{
	        	bumpMapping.GetEffect()->SetTexture("tex0", textures[i]);
			bumpMapping.GetEffect()->SetBool("noTextures", false);
		}				
		else
		{
			bumpMapping.GetEffect()->SetTexture("tex0", NULL);
			bumpMapping.GetEffect()->SetBool("noTextures", true);
		}
		//Beginne mit Effekt
		bumpMapping.BeginEffect();
		for(DWORD j = 0; j < bumpMapping.GetNumPasses(); j++)
		{
			bumpMapping.BeginPass(j);
			HRESULT hr = mesh->DrawSubset(i);
			bumpMapping.EndPass();
		}
		bumpMapping.EndEffect();
	}//bumpmapping wird nicht unterstützt
				
}//ende for materials
Sollte vllt. irgendwo noch die CommitChanges-Funktion der Effekt-Schnittstelle herein?
Übrigens: jetzt ist das Problem umgedreht. Jetzt wird keine einzige Textur mehr angezeigt nur das Material.
Mittels debuggen habe ich natürlich geprüft, ob die Texturen valid sind, dies ist der Fall. Ich bin Schritt für Schritt durch gegangen und dort wo eine Textur auf einem Material liegt wird sie auch dementsprechend dem Effekt übergeben.
Ich bin noch immer ratlos.

MfG Droven
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [DX9, HLSL]

Beitrag von Schrompf »

CommitChanges lädt alle geänderten Effekt-Parameter in die Konstantenregister der Grafikkarte. Der Aufruf sollte wohl kurz vor dem Zeichenaufruf stehen, wenn ich das recht verstehe.

Ansonsten: schnapp Dir mal PIX, stell es auf "Single Frame Capture" und klick Dich durch die einzelnen Zeichenaufrufe durch. Da müsstest Du Vertex für Vertex und Pixel für Pixel verfolgen können, welchen Weg die Grafikkarte nimmt. Und Du solltest der Klarheit wegen mal die ganzen Code-Verdopplungen entfernen. Die so tief ineinander geschachtelten ifs beim Setzen der Texturen kann man doch problemlos halb so lang ausdrücken. Und drittens: evtl. wäre es schlauer, anstatt der bools einfach verschiedene Techniques im Effekt zu definieren, die jeweils ohne und mit Bump Mapping arbeiten. Den Fall "keine Farbtextur" kannst Du sowieso knicken - wenn der tatsächlich mal vorkommen sollte, tut's auch eine kleine weiße Dummy-Textur, die Du dann stattdessen anklemmst. Diese semi-dynamischen Verzweigungen im Shader dürften ein Stück Rechenzeit kosten, auch wenn es nicht ganz so viel ist wie bei echten dynamischen Verzweigungen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: [DX9, HLSL]

Beitrag von Zudomon »

Ich kann nur empfehlen das NVidia PerfHUD einzubauen... das ist echt ein super Tool. Man kann genau sehen, wie der Frame gezeichnet wird, welche States aktiviert sind, welche Objekte im Speicher bei dem jeweiligen Draw-Call sind. Auch welche Shader und Texturen in dem Draw-Call involviert sind. Du kannst damit sogar Texturen zur Laufzeit ersetzen!

Damit kommt man vielen Grafikfehlern auf die Schliche, gerade bei solchen Problemen. :D
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: [DX9, HLSL]

Beitrag von eXile »

Zudomon hat geschrieben:Ich kann nur empfehlen das NVidia PerfHUD einzubauen... das ist echt ein super Tool. Man kann genau sehen, wie der Frame gezeichnet wird, welche States aktiviert sind, welche Objekte im Speicher bei dem jeweiligen Draw-Call sind. Auch welche Shader und Texturen in dem Draw-Call involviert sind. Du kannst damit sogar Texturen zur Laufzeit ersetzen!
Nur braucht man dazu die Nvidia-Treiber, d.h. auch eine Nvidia-Karte. Ich weiß nicht, ob der Threadersteller eine eben solche hat ...
Droven
Beiträge: 25
Registriert: 05.03.2009, 08:48
Echter Name: David Lorenz
Wohnort: Dresden

Re: [DX9, HLSL]

Beitrag von Droven »

Habe jetzt verschiedene Techniken definiert und den Fall, dass es keine Texturen gibt entfernt(damit auch die überflüssigen if-Bedingungen).
Gleiches wie vorher, keine Änderung. Das Kuriose ist ja, dass es für Modelle mit einer Textur immer noch ohne Probleme klapt.
Wo bekomme ich dieses PIX her, muss zugeben, habe davon noch nie etwas gehört.

Danke für die Hilfe.

MfG Droven
EDIT: Zum Glück habe ich die.
Ich werde mir das Tool mal zu Gemüte ziehen, danke für den Tipp.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [DX9, HLSL]

Beitrag von Schrompf »

PIX ist Teil des DirectX-SDKs.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Dirk Schulz
Establishment
Beiträge: 130
Registriert: 01.03.2009, 14:21
Alter Benutzername: frittentuete

Re: [DX9, HLSL]

Beitrag von Dirk Schulz »

Hi,

CommitChanges() ist nur notwendig, wenn du Änderungen der Shaderparameter innerhalb von BeginPass() und EndPass() durchführst, ist bei dir nicht der Fall, also ist das in Ordnung.

Was mich etwas verwirrt: Du iterierst i über die Anzahl der Materialien, renderst damit also nur die Subsets des Meshes, die unterschiedliche Materialien haben: mesh->DrawSubset(i). Sollte das nicht eher die Anzahl der Subsets des Meshes sein?

Dirk Schulz
Droven
Beiträge: 25
Registriert: 05.03.2009, 08:48
Echter Name: David Lorenz
Wohnort: Dresden

Re: [DX9, HLSL]

Beitrag von Droven »

Hi, ich habe die Lösung gefunden.

Dirk hat mich auf die Spur gebraucht:
Was mich etwas verwirrt: Du iterierst i über die Anzahl der Materialien, renderst damit also nur die Subsets des Meshes, die unterschiedliche Materialien haben: mesh->DrawSubset(i). Sollte das nicht eher die Anzahl der Subsets des Meshes sein?
Ich benutze das *.obj-file-Format und hatte vergessen die Subsets nach den Materialien zu ordnen, was ich jetzt nachträglich erweitert habe und jetzt funktionierts. Das Problem war also viel tiefer als ich zuerst angenommen hatte. Danke für die Hilfe und noch einen schönen Sonntag

MfG Droven
Antworten