Irrationaler CG-Shader

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Eisflamme
Establishment
Beiträge: 412
Registriert: 26.05.2002, 17:42
Wohnort: Köln

Irrationaler CG-Shader

Beitrag von Eisflamme »

Hi,

mein neuster Shader verhält sich irrational. Er widersagt jeder Logik. Ich weiß nicht, ob ich ihn in ein Internat schicken soll oder ob ich ihn irgendwie anderweitig zur Vernunft bringen kann. Hat jemand Ideen für Erziehungsmethoden?

Das Problem; zwei imo identische Codes führen zu unterschiedlichen Ergebnissen:

Code: Alles auswählen

struct inner
{
	float4	position	: POSITION;
	float4	color		: COLOR;
	float3	normal		: NORMAL;
	float4	shadowCoords: TEXCOORD0;
	float2	texCoords	: TEXCOORD1;
	float3	boneWeights	: TEXCOORD2;
	float4  boneIndices	: TEXCOORD3;
};

struct outer
{
	float4	position	: POSITION;
	float4	color		: COLOR;
	float4	shadowCoords: TEXCOORD0;
	float2	texCoords	: TEXCOORD1;
	float3	normal		: TEXCOORD2;
};

outer main(inner IN,
            uniform float4x4	ModelViewProj,
			uniform float4x4	ShadowTextureMatrix,
			uniform bool		activateAnimation,
			uniform float4		BoneMatrices[150]
            )
{
    outer OUT;
	
    float3 objPos;
	
	float4 allWeights = float4(IN.boneWeights, 1.0f - IN.boneWeights.x - IN.boneWeights.y - IN.boneWeights.z);

	if(activateAnimation)
	{
		for(float n = 0; n < 4; ++n)
		{	
			float3x4 matrix = float3x4(	BoneMatrices[IN.boneIndices[n] * 3],
										BoneMatrices[IN.boneIndices[n] * 3 + 1],
										BoneMatrices[IN.boneIndices[n] * 3 + 2]);

			objPos+= mul(matrix, IN.position) * allWeights[n];
		}
	}
	else
		objPos = IN.position.xyz;

	OUT.position    = mul(ModelViewProj, float4(objPos, 1));
	OUT.shadowCoords = mul(ShadowTextureMatrix, IN.position);

	OUT.color		= IN.color;// * dot(float3(1,1,1), IN.normal);//float4(0.4f, 0.4f, 0.4f, 0.f) + float4(dot(float3(sin(counter),cos(counter),sin(counter / 3.f)), IN.normal) * float3(1,1,(1 + sin(counter))/2.0f),1);

	OUT.normal			= IN.normal;//mul(WorldInverseTranspose, float4(IN.normal,1.f)).xyz;
	OUT.texCoords 		= IN.texCoords;

	return OUT;
}
Dieser Code führt dazu, dass OUT.texCoords nicht richtig gefüllt wird. Dementsprechend wird die Textur auf dem Modell nicht richtig dargestellt.

Der folgende Code funktioniert jedoch:

Code: Alles auswählen

struct inner
{
	float4	position	: POSITION;
	float4	color		: COLOR;
	float3	normal		: NORMAL;
	float4	shadowCoords: TEXCOORD0;
	float2	texCoords	: TEXCOORD1;
	float3	boneWeights	: TEXCOORD2;
	float4  boneIndices	: TEXCOORD3;
};

struct outer
{
	float4	position	: POSITION;
	float4	color		: COLOR;
	float4	shadowCoords: TEXCOORD0;
	float2	texCoords	: TEXCOORD1;
	float3	normal		: TEXCOORD2;
};

