OpenGL蓝宝书源码学习(六)第三章——Smoother.cpp

混合功能--抗锯齿源码示例(二维图形)

// Smoother.cpp
// OpenGL SuperBible
// Demonstrates point and line antialiasing
// Program by Richard S. Wright Jr.
#include 
   
   
    
    	// OpenGL toolkit
#include 
    
    
     
     

#ifdef __APPLE__
#include 
     
     
      
      
#else
#define FREEGLUT_STATIC
#include 
      
      
       
       
#endif

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);
            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);
            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[])
	{
	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;
	}

      
      
     
     
    
    
   
   

此源码示例运用了混合的功能,展示了平滑像素的效果。对比两个效果图,明显毛刺被平滑了。


源码解析:

此示例实际上是使用点、线以及图元画了一幅星星、月亮和山脉的黑白画,通过开启平滑的功能实现图形的平滑

#define SMALL_STARS     100
#define MEDIUM_STARS     40
#define LARGE_STARS      15
     //定义了各种星星的数量

#define SCREEN_X        800
#define SCREEN_Y        600
//定义窗口大小

1、 void SetupRC()
    {
    M3DVector3f vVerts[SMALL_STARS];      
//
定义小星星的顶点

int i;

shaderManager.InitializeStockShaders();

//开始设置小星星的批次图元,并根据小星星的数量,循环设置星星的顶点坐标

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();

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();

    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 }; 

//根据上面的12个顶点,画相连的线带  P67

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

//设置月亮的位置坐标、半径和弧度

GLfloat x = 700.0f;    
   GLfloat y = 500.0f;
    GLfloat r = 50.0f;
    GLfloat angle = 0.0f;  

//月亮的绘制是使用34个三角形扇拼接而成,

 moonBatch.Begin(GL_TRIANGLE_FAN, 34);
   
//初始化坐

 int nVerts = 0;
    vVerts[nVerts][0] = x;
    vVerts[nVerts][1] = y;
   
vVerts[nVerts][2] = 0.0f;

//循环弧度值画圆(2.0f*3.141592f就是2π,即一个圆周)

for(angle = 0; angle < 2.0f * 3.141592f; angle += 0.2f) {

//设置批次图元的坐标(是拼接圆周的三角形的坐标),x和y的坐标等于初始坐标加上弧度的余弦值、弧度的正弦与半径的成绩(),并++三角形扇的个数。

           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();  

   glClearColor(0.0f, 0.0f, 0.0f, 1.0f );//设置背景的清除颜色是黑色
   }

三角形扇:可以看书理解一下三角形扇行程过程 p71

2、void ChangeSize(int w,int h)

在函数中设置投影模式是正投影,设置裁剪范围,在范围内的图形会被显示在屏幕上

viewFrustum.SetOrthographic(0.0f, SCREEN_X, 0.0f, SCREEN_Y, -1.0f, 1.0f);

3、void RenderScene(void)

    {        
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//设置所有将要渲染的批次图元的颜色都是白色,并选择着色器(平面着色器),提供投影矩阵。把所有批次图元提交给着色器

    GLfloat vWhite [] = { 1.0f, 1.0f, 1.0f, 1.0f };
    shaderManager.UseStockShader(GLT_SHADER_FLAT, viewFrustum.GetProjectionMatrix(), vWhite);
    
    glPointSize(1.0f);
//设置点的大小

    smallStarBatch.Draw();
            
    glPointSize(4.0f);
    mediumStarBatch.Draw();
    
    glPointSize(8.0f);
    largeStarBatch.Draw();
        
    moonBatch.Draw();

    glLineWidth(3.5);
//设置线宽

    mountainRangeBatch.Draw();
    
    moonBatch.Draw();


    glutSwapBuffers();
    }
  

4、void ProcessMenu(int value) //在main函数中创建的菜单栏的回调函数
    {
    switch(value)
        {
        case 1:
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//设置混合因子,注意在开启了混合之后,图形图元不但被平滑了,颜色的白色也变暗了
            glEnable(GL_BLEND);  //开启混合模式
            glEnable(GL_POINT_SMOOTH);  //开启点抗锯齿(平滑)
            glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
            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:
            glDisable(GL_BLEND);
            glDisable(GL_LINE_SMOOTH);
            glDisable(GL_POINT_SMOOTH);
            break;

  default:
            break;
        }

//触发重绘(RenderScene)

 glutPostRedisplay();
    }

小结

