opengl超级宝典(第五版)阅读笔记 7 抗锯齿

在图形光栅化的时候,难免会出现很多锯齿现象,如下图所示:
在这里插入图片描述
可以看到很明显的一段一段的锯齿。
opengl中通过把该点像素与周围像素相混合来优化锯齿现象,方法如下:

		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//设置混合模式
		glEnable(GL_BLEND);//开启混合
		glEnable(GL_POINT_SMOOTH);//点的抗锯齿
		glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);//最好模式运行平滑 可选GL_FASTEST
		glEnable(GL_LINE_SMOOTH);//直线抗锯齿
		glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
		glEnable(GL_POLYGON_SMOOTH); //多边形抗锯齿
		glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);

优化的图片如下:
在这里插入图片描述

完整代码如下(因为大部分代码前面都有注释过,因此这里只有关键部分会有一些注释):

#include <GLTools.h>  // OpenGL toolkit   
#include <GLFrustum.h>   
#define FREEGLUT_STATIC  //在windows和linux上,使用freeglut静态版本,需要添加这一行,否则会出现错误
#include <glut.h>
#pragma comment(lib,"gltools.lib")//要加上这一行链接一下gltools库
#include <time.h>
GLShaderManager shaderManager;
GLFrustum viewFrustum;
GLBatch smallStarBatch;
GLBatch mediumStarBatch;
GLBatch largeStarBatch;
GLBatch mountainRangeBatch;
GLBatch moonBatch;

// Array of small stars   
#define SMALL_STARS     100   
#define MEDIUM_STARS     40   
#define LARGE_STARS      15   

#define SCREEN_X        800   
#define SCREEN_Y        600   

///////////////////////////////////////////////////////////////////////   
// Reset flags as appropriate in response to menu selections   
void ProcessMenu(int value)
{
	switch (value)
	{
	case 1:
		// Turn on antialiasing, and give hint to do the best   
		// job possible.   
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//设置混合模式
		glEnable(GL_BLEND);//开启混合
		glEnable(GL_POINT_SMOOTH);//点的抗锯齿
		glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);//最好模式运行平滑 可选GL_FASTEST
		glEnable(GL_LINE_SMOOTH);//直线抗锯齿
		glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
		glEnable(GL_POLYGON_SMOOTH); //多边形抗锯齿
		glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
		break;

	case 2:
		// Turn off blending and all smoothing   
		glDisable(GL_BLEND);
		glDisable(GL_LINE_SMOOTH);
		glDisable(GL_POINT_SMOOTH);
		glDisable(GL_POLYGON_SMOOTH);
		break;

	default:
		break;
	}

	// Trigger a redraw   
	glutPostRedisplay();
}


///////////////////////////////////////////////////   
// Called to draw scene   
void RenderScene(void)
{
	// Clear the window   
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	// Everything is white   
	GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
	shaderManager.UseStockShader(GLT_SHADER_FLAT, viewFrustum.GetProjectionMatrix(), vWhite);
	// Draw small stars   
	glPointSize(1.0f);
	smallStarBatch.Draw();
	// Draw medium sized stars   
	glPointSize(4.0f);
	mediumStarBatch.Draw();
	// Draw largest stars   
	glPointSize(8.0f);
	largeStarBatch.Draw();
	// Draw the "moon"   
	moonBatch.Draw();
	// Draw distant horizon   
	glLineWidth(3.5);
	mountainRangeBatch.Draw();
	moonBatch.Draw();
	// Swap buffers   
	glutSwapBuffers();
}

// This function does any needed initialization on the rendering   
// context.    

