• OpenGL模版小案例分析


    下面的案例通过模版实现三角形截取的功能,代码如下:

    void draw(){
     GLuint programObject;
        
        GLfloat vVerticessmall[] = {  0.0f,  0.25f, 0.0f,
            -0.25f, -0.25f, 0.0f,
            0.25f, -0.25f, 0.0f
        };
        
        GLfloat vVertices[] = {  0.0f,  0.5f, 0.0f,
            -0.5f, -0.5f, 0.0f,
            0.5f, -0.5f, 0.0f
        };
        
        GLfloat vColorssmall[] = {  0.0f,  0.5f, 0.0f,1.0f,
            0.0f,  0.5f, 0.0f,1.0f,
            0.0f,  0.5f, 0.0f,1.0f,
        };
        GLfloat vColorsbig[] = {  0.5f,  0.5f, 0.0f,1.0f,
            0.5f,  0.5f, 0.0f,1.0f,
            0.5f,  0.5f, 0.0f,1.0f,
        };
        
            //这里视口的像素要和 分配的纹理大小一致,这样才可以绘制全图,
            //注意这里的屏幕大小是以 纹理大小 为准了,与手机屏幕大小没有关系
            glViewport(0,0,1136,640);
            glClearColor(1.0,1.0,1.0,1.0);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        
    
        
        char vShaderStr[] =
            "  attribute vec4 a_position;                      
    "
            "  attribute vec4 a_color;  
                           "
        
        "
    #ifdef GL_ES
    "
        "varying lowp vec4 v_fragmentColor;"
        "varying mediump vec2 v_texCoord;"
        "
    #else
    "
           " varying vec4 v_fragmentColor;"
        "varying vec2 v_texCoord;"
        "
    #endif
    "
        
        
            "     void main()   {                     
    "
            "       gl_Position =  a_position;                           
    "
             "          
    "
        "              v_fragmentColor=  a_color ;     
    "
            "        }                                
    ";
            //片段着色器
            //写入的这个变量将被写入颜色缓冲区
            char fShaderStr[] =
            "                          
    "
            "                           
    "
            "
    #ifdef GL_ES
    "
             "precision lowp float;"
            " 
    #endif
    "
        
            " varying vec4 v_fragmentColor; 
    "
            "                          
    "
            "void main()                                  
    "
            "{                                            
    "
            "   gl_FragColor = v_fragmentColor ;  
    "
            "}                                            
    ";
        
        
        
             programObject= esLoadProgram ( vShaderStr, fShaderStr );
             glUseProgram ( programObject );
             // glEnable(GL_DEPTH_TEST);
             glEnable(GL_STENCIL_TEST);
        
        
        
         s_layer++;
         //左移s_layer位,一个模版点8位的话,最多可以移动8次
         GLint mask_layer = 0x1 << s_layer;
         //得到前一位,比如如果s_layer=100,那么mask_layer_l=011
         GLint mask_layer_l = mask_layer - 1;
         //两个相与,得到 111
         _mask_layer_le = mask_layer | mask_layer_l;
       
        /*
         设置模板缓冲区的写入掩码:
         只允许mask位被写入
         glStencilMask控制模板平面中各个位的写入。 掩码的最低有效n位,其中n是模板缓冲区中的位数,指定掩码。 只要出现一个1,模板缓冲区中的相应位就可写。 如果出现0,则该位被写保护。 最初,所有位都被启用以进行写入。
         */
         //这个方法很关键,控制被写入的位数,比如mask_layer=10,那么只能在第二位写入数据,其余的不动
         glStencilMask(mask_layer);
        
         glStencilFunc(GL_NEVER, mask_layer, mask_layer);
         glStencilOp(GL_REPLACE , GL_KEEP, GL_KEEP);
        /*****************屏蔽的部分***********************/
       //glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0,vVertices);
    //    glEnableVertexAttribArray ( 0 );
    //    glVertexAttribPointer ( 1, 4, GL_FLOAT, GL_FALSE, 0, vColorsbig );
    //    glEnableVertexAttribArray ( 1 );
    //
    //    glDrawArrays ( GL_TRIANGLES, 0, 3 );
        
        
        
         //再次向左移动一位
         s_layer++;
         mask_layer = 0x1 << s_layer;
         mask_layer_l = mask_layer - 1;
         _mask_layer_le = mask_layer | mask_layer_l;
        
         //比如如果是100,那么就只能向第三位写入数据
         glStencilMask(mask_layer);
     
         glStencilFunc(GL_NEVER,0xFF, 0xFF);
         glStencilOp(GL_REPLACE , GL_KEEP, GL_KEEP);
        
         // 绘制小三角形
        //通过绘制,因为之前设置的Never,所以这次只是替换mask_layer到模版缓冲区,因为之前设置了 glStencilMask
        //所以只能向数字为1的地方写入,如果mask_layer=100,那么只能吧1写入到第三位
        glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVerticessmall );
        glEnableVertexAttribArray ( 0 );
        glVertexAttribPointer ( 1, 4, GL_FLOAT, GL_FALSE, 0, vColorssmall );
        glEnableVertexAttribArray ( 1 );
        glDrawArrays ( GL_TRIANGLES, 0, 3 );
        //这里的条件是满足全部的值,比如111
        glStencilFunc(GL_EQUAL, _mask_layer_le,_mask_layer_le);
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        //绘制大三角形
        glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0,vVertices);
        glEnableVertexAttribArray ( 0 );
        glVertexAttribPointer ( 1, 4, GL_FLOAT, GL_FALSE, 0, vColorsbig );
        glEnableVertexAttribArray ( 1 );
        glDrawArrays ( GL_TRIANGLES, 0, 3 );
    
       
         s_layer--;
         s_layer--;
         glDisable(GL_STENCIL_TEST);
        
    
    }

    运行程序,发现什么也没绘制

    然后把标红的屏蔽代码打开,运行,绘制如图所示:

    分析原因:

    大部分代码都有注释,简单说一下:

    通过上面代码的运行,_mask_layer_le的二进制数最终为00000011,也就是绘制的时候,模版缓冲区的每一像素点的值为00000011,才能运行继续绘制,如果屏蔽掉那段代码,那么模版缓冲区中将只有00000000和00000010的数据,没有符合条件的,所以没有绘制出来,反之,会使模版缓冲区中一部分数据为00000011,所以这部分三角形绘制了出来

  • 相关阅读:
    【原创】极简的软件功能自动化测试
    重温归并排序
    vue中嵌入echarts关系图
    KDE 应用设置开机自启
    教大聪明学Linux
    支持Windows \Linux\Mac 平台制作系统启动盘的软件
    Linux命令man文档改为中文
    在Linux上使用企业微信提供的API发送信息给成员
    数字的放重新放置 #abc>bac #取数字 / % * #三步取
    frp内网穿透
  • 原文地址:https://www.cnblogs.com/xiaonanxia/p/9414193.html
Copyright © 2020-2023  润新知