多边形常见操作

android api sample中的region 操作如下图:

opengl  模板测试的几个例子_opengl

本文基于opengl 的stencil buffer 实现这几种多边形运算。

OpenGL 模板测试实现

如下图:

opengl  模板测试的几个例子_opengl_02

 如上图,

Source为原始半透明重叠多边形绘制效果,重叠部分因为融合的缘故 有增强效果。

Union  联合操作,需保证每个像素 当且仅当只属于一个多边形,为此通过模板测试实现的具体思路:

  1. 用0x00 清除模板缓冲区,开启模板测试

  2. 写模板缓冲区,同时进行模板测试,同时写颜色缓冲区:保证只有模板值为0的片源可以通过模板测试,而且通过模板测试后 模板值加1 操作。

 

Difference 做差操作,是两个矩形相减效果,顺序无关,具体实现:

  1. 0x00 清除模板缓冲区

  2. 禁止颜色缓冲区写入,禁止模板测试,画任意一个矩形,将模板值加1 操作。此时末班缓冲区中第一个矩形绘制区域为mask区域,该区域内不能绘图。

  3. 开启模板测试,只能在模板值为0x00的地方绘图,画第二个矩形,模板测试通过后模板值加1。

XOr 异或操作,两个矩形相交的区域不显示,不相交的区域显示,具体思路:

  1. 0x00 清除模板缓冲区,

  2. 禁掉模板测试,禁掉颜色缓冲区写入,将模板值加1操作,绘制两个矩形,相交区域的模板值为2,其他矩形区域模板值为1。

  3. 开启模板测试,允许写入颜色缓冲区,测试条件为模板值等于1,模板值为8位,此时掩码为0x01,二进制为00000001。绘制两个矩形。模板测试通过后将模板值置为0。

Intersection 相交操作,只显示两个矩形相交区域,具体思路:

  1. 0x00 清除模板缓冲区,

  2. 禁掉模板测试,禁掉颜色缓冲区写入,将模板值加1操作,绘制两个矩形,相交区域的模板值为2,其他矩形区域模板值为1。

  3. 开启模板测试,允许写入颜色缓冲区,测试条件为模板值等于2,模板值为8位,此时掩码为0x03,二进制为00000011。绘制任意一个矩形。模板测试通过后将模板值置为0。


GLUT框架下实现:

[cpp] view plain copy opengl  模板测试的几个例子_opengl_03opengl  模板测试的几个例子_opengl_04

  1. <span style="font-size:12px;">// @module:       stencil render  

  2. // @file:       opacityRectRender.cpp  

  3. // @author:     peteryfren  

  4. // @date:       2013/3/28  

  5. // @version:    1.0  

  6. // @desc:       通过模板缓冲区实现半透明矩形的常见操作。  

  7.   

  8. #include <Windows.h>  

  9. #include <GL/glut.h>  

  10.   

  11. #pragma comment(lib,"glut32.lib")  

  12. #pragma comment(lib,"glu32.lib")  

  13. #pragma comment(lib,"opengl32.lib")  

  14.   

  15. #include <stdio.h>  

  16. #include <string.h>  

  17. #include <stdlib.h>  

  18. #include <assert.h>  

  19. #include <time.h>  

  20. #include <math.h>  

  21.   

  22. const int windowWidth = 256, windowHeight = 256;  

  23.   

  24. typedef void (*opacityLogicRender)(const intconst int);  

  25. opacityLogicRender my_opacityLogicRender;  

  26.   

  27.   

  28. GLenum checkForError(char *loc)  

  29. {  

  30.     GLenum errCode;  

  31.     const GLubyte *errString;  

  32.   

  33.     if ((errCode = glGetError()) != GL_NO_ERROR)  

  34.     {  

  35.         errString = gluErrorString(errCode);  

  36.         printf("OpenGL error: %s", errString);  

  37.   

  38.         if (loc != NULL)  

  39.         {  

  40.             printf("(%s)", loc);  

  41.         }  

  42.         printf("\n");  

  43.     }  

  44.   

  45.     return errCode;  

  46. }  

  47. void opacitySourceRender(int width, int height)  

  48. {  

  49.     // one way to solve this in generic OpenGL is to   

  50.     //      fill the frame buffer with your desired alpha channel,   

  51.     // switch the blending mode to glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA)  

  52.     //      and draw the rectangles.   

  53.     glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);  

  54.   

  55.     float tileVertices[] = {0, height / 2, width, height / 2, width, height * 3 / 4, 0, height * 3 / 4};   

  56.     glColor4f(1, 0, 0, 0.5);  

  57.     glVertexPointer(2, GL_FLOAT, 0, tileVertices);  

  58.     glEnableClientState(GL_VERTEX_ARRAY);  

  59.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);  

  60.     glColor4f(1, 1, 1, 1);  

  61.   

  62.     float tileVertices1[] = {width / 4, 0, width / 2, 0, width / 2, height, width / 4, height};   

  63.     glColor4f(1, 0, 0, 0.5);  

  64.     glVertexPointer(2, GL_FLOAT, 0, tileVertices1);  

  65.     glEnableClientState(GL_VERTEX_ARRAY);  

  66.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);  

  67.     glColor4f(1, 1, 1, 1);  

  68. }  

  69.   

  70. void opacityRectDifferenceRender(int width, int height)  

  71. {  

  72.     glEnable(GL_STENCIL_TEST);  

  73.   

  74.     // draw mask area  

  75.     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);  

  76.     glStencilFunc(GL_ALWAYS, 0, 0xFF);          // 禁模板测试  

  77.     glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);     // 模板值加1  

  78.   

  79.     glColor4f(1, 0, 0, 0.1);  

  80.     float tileVertices[] = {0, height / 2, width, height / 2, width, height * 3 / 4, 0, height * 3 / 4};  

  81.     glColor4f(1, 0, 0, 0.5);  

  82.     glVertexPointer(2, GL_FLOAT, 0, tileVertices);  

  83.     glEnableClientState(GL_VERTEX_ARRAY);  

  84.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);  

  85.   

  86.     //static unsigned char data[windowWidth*windowHeight];  

  87.     //glReadPixels(0, 0, windowWidth, windowHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, data);  

  88.     //SaveFileGrayBMP("stencil.bmp", data, windowWidth,  windowHeight);  

  89.   

  90.     // draw main area  

  91.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);  

  92.     glStencilFunc(GL_EQUAL, 0x00, 0x01);    // 只能在模板为0的地方绘图  

  93.     glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);   

  94.   

  95.     glColor4f(1, 0, 0, 0.5);  

  96.     float tileVertices1[] = {width / 4, 0, width / 2,0, width / 2, height, width / 4, height};   

  97.     glVertexPointer(2, GL_FLOAT, 0, tileVertices1);  

  98.     glEnableClientState(GL_VERTEX_ARRAY);  

  99.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);  

  100.     glColor4f(1, 1, 1, 1);  

  101.   

  102.     glDisable(GL_STENCIL_TEST);  

  103. }  

  104.   

  105. void opacityRectXorRender(int width, int height)  

  106. {  

  107.     glEnable(GL_STENCIL_TEST);  

  108.   

  109.     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);  

  110.   

  111.     // draw mask area   

  112.     glStencilOp(GL_INCR, GL_INCR, GL_INCR);  

  113.     glStencilFunc(GL_ALWAYS, 0x00, 0xFF);       // 禁用模板  

  114.   

  115.     float tileVertices[] = {0, height / 2, width, height / 2, width, height * 3 / 4, 0, height * 3 / 4};  

  116.     glColor4f(1, 0, 0, 0.5);  

  117.     glVertexPointer(2, GL_FLOAT, 0, tileVertices);  

  118.     glEnableClientState(GL_VERTEX_ARRAY);  

  119.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);  

  120.   

  121.     glColor4f(1, 0, 0, 0.5);  

  122.     float tileVertices1[] = {width / 4,0, width / 2, 0, width / 2, height, width / 4, height};   

  123.     glVertexPointer(2, GL_FLOAT, 0, tileVertices1);  

  124.     glEnableClientState(GL_VERTEX_ARRAY);  

  125.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);  

  126.     glColor4f(1, 1, 1, 1);  

  127.   

  128.     //static unsigned char data[windowWidth*windowHeight];  

  129.     //glReadPixels(0, 0, windowWidth, windowHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, data);  

  130.     //SaveFileGrayBMP("stencil.bmp", data, windowWidth,  windowHeight);  

  131.   

  132.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);  

  133.     glStencilFunc(GL_EQUAL, 0x01, 0x01);        // 模板值为1的区域才绘制  

  134.     glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);     // 用0替换当前值  

  135.   

  136.     glColor4f(1, 0, 0, 0.5);  

  137.     glVertexPointer(2, GL_FLOAT, 0, tileVertices);  

  138.     glEnableClientState(GL_VERTEX_ARRAY);  

  139.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);  

  140.     glColor4f(1, 1, 1, 1);  

  141.   

  142.     glColor4f(1, 0, 0, 0.5);  

  143.     glVertexPointer(2, GL_FLOAT, 0, tileVertices1);  

  144.     glEnableClientState(GL_VERTEX_ARRAY);  

  145.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);  

  146.     glColor4f(1, 1, 1, 1);  

  147.   

  148.     glDisable(GL_STENCIL_TEST);  

  149. }  

  150.   

  151. void opacityRectIntersectRender(int width, int height)  

  152. {  

  153.     glEnable(GL_STENCIL_TEST);  

  154.   

  155.     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);  

  156.   

  157.     // draw mask area   

  158.     glStencilOp(GL_INCR, GL_INCR, GL_INCR);  

  159.     glStencilFunc(GL_ALWAYS, 0x00, 0xFF);       // 禁用模板  

  160.   

  161.     float tileVertices[] = {0, height / 2, width, height / 2, width, height * 3 / 4, 0, height * 3 / 4};  

  162.     glColor4f(1, 0, 0, 0.5);  

  163.     glVertexPointer(2, GL_FLOAT, 0, tileVertices);  

  164.     glEnableClientState(GL_VERTEX_ARRAY);  

  165.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);  

  166.   

  167.     glColor4f(1, 0, 0, 0.5);  

  168.     float tileVertices1[] = {width / 4,0, width / 2, 0, width / 2, height, width / 4, height};   

  169.     glVertexPointer(2, GL_FLOAT, 0, tileVertices1);  

  170.     glEnableClientState(GL_VERTEX_ARRAY);  

  171.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);  

  172.     glColor4f(1, 1, 1, 1);  

  173.   

  174.     //static unsigned char data[windowWidth*windowHeight];  

  175.     //glReadPixels(0, 0, windowWidth, windowHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, data);  

  176.     //SaveFileGrayBMP("stencil.bmp", data, windowWidth,  windowHeight);  

  177.   

  178.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);  

  179.     glStencilFunc(GL_EQUAL, 0x02, 0x03);        // 模板值为2的区域才绘制 掩码0000 0011  

  180.     glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);  

  181.   

  182.     glColor4f(1, 0, 0, 0.5);  

  183.     glVertexPointer(2, GL_FLOAT, 0, tileVertices1);  

  184.     glEnableClientState(GL_VERTEX_ARRAY);  

  185.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);  

  186.     glColor4f(1, 1, 1, 1);  

  187.   

  188.     glDisable(GL_STENCIL_TEST);  

  189. }  

  190.   

  191. void opacityRectUnionRender(int width, int height)  

  192. {  

  193.     // 模板缓冲区就一个字节  

  194.   

  195.     glEnable (GL_STENCIL_TEST);       

  196.   

  197.     // glStencilFunc(GL_ALWAYS,0,0xFF); // 禁用模板测试  

  198.   

  199.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);    // 开启写入颜色缓冲区  

  200.   

  201.     // fail = KEEP  模版测试失败后保持模板缓冲区中值 不变  

  202.     // zfail =  KEEP 深度测试失败后保持模版缓冲区中值 不变  

  203.     // zpass = INCR 深度测试通过后对模版缓冲区中值 加1操作  

  204.     glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);       

  205.   

  206.     // glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);  

  207.   

  208.     // func = EQUAL 只有与参考值相等才能通过模版测试  

  209.     // ref = 0x00   参考值  

  210.     // mask = 0x01  只比较最低位  

  211.     glStencilFunc(GL_EQUAL, 0x0, 0x1);  // 开启模板测试  

  212.   

  213.     glEnable (GL_BLEND);        // 开启混合  

  214.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  

  215.   

  216.     // sfactor = 1 - dstA  

  217.     // dfactor = dstA  

  218.     // glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);  

  219.   

  220.     float tileVertices[] = {0, height / 2, width, height / 2, width, height * 3 / 4, 0, height * 3 / 4};  

  221.     glColor4f(1, 0, 0, 0.5);  

  222.     glVertexPointer(2, GL_FLOAT, 0, tileVertices);  

  223.     glEnableClientState(GL_VERTEX_ARRAY);  

  224.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);  

  225.   

  226.     glColor4f(1, 0, 0, 0.5);  

  227.     float tileVertices1[] = {width / 4,0, width / 2, 0, width / 2, height, width / 4, height};   

  228.     glVertexPointer(2, GL_FLOAT, 0, tileVertices1);  

  229.     glEnableClientState(GL_VERTEX_ARRAY);  

  230.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);  

  231.     glColor4f(1, 1, 1, 1);  

  232.   

  233.     //static unsigned char data[windowWidth*windowHeight];  

  234.     //glReadPixels(0, 0, windowWidth, windowHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, data);  

  235.     //SaveFileGrayBMP("stencil.bmp", data, windowWidth,  windowHeight);  

  236.   

  237.     glDisable (GL_STENCIL_TEST);  

  238. }  

  239. void init()  

  240. {  

  241.     printf("1. Source Render \n");  

  242.     printf("2. Difference Render \n");  

  243.     printf("3. Intersect Render \n");  

  244.     printf("4. Union Render \n");  

  245.     printf("5. Xor Render \n");  

  246.   

  247.     my_opacityLogicRender = opacitySourceRender;  

  248.     glClearColor(0.0, 0.0, 0.0, 1.0);   // 指定清理颜色值  

  249.     glClearStencil(0x00);               // 指定清理帧缓冲值  

  250.     glClearDepth(0.0);                  // 指定清理深度缓冲值  

  251.     glCullFace(GL_BACK);  

  252.     glEnable(GL_CULL_FACE);  

  253.     glShadeModel(GL_FLAT);  

  254.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);  

  255.     glEnable(GL_POLYGON_MODE);  

  256.   

  257.     //  glEnable(GL_BLEND);  

  258.     //  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  

  259. }  

  260. void Redraw(void)  

  261. {  

  262.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);  

  263.   

  264.     //  opacitySourceRender(windowWidth, windowHeight);  

  265.     //  opacityRectDifferenceRender(windowWidth, windowHeight);  

  266.     //  opacityRectIntersectRender(windowWidth, windowHeight);  

  267.     //  opacityRectUnionRender(windowWidth, windowHeight);  

  268.     //  opacityRectXorRender(windowWidth, windowHeight);  

  269.   

  270.     my_opacityLogicRender(windowWidth, windowHeight);  

  271.   

  272.     glutSwapBuffers();  

  273.     checkForError("swap");  

  274. }  

  275. void Reshape(int width, int height)  

  276. {  

  277.     glMatrixMode(GL_PROJECTION);  

  278.     glLoadIdentity();  

  279.     glOrtho(0.0f, (GLfloat)windowWidth, 0.0f, (GLfloat)windowHeight, -1.0f, 1.0f);  

  280.     glMatrixMode(GL_MODELVIEW);  

  281.     glLoadIdentity();  

  282.     glViewport(0, 0, windowWidth, windowHeight);  

  283. }  

  284. void mouse(int button, int state, int x, int y)  

  285. {  

  286.     if (state != GLUT_UP)  

  287.     {  

  288.         return;  

  289.     }  

  290.     switch (button)   

  291.     {  

  292.     case GLUT_LEFT_BUTTON:  

  293.   

  294.         glutPostRedisplay();  

  295.         break;  

  296.   

  297.     case GLUT_RIGHT_BUTTON:  

  298.   

  299.         glutPostRedisplay();  

  300.         break;  

  301.     }  

  302. }  

  303. void Keyboard(unsigned char key, int x, int y)  

  304. {  

  305.     if ('1' == key)  

  306.     {  

  307.         printf("1. Source Render \n");  

  308.         my_opacityLogicRender = opacitySourceRender;  

  309.     }  

  310.     else if ('2' == key)  

  311.     {  

  312.         printf("2. Difference Render \n");  

  313.         my_opacityLogicRender = opacityRectDifferenceRender;  

  314.     }  

  315.     else if ('3' == key)  

  316.     {  

  317.         printf("3. Intersect Render \n");  

  318.         my_opacityLogicRender = opacityRectIntersectRender;  

  319.     }  

  320.     else if ('4' == key)  

  321.     {  

  322.         printf("4. Union Render \n");  

  323.         my_opacityLogicRender = opacityRectUnionRender;  

  324.     }  

  325.     else if ('5' == key)  

  326.     {  

  327.         printf("5. Xor Render \n");  

  328.         my_opacityLogicRender = opacityRectXorRender;  

  329.     }  

  330.   

  331.   

  332.     glutPostRedisplay();  

  333. }  

  334. int main(int argc, char *argv[])  

  335. {  

  336.     //  glutInit(&argc, argv);  

  337.     //  glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_STENCIL);  

  338.     //   

  339.     //  glutInitWindowSize(windowWidth, windowHeight);  

  340.     //  glutCreateWindow("Region");  

  341.     //   

  342.     //  // set up world space to screen mapping  

  343.     //  glMatrixMode(GL_PROJECTION);  

  344.     //  glLoadIdentity();  

  345.     //  glOrtho(0.0f, (GLfloat) windowWidth, 0.0f, (GLfloat) windowHeight, -1.0f, 1.0f);  

  346.     //  glMatrixMode(GL_MODELVIEW);  

  347.     //  glLoadIdentity();  

  348.     //  glViewport(0, 0, windowWidth, windowHeight);  

  349.     //   

  350.     //  glClearColor(1.0, 1.0, 1.0, 1.0);  

  351.     //  glutDisplayFunc(Redraw);  

  352.     //  glutReshapeFunc(Reshape);  

  353.     //  glutMouseFunc(Button);  

  354.     //  glutKeyboardFunc(Keyboard);  

  355.     //   

  356.     //  glEnable(GL_CULL_FACE);  

  357.     //   

  358.     //  glutMainLoop();  

  359.     glutInit(&argc, argv);  

  360.     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);  

  361.     glutInitWindowPosition(100, 100);  

  362.     glutInitWindowSize(windowWidth, windowHeight);  

  363.     glutCreateWindow("Region");  

  364.     init();  

  365.   

  366.     glutDisplayFunc(Redraw);  

  367.     glutReshapeFunc(Reshape);  

  368.     glutMouseFunc(mouse);  

  369.     glutKeyboardFunc(Keyboard);  

  370.     glutMainLoop();  

  371.   

  372.     return 0;  

  373. }</span>  

参考

1. opengl 模板测试理论:http://blog.csdn.net/xiajun07061225/article/details/7388417

2. glStencilFunc函数讲解:http://blog.csdn.net/doing5552/article/details/2297280

3. opencsg  http://www.opencsg.org/