Mehrere Texturen im Shader [solved]

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
Jonathan
Establishment
Beiträge: 2658
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Mehrere Texturen im Shader [solved]

Beitrag von Jonathan »

[EDIT] Inzwischen gelöst, Thema kann gelöscht werden oder der Nachwelt als Hinweis auf die Lösung erhalten bleiben[/EDIT]

Ich habe eine Qt-Anwendung die in einem glWidget per Shader mehrere Texturen kombinieren soll. Das funktioniert auch alles soweit ganz gut, aber sobald ich mehrere Texutren benutzen will, stimmen die Werte aus den Samplern nicht, ich sehe immer nur die zuletzt gebundene Textur.

[EDIT] Code im zweiten Post vereinfacht und stark verkürzt, den alten lass ich nur als Referenz hier stehen [/EDIT]

Hier mal Code:

Code: Alles auswählen

uniform sampler2D Clusters;
uniform sampler2D OriginalImage;
uniform bool ShowC1;
uniform bool ShowC2;

varying vec2 vTextureCoord;

void main(void)
{
	if(ShowC1)
		gl_FragColor = vec4(texture2D(Clusters, vTextureCoord).rrr, 0.5);
	else
		gl_FragColor = vec4(texture2D(OriginalImage, vTextureCoord).rrr, 0.5);

Code: Alles auswählen

void MainWindow::on_StartClustering()
{
	//m_OutputWidget->makeCurrent();

	//Load the Shader
	//well, it would be better to do this just once, but we can't do it in the ctor
	m_OutputWidget->SetShaderSourceFile(":/Shader/Shader.vert", ":/Shader/Shader.frag");

	m_OutputWidget->Shader()->setUniformValue("ShowC1", true);
	m_OutputWidget->Shader()->setUniformValue("ShowC2", true);
	
	m_OutputWidget->SetTexture(msi::OpenGL::CreateTexture(m_InputImage[0]), 1);
	m_OutputWidget->SetTexture(msi::OpenGL::CreateTexture(kMeansClustering(m_InputImage)), 0);

	//m_OutputWidget->Shader()->setUniformValue("Clusters", 0);
	//m_OutputWidget->Shader()->setUniformValue("OriginalImage", 1);
	
	cout << "Locations: " << m_OutputWidget->Shader()->uniformLocation("Clusters") << " " << m_OutputWidget->Shader()->uniformLocation("OriginalImage") << endl;

	glUniform1i(m_OutputWidget->Shader()->uniformLocation("Clusters"), 0);
	glUniform1i(m_OutputWidget->Shader()->uniformLocation("OriginalImage"), 1);

	m_OutputWidget->updateGL();
}

Code: Alles auswählen

void ShaderWidget::SetShaderSourceFile(QString VertexSource, QString FragmentSource)
{
	m_Shader->removeAllShaders();
	if(!m_Shader->addShaderFromSourceCode(QGLShader::Vertex, VertexSource)) ...
	if(!m_Shader->addShaderFromSourceCode(QGLShader::Fragment, FragmentSource)) ...
	if(!m_Shader->link()) ...
	if(!m_Shader->bind()) ...
}

void ShaderWidget::SetTexture(GLuint Texture, int Channel)
{
	m_Textures[Channel]=Texture;
	
	glActiveTexture(GL_TEXTURE0+Channel);
	glBindTexture(GL_TEXTURE_2D, Texture);
}
Die Theorie sollte ja ganz einfach sein. Man hat seine Texturen gebunden und muss dann den Sampler als Uniformvariable nicht die Textur ID geben sondern den Channel und die Texturid eben an diesen Channel binden (eine Tatsache, derer ich mir früher nicht bewusst war, was ziemlich ärgerlich war). Aber viel mehr sollte da ja nicht mehr zu machen sein, deshalb verstehe ich nicht, wieso es nicht geht. Der Shader ansich läuft, die Texturen sind richtig, ich kann auch ganz wunderbar alle anderen Uniforms setzen, nur eben nicht mehrere Texturen gleichzeitig...
Zuletzt geändert von Jonathan am 16.11.2012, 12:49, insgesamt 2-mal geändert.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Jonathan
Establishment
Beiträge: 2658
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Mehrere Texturen im Shader

Beitrag von Jonathan »

Habs mal vereinfacht:

Code: Alles auswählen

	m_OutputWidget->SetShaderSourceFile(":/Shader/Shader.vert", ":/Shader/Shader.frag");

	m_OutputWidget->Shader()->setUniformValue("ShowC1", true);
	m_OutputWidget->Shader()->setUniformValue("ShowC2", true);
	
	GLint Tex=msi::OpenGL::CreateTexture(kMeansClustering(m_InputImage));
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, Tex);
	
	GLint Tex2=msi::OpenGL::CreateTexture(m_InputImage[0]);
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, Tex2);

	glActiveTexture(GL_TEXTURE0);

	glUniform1i(m_OutputWidget->Shader()->uniformLocation("Clusters"), 0);
	glUniform1i(m_OutputWidget->Shader()->uniformLocation("OriginalImage"), 1);

	m_OutputWidget->updateGL();
In dem Zustand sind beide Texturen jeweils die zweite Textur. Wenn ich den unteren Teil mit Tex2 auskommentiere, ist die erste Textur korrekt, die zweite schwarz. Also irgendwie überschreibt die erste Textur die zweite, aber ich habe keine Ahnung, warum.
Auch das nochmal eingefügt ActiveTexture(0) ändert überhaupt nichts am gezeigten Sachverhalt.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Jonathan
Establishment
Beiträge: 2658
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Mehrere Texturen im Shader

Beitrag von Jonathan »

Oh man. Ich hasse OpenGL, ich hasse alles, was mit globalen States zu tun hat. Die CreateTexture aufrufe mussten die Textur auch erst binden, und da ich erst die zweite Textur erzeugt habe und dann an den zweiten Channel (oder wie man das auch nennt?) gebunden habe, hat das erstellen der ersten Textur die zweite Textur überschrieben. Was für ein sau dämliches Konzept.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Antworten