outer main(inner IN,
            uniform float4x4	ModelViewProj,
			uniform float4x4	ShadowTextureMatrix,
			uniform bool		activateAnimation,
			uniform float4		BoneMatrices[150]
            )
{
    outer OUT;
	
    float3 objPos;
	
	float4 allWeights = float4(IN.boneWeights, 1.0f - IN.boneWeights.x - IN.boneWeights.y - IN.boneWeights.z);

	OUT.shadowCoords = mul(ShadowTextureMatrix, IN.position);

	if(activateAnimation)
	{
		for(float n = 0; n < 4; ++n)
		{	
			float3x4 matrix = float3x4(	BoneMatrices[IN.boneIndices[n] * 3],
										BoneMatrices[IN.boneIndices[n] * 3 + 1],
										BoneMatrices[IN.boneIndices[n] * 3 + 2]);

			objPos+= mul(matrix, IN.position) * allWeights[n];
		}
	}
	else
		objPos = IN.position.xyz;

	OUT.position    = mul(ModelViewProj, float4(objPos, 1));

	OUT.color		= IN.color;// * dot(float3(1,1,1), IN.normal);//float4(0.4f, 0.4f, 0.4f, 0.f) + float4(dot(float3(sin(counter),cos(counter),sin(counter / 3.f)), IN.normal) * float3(1,1,(1 + sin(counter))/2.0f),1);

	OUT.normal			= IN.normal;//mul(WorldInverseTranspose, float4(IN.normal,1.f)).xyz;
	OUT.texCoords 		= IN.texCoords;

	return OUT;
}
Man beachte, dass ich die shadowCoords-Berechnung nur einige Zeilen weiter nach oben geschoben habe.

Wie kann das sein? Im generierten GLSL-Code wurden beide Varianten bis auf die Verschiebung ebenfalls gleich kompiliert und die Kopie von IN.texCoords -> OUT.texCoords findet beide Male statt.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Irrationaler CG-Shader

Beitrag von dot »

Möglicherweise ein Compilerbug? Stimmen überhaupt die Inputs? Wenn schon keine sinnvollen Texcoords aus dem VertexBuffer kommen, können natürlich auch keine sinnvollen Texcoords kopiert werden...
Eisflamme
Establishment
Beiträge: 412
Registriert: 26.05.2002, 17:42
Wohnort: Köln

Re: Irrationaler CG-Shader

Beitrag von Eisflamme »

Also Positionsberechnung, Normalen, Texturkoordinaten werden ja alle korrekt berechnet, das sieht man am Ende am Bild. Die Schattenmatrix hätte falsch sein können, jedoch habe ich probeweise Mal dieselbe Matrix wie für die ModelViewProj übergeben, die Übergabe geprüft (indem ich die Positionsberechnung mit der ShadowTextureMatrix tat, was funktionierte) und das Resultat ist dasselbe: Am Ende sind die Texturkoordinaten weg (oder irgendwie unsinnig zumindest, denn am Ende ist das Modell schwarz; vll. ist auch COLOR oder die Schattenmatrix selbst das Problem, werde ich später noch untersuchen!). Wenn ich an besagter Stelle (wo ShadowTextureMatrix und ModelViewProj gleich sind) dann mit der ModelViewProj multipliziere geht's; und falls mit ShadowTextureMatrix die Multiplikation durchgeführt wird, so erhalte ich besagtes Verhalten, dass die Texturkoordinaten nicht mehr stimmen.

Das ist sehr sinnlos. Ich überlege auch, ob das zu viele Koordinaten für den Shader sind? CG macht oft Unfug, jedoch ist der GLSL-Code ja eigentlich okay...

Sonst würde nur noch Sinn machen, dass die Schatten-Texturkoordinaten sehr unsinnig sind. Für einen anderen Shader, der auch TEXCOORD0 nutzt, funktionieren diese jedoch wunderbar! Einzige Möglichkeit wäre, dass ich von OpenGL-Seite irgendwas doch noch überschreibe, was ich aber nicht tue. Ich prüfe dies nochmal, aber bin eigentlich recht sicher, dass da nichts ist.

Gibt es sonst irgendwelche möglichen Gründe, die undefiniertes Verhalten hervorrufen kann? Am Shadercode ist sonst nichts semantisch falsch, soweit man das sehen kann?

Ich poste Mal noch meinen Fragment-Shader, falls den jemand sehen will. Leider teilweise weniger gelungene Variablenbezeichnungen:

Code: Alles auswählen

struct inner
{
	float4 color : COLOR;
	float4 shadowCoords : TEXCOORD0;
	float2 texCoords : TEXCOORD1;
	float3 normal : TEXCOORD2;
};

struct OUT
{
	float4 color : COLOR;
};

OUT mains(inner IN, uniform sampler2D shadowMap : TEXUNIT0, uniform sampler2D sampler : TEXUNIT1, uniform float Highlight)
{
	OUT x;

	x.color	= tex2D(sampler, IN.texCoords);

	IN.shadowCoords.z += 0.0005;

	float distanceFromLight = tex2D(shadowMap, IN.shadowCoords.xy).z;
	if(IN.shadowCoords.w > 0.0)
	{
		float shadowFactor = distanceFromLight < IN.shadowCoords.z ? 0.5 : 1.0;
		x.color.rgb *= shadowFactor;
	}
	
	//x.color.rgb *= float4(.7f, .7f, .7f, 1.f) + float4(dot(float3(1,1,1), IN.normal) * float3(.3,.3,.3), 1.f);

	return x;
}
Benutzeravatar
mOfl
Beiträge: 37
Registriert: 23.10.2010, 21:53

Re: Irrationaler CG-Shader

Beitrag von mOfl »

Ich weiß nicht, inwiefern dir das weiter hilft, aber ich hatte vor ein paar Wochen ein Problem mit CG auf meinem Notebook (GeForce GTX 260M), auf meinem PC (GeForce GTX 480) lief alles ohne Probleme. Das Problem war, dass die Inhalte in den Buffern auf dem Notebook anscheinend nicht der angegebenen Größe entsprachen, sondern alle vom Typ float4 waren, d.h. auch meine Normalen und Texturkoordinaten hatten auf einmal 4 Komponenten, die dann an anderer Stelle fehlten. Das war relativ seltsam und ich konnte es dann lösen, indem ich von Cg 3.0 auf 3.1 February 2012 geupdated habe. Hast du die Version? Wenn nein, würde ich dir das mal empfehlen.

Eine Frage aus Neugier: (Warum) übergibst du in deinem inner-struct "shadowCoords"? Wenn ich das recht deute, machst du Shadow Mapping und willst dem Fragment Shader die transformierte Position in OUT.shadowCoords übergeben, was sollte dann in IN.shadowCoords stehen?

Allgemein bin ich ein wenig enttäuscht von Cg. Habe mich lange damit auseinander gesetzt und viele Stunden darauf verwendet, ein paar exotischere Sachen wie z.B. Tessellation zum Laufen zu kriegen, aber irgendwie ist es meiner Meinung nach viel instabiler als GLSL und unterstützt immer noch nicht einmal Core Profiles... ich glaub, im Sommer steige ich wieder auf GLSL um, so zukunftsträchtig wie angekündigt scheint Cg doch nicht zu sein :(
Eisflamme
Establishment
Beiträge: 412
Registriert: 26.05.2002, 17:42
Wohnort: Köln

Re: Irrationaler CG-Shader

Beitrag von Eisflamme »

Das mit den Komponenten würde Sinn machen, da die Texturkoordinaten (nach erneutem Test) nämlich 0 und 0 sind.

Bzgl. ShadowCoords hast Du richtig gedacht, das sind die Texturkoordinaten für meine Shadowmap. Die ShadowTextureMatrix transferiert die Vertex-Position in die entsprechende Texturkoordinate. Dementsprechend sollte bei richtiger Übertragung eben die jeweiligen Schatten auf dem Objekt landen (die übrigens nicht dem schwarz entsprechen, was ich zurzeit habe).

Cg enttäuscht mich leider auch immer wieder. Zwar mache ich auch viele Fehler, aber es ist einfach oft nicht deterministisch, auch wenn alle Parameter korrekt sind. Update lade ich sofort, bin sehr gespannt. :)

Edit: Update half leider nix :(
Antworten