抗锯齿(平滑)功能其实是混合功能的一个用途,在开启平滑功能前,要开启混合功能,关闭同样如此。此示例展示2维图形,在ChangeSize方法中设置了正投影的模式。我觉得其中要理解的地方是“月亮”的绘制,它应用了三角形扇的拼接,要理解顶点连接的顺序以及根据圆周的弧度值与弧长来判断顶点的坐标。再就是应用了平面着色器,需要给着色器提供一个投影矩阵。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: OpenGL蓝宝书PDF是指《OpenGL超级宝典》一书的电子版本,主要介绍了OpenGL图形学编程的基础知识和开发技巧。 OpenGL是一种跨平台的图形库,可以用于开发高性能的2D和3D图形应用程序。《OpenGL超级宝典》是一本经典的OpenGL教材,适合初学者和有一定OpenGL基础的开发者学习和参考。 这本书的PDF版本提供了一种便捷的阅读方式,可以随时随地通过电脑、平板或手机进行学习。相比于传统的纸质书籍,PDF版本的《OpenGL超级宝典》具有以下优势: 1. 可随时复制和搜索:PDF格式的书籍可以方便地进行复制和搜索,使得我们可以快速找到我们需要的内容,并方便地进行引用和参考。 2. 纸质书籍的替代品:PDF版本的书籍不占用实体空间,而且可以通过电子设备随时携带,方便在任何时间、任何地点进行学习和阅读。 3. 交互性强:PDF格式的书籍还可以添加书签、注释和标记,方便读者进行个性化的标记和笔记,更好地帮助记忆和理解。 总之,《OpenGL超级宝典》PDF版本是一种便捷、高效的学习OpenGL图形学编程的工具,通过这本书,读者可以系统地学习OpenGL的基础知识和开发技巧,从而提高自己在图形学编程领域的能力。 ### 回答2: OpenGL蓝宝书是一本关于OpenGL编程的经典教材,适合初学者和有一定编程基础的开发者。本书全面介绍了OpenGL的基础知识和常用编程技巧,并提供了大量的代码示例和实践项目。 这本书的PDF版本提供了方便的电子阅读方式,读者可以随时随地学习和实践OpenGL编程。使用PDF格式的优点是可以根据需要进行搜索、标注、复制和打印,在学习过程中方便查阅和注释,提高学习效率。 《OpenGL蓝宝书》的内容涵盖了OpenGL的基础知识,包括顶点和片元着色器、图元绘制、纹理映射、新的OpenGL特性等。此外,该书还介绍了OpenGL的高级技术,如光照、阴影、透明度、几何着色器等,帮助读者掌握更复杂的图形渲染技术。 这本书对于学习OpenGL编程的人来说是一部非常有价值的参考资料。它通过清晰的逻辑结构和易于理解的语言,帮助读者理解和掌握OpenGL的核心概念和编程技巧。同时,书中提供的示例代码和实践项目可以帮助读者巩固所学知识,并进一步探索OpenGL的应用。 总的来说,《OpenGL蓝宝书》的PDF版本是一种方便快捷的学习OpenGL编程的方式,可以满足读者在不同场合和需求下的学习和实践需求。无论是初学者还是有一定经验的开发者,都可以从中获得宝贵的知识和经验。 ### 回答3: OpenGL蓝宝书是一本经典的OpenGL编程指南,全书详尽地介绍了OpenGL的基础知识和编程技巧。这本书的完整版可以在网上找到PDF格式的电子书。通过阅读OpenGL蓝宝书,我们可以了解到OpenGL的底层原理、渲染管线以及各种常用的绘图和渲染技术。 OpenGL是一种跨平台的图形编程接口,它可以用于开发2D和3D图形应用程序。蓝宝书从基础概念开始,逐步介绍OpenGL的各个方面,包括顶点缓冲对象、着色器、纹理映射、光照等。通过例子和代码实践,读者可以深入理解OpenGL的工作原理,并学会如何使用OpenGL进行图形渲染。 OpenGL蓝宝书的PDF版本提供了便捷的学习方式。电子版本便于阅读和搜索,可以随时随地进行学习。同时,通过电子书的书签和目录功能,读者可以方便地定位到自己感兴趣的章节和内容。此外,电子书的PDF格式可以在多个设备上使用,如电脑、平板电脑和手机等。 总之,OpenGL蓝宝书PDF是一本非常有价值的OpenGL学习资料,它为初学者提供了一个系统而又详细的学习路径,帮助读者深入理解OpenGL的基础知识和编程技巧。无论是对于想要学习图形编程的人来说,还是对于已经对OpenGL有一定了解的开发者来说,这本书都是一本非常值得阅读的指南。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值