Jump to content
  • Advertisement
Sign in to follow this  
wall

OpenGL Problem with smooth color shading

This topic is 5064 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi! I'm trying to create a simple skydome for my game. I am going to use vertex coloring to create a nice sky color that can be changed in realtime. My problem is that I don't get a smooth color transition between the vertices(not animation, ahven't come to that yet). Here's a screenshot to illustrate my problem: http://img82.exs.cx/my.php?loc=img82&image=DOME.jpg I use OpenGL and obviously have GL_SMOOTH set as shade model. The dome is drawn as a triangle strip from top to bottom in horisontal circles, not as vertical stripes. Maybe that has something to do with it? I don't know... Anyways, here's the code that I use and found at www.spheregames.com:
void CSky::CreateSkyDome()
{
	int theta, phi;

	//Allocate memory for the vertices
	m_nrVertices = (int)((360/m_dTheta)*(90/m_dPhi)*4);
	m_vertices = new Vector3D[m_nrVertices];

        //Calculate and store the vertices
	int n = 0;
	for (phi=0; phi <= 90 - m_dPhi; phi += (int)m_dPhi)
        {
		for (theta=0; theta <= 360 - m_dTheta; theta += (int)m_dTheta)
                {
			m_vertices[n].x = m_radius * sinf(DEGTORAD(phi)) * cosf(DEGTORAD(theta));
			m_vertices[n].y = m_radius * sinf(DEGTORAD(phi)) * sinf(DEGTORAD(theta));
			m_vertices[n].z = m_radius * cosf(DEGTORAD(phi));
			n++;
			m_vertices[n].x = m_radius * sinf(DEGTORAD((phi+m_dPhi))) * cosf(DEGTORAD(theta));
			m_vertices[n].y = m_radius * sinf(DEGTORAD((phi+m_dPhi))) * sinf(DEGTORAD(theta));
			m_vertices[n].z = m_radius * cosf(DEGTORAD((phi+m_dPhi)));
			n++;
			m_vertices[n].x = m_radius * sinf(DEGTORAD(phi)) * cosf(DEGTORAD((theta+m_dTheta)));
			m_vertices[n].y = m_radius * sinf(DEGTORAD(phi)) * sinf(DEGTORAD((theta+m_dTheta)));
			m_vertices[n].z = m_radius * cosf(DEGTORAD(phi));
			n++;
			if (phi > -90 && phi < 90)
			{
				m_vertices[n].x = m_radius * sinf(DEGTORAD((phi+m_dPhi))) * cosf(DEGTORAD((theta+m_dTheta)));
				m_vertices[n].y = m_radius * sinf(DEGTORAD((phi+m_dPhi))) * sinf(DEGTORAD((theta+m_dTheta)));
				m_vertices[n].z = m_radius * cosf(DEGTORAD((phi+m_dPhi)));
				n++;
			}
		}
	}
}


phi is the latitude of the sphere and theta is the longitude(m_dPhi and m_dTheta between each "segment") And here's my code to draw the dome. I change the color of the vertices according to the y coordinate of each vertex. But as mentioned, I get the problem you see in the screenshot above.
void CSky::RenderSkyDome()
{
        //Used to change the color
	Vector3D tempVert(m_vertices[0]);
	float color = 0;

        //Draw the dome as a triangle strip
	glBegin(GL_TRIANGLE_STRIP);
	for (int i = 0; i < m_nrVertices; i++)
	{
                //Check to see if we should change the color
		if (tempVert.y < m_vertices.y)
		{
			vert = m_vertices;
                        glColor3f(color, color, 1.0f);
			color += 0.05f;
		}

		glVertex3f(m_vertices.x, m_vertices.y, m_vertices.z);
	}
	glEnd();
}



As I said, I found the code to generate the dome on the internet, and I don't fully understand it. But I would be glad if somebody could point out the problem and a solution. Thanks in advance William

Share this post


Link to post
Share on other sites
Advertisement
You say that you are using smooth shading, but for a sky dome, wouldn't you rather draw it with out any lighting?

Share this post


Link to post
Share on other sites
I don't use any lighting. It's the vertices colors I want interpolated between eachother. Therefore I use smooth shading, but I still don't get the result I want. Anybody know how to solve this? should I build the dome in some other way?

Share this post


Link to post
Share on other sites
I can't see your screen shot so it's hard to say what the problem is. Nothing obvious jumps out from the code you posted.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
glShadeModel(GL_SMOOTH);

Share this post


Link to post
Share on other sites
Sorry for the broken image link...
Here's a screenshot:
http://img14.exs.cx/img14/2505/DOME.jpg

And as I mentioned in my first post, I have GL_SMOOTH set as shade model...

Share this post


Link to post
Share on other sites
i think i see the problem

looking at your code, as soon as you see a vertex in the strip that is higher up than the current highest Y, you consider it a new row and change the color

but this dome is made using triangle strips

which means, every other vertex alternates between the top and bottom edge of each horizontal band
(each band is a circular triangle strip)

thus, you end up with the same vertex color for both the top and bottom edges of each band, and when you smooth shade between 2 verts that are the same color, it looks flat

bottom line:
you need to rethink the way you decide to change colors, its happening at the wrong times

quick fix might be:
keep your current color detection code, but
try alternating between the new color and the last used color every other vertex, and the order matters, so try both ways

if you cant get that working, a less efficient but simpler way
is to just do a check on the Y value for every single vertex and set their color individually

and in the long term, you might consider using a vertex array
since the domecreate function is already outputting in array form....
that would mean having a color array in addition

Share this post


Link to post
Share on other sites
aww heck
here i'll write it for you
only takes a minute anyway

if this doesnt work try swapping the lines marked color band 1 and 2



void CSky::RenderSkyDome()
{
//Used to change the color
Vector3D tempVert(m_vertices[0]);
float color = 0;
float lastcolor=0;
int swap=0;*/this is a swtich to toggle between top and bottom edge of each band*/

//Draw the dome as a triangle strip
glBegin(GL_TRIANGLE_STRIP);
for (int i = 0; i < m_nrVertices; i++)
{
//Check to see if we should change the color
if (tempVert.y < m_vertices.y)
{
vert = m_vertices;
lastcolor=color;
color += 0.05f;
}

if(swap){
//color band 1
glColor3f(color, color, 1.0f);
}else{
//color band 2
glColor3f(lastcolor, lastcolor, 1.0f);
}
glVertex3f(m_vertices.x, m_vertices.y, m_vertices.z);
swap=swap^1;
}
glEnd();
}


Share this post


Link to post
Share on other sites
Thanks for pointing that out haphazardlynamed! you were a great help!
I rewrote the function so that it uses the vertices y-coordinate directly to choose the color(glColor3f(yCoord, yCoord, 1) basically). Thanks for providing the code though!

I will probably switch to vertex arrays later, just wanted to get it working first.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!