OpenGL - 쉐이딩(Shading, line, flat smooth)

설명

삼각형으로 만든 원을 LineStrip, FlatShading, SmoothShading 효과를 줘 차이를 본다.


main에 없는 함수는 아래의 링크를 참조한다 (수정 x)

2017/09/12 - [SW/OpenGL] - OpenGL - 사각형 회전, 색바꾸기


선언부

typedef GLfloat point3[3];
static float theta[3];
int num = 1;
void DrawTriangle(point3 &apoint3 &bpoint3 &c);
void Normalize(point3 &p);
void DivideTriangle(point3 &apoint3 &bpoint3 &cint n);
void CrossProduct(point3 &apoint3 &bpoint3 &cpoint3 &r);

Theta 초기화

void init(void) {
	for (int i = 0i < 3i++)
	{
		theta[i] = 0;
	}
}


렌더링 함수

void RenderScene(void) {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(002000010);
 
	glEnable(GL_LIGHTING);//turn on light
	glEnable(GL_LIGHT0);//light0 turn on
 
	glRotatef(theta[2], 001);
	glRotatef(theta[1], 010);
	glRotatef(theta[0], 100);
 
	point3 v[4] = { { 001 },{ 00.942809, -0.333333 },{ -.816497, -0.471405, -0.333333 },{ 0.816497, -0.471405, -0.333333 } };
	int n = 3;
	DivideTriangle(v[0], v[1], v[2], n);
	DivideTriangle(v[0], v[2], v[3], n);
	DivideTriangle(v[0], v[3], v[1], n);
	DivideTriangle(v[3], v[2], v[1], n);
 
	glutSwapBuffers();
}

벡터 정규화

/// <summary>
/// Normalizes vector
/// </summary>
/// <param name="p">The p.</param>
void Normalize(point3 &p) {
	double d = p[0] * p[0] + p[1] * p[1] + p[2] * p[2];
	if (d > 0) {
		float len = (float)(1.0 / sqrt(d));
		p[0] *= lenp[1] *= lenp[2] *= len;
	}
}


벡터 외적

/// <summary>
/// Cross product vector a, b
/// </summary>
/// <param name="a">a.</param>
/// <param name="b">The b.</param>
/// <param name="c">The c.</param>
/// <param name="r">The r.</param>
void CrossProduct(point3 &apoint3 &bpoint3 &cpoint3 &r) {
	r[0] = (b[1] - a[1])*(c[2] - a[2]) - (b[2] - a[2])*(c[1] - a[1]);
	r[1] = (b[2] - a[2])*(c[0] - a[0]) - (b[0] - a[0])*(c[2] - a[2]);
	r[2] = (b[0] - a[0])*(c[1] - a[1]) - (b[1] - a[1])*(c[0] - a[0]);
	Normalize(r);//normalize
}


삼각형으로 나누기

/// <summary>
/// Divides the triangle recursively
/// </summary>
/// <param name="a">a.</param>
/// <param name="b">The b.</param>
/// <param name="c">The c.</param>
/// <param name="n">The n.</param>
void DivideTriangle(point3 &apoint3 &bpoint3 &cint n) {
	if (n > 0) {
		point3 v1v2v3;
		for (register int i = 0i < 3i++) {
			v1[i] = a[i] + b[i];
			v2[i] = b[i] + c[i];
			v3[i] = c[i] + a[i];
		}
		Normalize(v1); Normalize(v2); Normalize(v3);
		DivideTriangle(av1v3n - 1);
		DivideTriangle(bv2v1n - 1);
		DivideTriangle(cv3v2n - 1);
		DivideTriangle(v1v2v3n - 1);
	}
	else {
		DrawTriangle(abc);
	}
}

삼각형들 그리기

/// <summary>
/// Draws the triangle.
/// </summary>
/// <param name="a">point a.</param>
/// <param name="b">point b</param>
/// <param name="c">point c</param>
void DrawTriangle(point3 &apoint3 &bpoint3 &c) {
	if (num == 1// line strip
	{
		glDisable(GL_LIGHT0);//turn off light
		glBegin(GL_LINE_STRIP); {
			glNormal3fv(a); glVertex3fv(a);
			glNormal3fv(b); glVertex3fv(b);
			glNormal3fv(c); glVertex3fv(c);
		}glEnd();
	}
	else if (num == 2//flat shading
	{
		point3 n;
		CrossProduct(abcn);
		glBegin(GL_TRIANGLES);
		glNormal3fv(n);
		glVertex3fv(a);
		glVertex3fv(b);
		glVertex3fv(c);
		glEnd();
	}
	else //smooth shading
	{
		glBegin(GL_TRIANGLES); {
			glNormal3fv(a); glVertex3fv(a);
			glNormal3fv(b); glVertex3fv(b);
			glNormal3fv(c); glVertex3fv(c);
		}glEnd();
	}
}


각 shading마다 이벤트를 받는다.

void keyboard(unsigned char keyint xint y)
{
	switch (key)
	{
	case 1://line strip
	{
		num = 1;
	}break;
 
	case 2://flat shading
	{
		num = 2;
	}break;
	case 3://smooth shading
	{
		num = 3;
	}break;
	default:
		break;
	}
	RenderScene();
}
 
void shape(int item)
{
	keyboard((unsigned char)item00);
}

메인함수

void main(int argccharargv[]) {
	glutInit(&argcargv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(600600);
	glutCreateWindow("Shading");
	glutDisplayFunc(RenderScene);
	glutReshapeFunc(ChangeSize);
 
	//show menu when right click
	glutCreateMenu(shape);
 
	//bind with key event
	glutAddMenuEntry("Wire frame"1);
	glutAddMenuEntry("Flat"2);
	glutAddMenuEntry("Smooth"3);
	glutAttachMenu(GLUT_RIGHT_BUTTON);
 
	init();
	SetupRC();
	glutMainLoop();
}

결과물