void SetupRC()
{
	M3DVector3f vVerts[SMALL_STARS];       // SMALL_STARS is the largest batch we are going to need   
	int i;
	shaderManager.InitializeStockShaders();
	// Populate star list   
	smallStarBatch.Begin(GL_POINTS, SMALL_STARS);
	for (i = 0; i < SMALL_STARS; i++)
	{
		vVerts[i][0] = (GLfloat)(rand() % SCREEN_X);
	 	vVerts[i][1] = (GLfloat)(rand() % (SCREEN_Y - 100)) + 100.0f;
		vVerts[i][2] = 0.0f;
	}
	smallStarBatch.CopyVertexData3f(vVerts);
	smallStarBatch.End();

	// Populate star list   
	mediumStarBatch.Begin(GL_POINTS, MEDIUM_STARS);
	for (i = 0; i < MEDIUM_STARS; i++)
	{
		vVerts[i][0] = (GLfloat)(rand() % SCREEN_X);
		vVerts[i][1] = (GLfloat)(rand() % (SCREEN_Y - 100)) + 100.0f;
		vVerts[i][2] = 0.0f;
	}
	mediumStarBatch.CopyVertexData3f(vVerts);
	mediumStarBatch.End();

	// Populate star list   
	largeStarBatch.Begin(GL_POINTS, LARGE_STARS);
	for (i = 0; i < LARGE_STARS; i++)
	{
		vVerts[i][0] = (GLfloat)(rand() % SCREEN_X);
		vVerts[i][1] = (GLfloat)(rand() % (SCREEN_Y - 100)) + 100.0f;
		vVerts[i][2] = 0.0f;
	}
	largeStarBatch.CopyVertexData3f(vVerts);
	largeStarBatch.End();

	M3DVector3f vMountains[12] = { 0.0f, 25.0f, 0.0f,
		50.0f, 100.0f, 0.0f,
		100.0f, 25.0f, 0.0f,
		225.0f, 125.0f, 0.0f,
		300.0f, 50.0f, 0.0f,
		375.0f, 100.0f, 0.0f,
		460.0f, 25.0f, 0.0f,
		525.0f, 100.0f, 0.0f,
		600.0f, 20.0f, 0.0f,
		675.0f, 70.0f, 0.0f,
		750.0f, 25.0f, 0.0f,
		800.0f, 90.0f, 0.0f };

	mountainRangeBatch.Begin(GL_LINE_STRIP, 12);
	mountainRangeBatch.CopyVertexData3f(vMountains);
	mountainRangeBatch.End();

	// The Moon   
	GLfloat x = 700.0f;     // Location and radius of moon   
	GLfloat y = 500.0f;
	GLfloat r = 50.0f;
	GLfloat angle = 0.0f;   // Another looping variable   

	moonBatch.Begin(GL_TRIANGLE_FAN, 34);
	int nVerts = 0;
	vVerts[nVerts][0] = x;
	vVerts[nVerts][1] = y;
	vVerts[nVerts][2] = 0.0f;
	for (angle = 0; angle < 2.0f * 3.141592f; angle += 0.2f) {
		nVerts++;
		vVerts[nVerts][0] = x + float(cos(angle)) * r;
		vVerts[nVerts][1] = y + float(sin(angle)) * r;
		vVerts[nVerts][2] = 0.0f;
	}
	nVerts++;

	vVerts[nVerts][0] = x + r;;
	vVerts[nVerts][1] = y;
	vVerts[nVerts][2] = 0.0f;
	moonBatch.CopyVertexData3f(vVerts);
	moonBatch.End();

	// Black background   
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}



void ChangeSize(int w, int h)
{
	// Prevent a divide by zero   
	if (h == 0)
		h = 1;

	// Set Viewport to window dimensions   
	glViewport(0, 0, w, h);
	// Establish clipping volume (left, right, bottom, top, near, far)   
	viewFrustum.SetOrthographic(0.0f, SCREEN_X, 0.0f, SCREEN_Y, -1.0f, 1.0f);
}

int main(int argc, char* argv[])
{
	srand((int)time(NULL));
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(800, 600);
	glutCreateWindow("Smoothing Out The Jaggies");
	// Create the Menu   
	glutCreateMenu(ProcessMenu);
	glutAddMenuEntry("Antialiased Rendering", 1);
	glutAddMenuEntry("Normal Rendering", 2);
	glutAttachMenu(GLUT_RIGHT_BUTTON);
	glutReshapeFunc(ChangeSize);
	glutDisplayFunc(RenderScene);
	GLenum err = glewInit();
	if (GLEW_OK != err) {
		fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
		return 1;
	}
	SetupRC();
	glutMainLoop();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43813453/article/details/85415492