反走样

走样(Aliasing)是由于像素离散采样导致的锯齿、闪烁等问题。反走样技术通过混合像素颜色来平滑边缘。OpenGL中主要针对点、线条和面等进行反走样处理。

线条和点反走样

对点和线形图形元素进行反走样的代码如下所示。

code.vc#.net
// 启用平滑
Gl.glEnable(Gl.GL_LINE_SMOOTH);
Gl.glEnable(Gl.GL_POINT_SMOOTH);  // 设置最佳质量提示
Gl.glHint(Gl.GL_LINE_SMOOTH_HINT, Gl.GL_NICEST);
Gl.glHint(Gl.GL_POINT_SMOOTH_HINT, Gl.GL_NICEST);
// 启用混合(平滑必需)
Gl.glEnable(Gl.GL_BLEND);
Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
// 设置线宽和点大小
Gl.glLineWidth(1.5F);
Gl.glPointSize(3.0F);

多边形面反走样

对多边形面进行反走样的代码如下所示。

code.vc#.net
Gl.glEnable(Gl.GL_POLYGON_SMOOTH);
Gl.glHint(Gl.GL_POLYGON_SMOOTH_HINT, Gl.GL_NICEST);  // 多边形也需要启用混合
Gl.glEnable(Gl.GL_BLEND);
Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);

反走样示例

第3章绘制了直线段、矩形和圆等图形元素,本例在该例的基础上对各图形元素进行反走样,代码如下所示。

code.vc#.net
        private void button1_Click(object sender, EventArgs e)
        {
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
            Gl.glEnable(Gl.GL_LINE_SMOOTH);
            Gl.glEnable(Gl.GL_BLEND);
            Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
            Gl.glHint(Gl.GL_LINE_SMOOTH_HINT, Gl.GL_NICEST);
            Gl.glPushMatrix();
            Gl.glColor3d(1.0, 0.0, 0.0);
            Gl.glLineWidth(2);
            Gl.glBegin(Gl.GL_LINES);
                Gl.glVertex3d(5, 13, 0);
                Gl.glVertex3d(12, 5, 0);
            Gl.glEnd();
            Gl.glPopMatrix();
            Gl.glFinish();
            Gl.glDisable(Gl.GL_LINE_SMOOTH);
            Gl.glDisable(Gl.GL_BLEND);
            simpleOpenGlControl1.SwapBuffers();
        }
        private void button2_Click(object sender, EventArgs e)
        {
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
            Gl.glEnable(Gl.GL_LINE_SMOOTH);
            Gl.glEnable(Gl.GL_BLEND);
            Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
            Gl.glHint(Gl.GL_LINE_SMOOTH_HINT, Gl.GL_NICEST);
            Gl.glPushMatrix();
            Gl.glColor3d(0.0, 0.0, 1.0);
            Gl.glLineWidth(2);
            Gl.glBegin(Gl.GL_LINES);
                Gl.glVertex3d(-3, 5, 0);
                Gl.glVertex3d(-3, -5, 0);
                Gl.glVertex3d(-3, -5, 0);
                Gl.glVertex3d(3, -5, 0);
                Gl.glVertex3d(3, -5, 0);
                Gl.glVertex3d(3, 5, 0);
                Gl.glVertex3d(3, 5, 0);
                Gl.glVertex3d(-3, 5, 0);
            Gl.glEnd();
            Gl.glPopMatrix();
            Gl.glFinish();
            Gl.glDisable(Gl.GL_LINE_SMOOTH);
            Gl.glDisable(Gl.GL_BLEND);
            simpleOpenGlControl1.SwapBuffers();
        }
        private void button3_Click(object sender, EventArgs e)
        {
            float[] sngX=new float[52];
            float[] sngY=new float[52];
            float[] sngZ=new float[52];
            float sngAngStep, sngTemp;
            int intI;
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
            sngAngStep = (float)(6.2832 / 50);
            for(intI = 1;intI<=51;intI++)
            {
                sngTemp = sngAngStep * intI;
                sngX[intI] = (float)(8 * System.Math.Cos(sngTemp) + 0.0);
                sngY[intI] = (float)(8 * System.Math.Sin(sngTemp) + 0.0);
                sngZ[intI] = 0;
            }
            Gl.glLineWidth(2);
            Gl.glColor3f(0, 1, 0);
            Gl.glEnable(Gl.GL_LINE_SMOOTH);
            Gl.glEnable(Gl.GL_BLEND);
            Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
            Gl.glHint(Gl.GL_LINE_SMOOTH_HINT, Gl.GL_NICEST);
            Gl.glPushMatrix();
            for(intI = 1;intI<=50;intI++)
            {
                Gl.glBegin(Gl.GL_LINES);
                    Gl.glVertex3d(sngX[intI], sngY[intI], 0);
                    Gl.glVertex3d(sngX[intI + 1], sngY[intI + 1], 0);
                Gl.glEnd();
            }
            Gl.glPopMatrix();
            Gl.glFinish();
            Gl.glDisable(Gl.GL_LINE_SMOOTH);
            Gl.glDisable(Gl.GL_BLEND);
            simpleOpenGlControl1.SwapBuffers();
        }
        private void button4_Click(object sender, EventArgs e)
        {
            this.Dispose();
        }

运行代码,生成图形如图4-2所示。

Document Image
\[\]

图4-2 绘制图形并进行反走样