How to render few objects with texture and other without (Simple deferred shading)

Hello there,

I am writing my small render engine mostly to learn how OpenGL works, improve my C++, and to refresh those high school maths.

It seems that i struggle a lot with design of the whole engine mostly because I want to do it my own way even thought i read from few books how it should be done correctly. My goal now is to finish how i handle materials then go to implementing lights, then improve/extend the texture class to use it as FBO, render shadows, and use it for multiple pass rendering. Then i don’t know what, but i am planing to implement fog, particles, caustics (for water), volumetric light, depth testing, stencil testing, instancing, culling and cube maps. I might most probably implement depth testing and culling to improve performance and see how i can use then in future when i add more to the render engine.

My biggest issue now is that i can not render objects that have no textures bound to them. I am about to finish this and it will conclude the first phase, the deferred shading of my engine and its core components (then it is light and extend Material class). I know there are lots of issues with my C++ but for now i don’t really care (just wnat to learn OpenGL now) because during summer i plan to try and reuse this engine to implement an improved version to a simple Physically Based Rendering engine.

I have a scene that i have a plane, a teapot without texture a circle and a box with textures but i cant not render objects without texture (You can notice the straight line of plane being rendered in black). Is there a way to solve this issue without many conditions in the shader file and if you have any suggestions how can I improve my engine or especially the material class even though I just wrote the basic structure today. I found this post but still starching my head how to deal with this issue https://www.opengl.org/discussion_boards/showthread.php/174945-Check-for-invalid-Sampler

The code i use to draw the shapes.



void Mesh::draw(){

	glBindVertexArray(vertexArrayObject_);

	for (size_t i = 0; i < bufferTypes_.size(); ++i) {
		// FIXME :: bind only those texture for the aporpriate object
		// for easyer testing and debugging i use an iterator. This allows me to see what material is found
		for (size_t j = 0; j < bufferTypes_[i].material_id.size(); j++){
			auto it = material_.find(bufferTypes_[i].material_id[j]);

			if (it != material_.end()){
				if (it->second->getDiffuseTexture() != NULL){
					it->second->getDiffuseTexture()->bind(j,1);
				}
				else {
					glBindSampler(1, 0);
					glBindTexture(GL_TEXTURE_2D, 0);
					glUniform1i(1, 0);
					//glUniform1i(it->second->getDiffuseTexture()->getTextureId(), 0);
				}
			}
	
		}

		glEnableVertexAttribArray(0);
		glBindBuffer(GL_ARRAY_BUFFER, bufferTypes_[i].vertex);
		//glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)((sizeof(shapes_[i].mesh.positions[0])) * shapes_[i].mesh.positions[0].size()));
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

		if (hasUV(i)){
			glEnableVertexAttribArray(1);
			glBindBuffer(GL_ARRAY_BUFFER, bufferTypes_[i].uv);
			//glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)((sizeof(shapes_[i].mesh.texcoords[0])) *shapes_[i].mesh.texcoords.size()));
			glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
		}

		if (hasNormals(i)){
			glEnableVertexAttribArray(2);
			glBindBuffer(GL_ARRAY_BUFFER, bufferTypes_[i].normal);
			//glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)((sizeof(shapes_[i].mesh.normals[0]))* shapes_[i].mesh.normals.size()));
			glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
		}

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferTypes_[i].index);

		glDrawElements(GL_TRIANGLES, shapes_[i].mesh.indices.size(), GL_UNSIGNED_INT, (void*)0);

		glDisableVertexAttribArray(0);
		if (hasUV(i)) glDisableVertexAttribArray(1);
		if (hasNormals(i)) glDisableVertexAttribArray(2);

		// for easyer testing and debugging i use an iterator. This allows me to see what material is found
		for (size_t j = 0; j < bufferTypes_[i].material_id.size(); j++){
			auto it = material_.find(bufferTypes_[i].material_id[j]);
			if (it != material_.end()){
				if (it->second->getDiffuseTexture() != NULL)
					it->second->getDiffuseTexture()->unbind(j);
			}
			else {
				glBindSampler(0, 0);
			}
		}
	}

	glBindVertexArray(0);
}

I have my engine in github and I will put the links of the classes. If you would like to put the code let me know and i will edit the post.

https://github.com/lumx/GameEngine/blob/master/GameEngine/src/Core/Render/Material.h
https://github.com/lumx/GameEngine/blob/master/GameEngine/src/Core/Render/Material.cpp

https://github.com/lumx/GameEngine/blob/master/GameEngine/src/Core/Render/Texture.h
https://github.com/lumx/GameEngine/blob/master/GameEngine/src/Core/Render/Texture.cpp

https://github.com/lumx/GameEngine/blob/master/GameEngine/src/Core/Render/ShaderProgram.h
https://github.com/lumx/GameEngine/blob/master/GameEngine/src/Core/Render/ShaderProgram.cpp

I am sorry I am putting the links like this but i dont see a better way how to make this post shorter.

There are a number of options here. First, just bind a a texture with a solid color that (when sampled and applied) will result in a change which effectively omits the texturing computation. For instance, if your shader uses the texture as a MODULATE factor (e.g. color *= texture_value), pass in a 1x1 texture which contains a white texel. With this option, you don’t need a specific shader permutation to handle this case, nor conditional logic in the shader to decide texturing path to take.

Another option is that you could pass in a uniform that would dynamically skip texturing based on some uniform you pass in. But you need to be careful here because derivatives aren’t defined in conditionals. See:

A third option is you could compile a special shader permutation (e.g. via an ubershader technique) for with and without texturing. May or may not be worth your trouble depending on whether you are ever fragment limited. But this is nevertheless an option.

Ok i fixed it. I use the first method with 1 white texel for now. I still dont like this way but i guess it was the simplest one to be able to continue faster. If you have any suggestion how can i improve my small render engine i would be happy to get hear them and learn something from them.

Thank you for help. :smiley: