Problem bei mehreren Shadern



  • Hallo,

    ich bin noch relativ neu in OpenGL und versuche mich Momentan bei der Erstellung einer Skybox im Zusammenspiel mit einem anderen Objekt.
    Irgendwo steckt noch ein kleiner Denkfehler drin, den ich auf Grund meiner mangelnden Erfahrung nicht finde.
    Ich hoffe, ihr könnt mir helfen.

    Entferne ich den ersten Programmaufruf, wird das zweite Objekt korrekt gezeichnet, entferne ich stattdessen den zweiten, funktioniert die Skybox. Bleiben beide aktiv, wird beides fehlerhaft.

    Hier mal die Renderfunktion, ist hier kein Fehler zu finden, reiche ich Stück für Stück nach:

    void renderScene(void)
    {
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    	glClearColor(0.0f, 0.3f, 1.0f, 1.0f);
    
    	computeMatricesFromInput();
    	Projection	= getProjectionMatrix();
    	View		= getViewMatrix();
    
    	Model		= glm::mat4(1.0f);
    	vp			= Projection * glm::mat4(glm::mat3(View)); ;
    	mvp			= Projection * View * Model;
    	pos			= getPosition();
    
    	glUniformMatrix4fv(vp_handle, 1, GL_FALSE, &vp[0][0]);
    
    	glDepthMask(GL_FALSE);
    	glUseProgram(skyboxHandle);
    	glEnableVertexAttribArray(0);
    	glBindBuffer(GL_ARRAY_BUFFER, VBO);
    	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
    	glDrawArrays(GL_TRIANGLES, 0, 36);
    
    	glDepthMask(GL_TRUE);
    
    	glUniformMatrix4fv(mvp_handle, 1, GL_FALSE, &mvp[0][0]);
    	glUniformMatrix4fv(m_handle, 1, GL_FALSE, &Model[0][0]);
    	glUniform3fv(pos_handle, 1, &pos[0]);
    
    	glEnableVertexAttribArray(0);
    	glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
    
    	glEnableVertexAttribArray(1);
    	glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
    	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );
    
    	// Index buffer
    	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
    
    	texture = genTexture();
    
    	glUseProgram(renderHandle);
    
    	glDrawElements(
    		GL_TRIANGLES,      // mode
    		(GLsizei)indices.size(),    // count
    		GL_UNSIGNED_INT,   // type
    		(void*)0           // element array buffer offset
    	);
    
    	glDisableVertexAttribArray(0);
    	glDisableVertexAttribArray(1);
    
    	glutSwapBuffers();	
    }
    

    Edit:
    Hier noch ein bisschen mehr Code, der bei der Problemlösung helfen könnte.
    Teil der Initialisierung:

    skyboxHandle = genSkyBoxProg();
    	renderHandle = genRenderProg();	
    
    	vp_handle	= glGetUniformLocation(skyboxHandle, "VP");
    	mvp_handle	= glGetUniformLocation(renderHandle, "MVP");
    	m_handle	= glGetUniformLocation(renderHandle, "model");
    	pos_handle = glGetUniformLocation(renderHandle, "cameraPos");
    
    GLuint genSkyBoxProg() {
    	GLuint progHandle = glCreateProgram();
    	GLuint vp = glCreateShader(GL_VERTEX_SHADER);
    	GLuint fp = glCreateShader(GL_FRAGMENT_SHADER);
    
    	const char *vpSrc[] = {
    
    		"#version 430 core\n",
    		"layout(location = 0) in vec3 vertexPosition_modelspace;\
    		out vec3 texCoords;\
    		uniform mat4 VP;\
    		\
    		void main(){\
    			vec3 pos = vertexPosition_modelspace;\
    			gl_Position =  (VP * vec4(pos,1));\
    			texCoords = pos;\
    		}"
    	};
    
    	const char *fpSrc[] = {
    		"#version 430 core\n",
    		"in vec3 texCoords;\
    		out vec3 color;\
    		uniform samplerCube cubemap;\
    		\
    		void main(){\
    			color = texture(cubemap, texCoords).rgb;\
    		}"
    	};
    	// 
    	glShaderSource(vp, 2, vpSrc, NULL);
    	glShaderSource(fp, 2, fpSrc, NULL);
    
    	glCompileShader(vp);
    	int rvalue;
    	glGetShaderiv(vp, GL_COMPILE_STATUS, &rvalue);
    	if (!rvalue) {
    		fprintf(stderr, "Error in compiling vp\n");
    		exit(130);
    	}
    	glAttachShader(progHandle, vp);
    
    	glCompileShader(fp);
    	glGetShaderiv(fp, GL_COMPILE_STATUS, &rvalue);
    	if (!rvalue) {
    		fprintf(stderr, "Error in compiling fp\n");
    		exit(131);
    	}
    	glAttachShader(progHandle, fp);
    
    	glBindFragDataLocation(progHandle, 0, "color");
    	glLinkProgram(progHandle);
    
    	glGetProgramiv(progHandle, GL_LINK_STATUS, &rvalue);
    	if (!rvalue) {
    		fprintf(stderr, "Error in linking sp\n");
    		exit(132);
    	}
    
    	glUseProgram(progHandle);
    	glUniform1i(glGetUniformLocation(progHandle, "cubemap"), 1);
    
    	return progHandle;
    }
    

    Der zweite Shader baut sich genauso auf, hat nur einen anderen Code.



  • letavino schrieb:

    Bleiben beide aktiv, wird beides fehlerhaft.

    Treffen zwei Programme aufeinander, wird ein Bannungsfeld generiert aus dem die hochfrequenten Frequenzen nicht entkommen, deswegen wird alles Rot bis Infrarot gezeichnet.



  • glUniformMatrix4fv() und glUniform3fv() setzen uniforms in dem momentan aktivem shader der vorher durch glUseProgram() gesetzt wurde.
    Du rufst jedoch glUniform...() immer auf bevor du den dazugehörigen shader aktivierst!

    Also einfach die glUniform...() verschieben, so dass diese nach glUseProgram() aufgerufen werden.

    Du kannst ansonsten auch:

    GL_ARB_separate_shader_objects (Core seit 4.1)
    glProgramUniform...()

    oder GL_EXT_direct_state_access (Kein Bestandteil von Core)
    glProgramUniform...EXT()

    benutzen. Dort gibt man die shader ID mit als Parameter an und muss daher den shader nicht vorher mit glUseProgram() aktivieren.


Anmelden zum Antworten