Shading looks ugly

Hi there, I’m new using OpenGL. I’m using openFrameworks to load a .3ds model. It loads fine, but it looks kind of ugly compared to what it “should” look like. As you can see in the pictures below, edges don’t look sharp, there are some dark patterns, etc.

I have tried to google this, but I don’t really know what I should look for. Can you guys please give me some idea about what are the possible causes, whether that’s a common problem, what can I do to fix it…? Or at least what terms should I google :slight_smile: ?

Thanks in advance.

You need to figure out how to get better normals. Looks like only have shared normals. Perhaps it is possible to export model with proper non shared normals, or information about smoothing groups, or at least max smoothing angles. This forum has a number of threads discussing how to calculate normals with smoothing angle, If you check my posts you may find some related replies.

Indeed verify carefully everything about the normals :

  • are they really present on the .3ds files ? what is the tool used to display your second image, and is 3ds a native format for it, can you load the .3ds and see exactly this image for example ?
  • are they correctly loaded by your openFrameworks tools ? ie. have several distinct normals at each edge, instead of sharing the same (which will look smoothed out). This would need some printf of the data, try a simple cube as example.
  • are you correctly doing the rendering using the data generated by openFrameworks ? Show your code.

Hi, first of all, thank you both for your reply.

I downloaded the .max file from artist-3d.com. That’s where I got the second picture.

I exported the model in .3ds format, because that’s the format used by the openFrameworks addon.

I followed your suggestions and reopened the .3ds file with 3dsmax and the edges look fine, also in Blender.

I attached the openFrameworks addon code. I think the file we need to look at is “3DS/model3DS.cpp”.

This is the part of the code that computes the normals:


void mesh3DS::calculateNormals(){

	// Doesn't take smoothing groups into account yet

	if(DEBUG_OUTPUT) std::cout<<"Calculating normals... ";
	m_normals.assign(m_vertices.size(), 0.0f);

	Vertex vtx1, vtx2, vtx3;
	Vector3DS v1, v2, faceNormal;

	for(int face=0; face < int(m_faces.size()); face+=3){
		// Calculate face normal
		vtx1.set(m_vertices[m_faces[face]*3], m_vertices[(m_faces[face]*3)+1], m_vertices[(m_faces[face]*3)+2]);
		vtx2.set(m_vertices[m_faces[face+1]*3], m_vertices[(m_faces[face+1]*3)+1], m_vertices[(m_faces[face+1]*3)+2]);
		vtx3.set(m_vertices[m_faces[face+2]*3], m_vertices[(m_faces[face+2]*3)+1], m_vertices[(m_faces[face+2]*3)+2]);

		v1 = vtx2 - vtx1;
		v2 = vtx3 - vtx1;

		faceNormal = v1.crossProduct(v2);

		// Add normal to all three vertex normals
		m_normals[m_faces[face]*3] += faceNormal.x;
		m_normals[(m_faces[face]*3)+1] += faceNormal.y;
		m_normals[(m_faces[face]*3)+2] += faceNormal.z;

		m_normals[m_faces[face+1]*3] += faceNormal.x;
		m_normals[(m_faces[face+1]*3)+1] += faceNormal.y;
		m_normals[(m_faces[face+1]*3)+2] += faceNormal.z;

		m_normals[m_faces[face+2]*3] += faceNormal.x;
		m_normals[(m_faces[face+2]*3)+1] += faceNormal.y;
		m_normals[(m_faces[face+2]*3)+2] += faceNormal.z;

	}

	//normalize all normals
	for(int n=0; n < int(m_normals.size()); n+=3){
		faceNormal.set(m_normals[n], m_normals[n+1], m_normals[n+2]);
		faceNormal.normalize();
		m_normals[n] = faceNormal.x;
		m_normals[n+1] = faceNormal.y;
		m_normals[n+2] = faceNormal.z;
	}

	if(DEBUG_OUTPUT) std::cout<<"done"<<std::endl;
}

In my code, I just setup the lighting, and call the .loadModel() and .draw() methods.

Ok, I see there is this comment in the code

// Doesn't take smoothing groups into account yet

Is that what is missing?

Indeed.
The smoothing groups define the set of vertices that are smooth.
The “Add normal to all three vertex normals” part should not add normal to a vertex not belonging to the same smoothing group.

Now, I am not sure if your best bet is to fix the 3DS/model3DS.cpp code or use a different loading library, like http://assimp.sourceforge.net/ for example. Try the viewer to have a quick look if the features are enough for you.

I just tried the assimp viewer and the model loads perfect. I downloaded the library and had a look at the “simple opengl sample”, but it doesn’t look very simple though :frowning:

I see in the openFrameworks addon code that the smoothing groups are actually already loaded into a vector, but they are never used. Is it very hard to fix?

It also looks like they are doing a full radiosity solve for the lighting or at least some pretty accomplished ambient occlusion lighting. So one the edges are sharper, that will be the next difference…

Thanks guys! I managed to solve this issue. I found out there is actually an Assimp addon for the latest version of openFrameworks. I was using an older version because I wasn’t able to render textures with the lastest one. Then I upgraded the graphics driver and everything seems to work fine now.

Thank you very much :slight_smile: