glCullFace & texture Y-inverted

     上个礼拜一直在调试一个texture Y-inverted的问题,本来以为是小case,没想到整了这么久,里面有很多隐藏的知识点,中途还请教了Alex,崩溃了。

      今天结张,写篇总结。

      问题是这样的,纹理渲染出来内外面反调(Y-inverted),尝试改变MTE_CULLMODE寄存器位,没有任何显示结果。我原本的想法是每个3D的物体都有front face和back face,纹理采样时逆时针扫描数据得到的是front face,顺时针扫描得到back face,那么强制修改MTE_CULLMODE位使每次纹理采样都逆时针扫描应该能得到正面的纹理显示。结果却什么都没有。失望。。。

      关于这个问题请教了Alex,他的原文回复如下

First, texturing has nothing to do with culling. If you want to draw a y-inverted texture, change your vertex y-coordinate to (1 oldYCoord).

Second, yes, each 3D object has both front face and back face. Then how to determine front face of an triangle? Says you have triangle with vertice v0->v1->v2. For the two faces of the triangle, the one fits in (v0v1v2->XYZ) the right-handed Cartesian coordinate is front; and your thumb points to front face direction (back face direction away from your thumb). A triangle is lit if its face direction points to camera. So, if you rotate a triangle and culling is disable, you will always see it because either front or back face will facing camera one after another. When culling is enabled, the face you culled will not shown even it faces camera. There are two simple ways to change direction: 1. glFrontFace(GL_CW) will change default counter clockwise to clockwise (left-handled), therefore you switch the face. 2. Submit your vertice in reverse sequence. Your test code has vertice in v0,v1,v2,v3. You can try v3,v2,v1,v0.

Third, GL_POLYGON is treated as multiple triangles in driver because most GPUs do not support POLYGON primitive rendering. Suppose there is no difference in rendering POLYGON regarding to culling.

      说的很清楚,camera的方向决定了纹理会不会被渲染出来,这是3D transform部分的操作,也是我的空缺。抽时间补习一下才好。

      glCullFace相关的opengl函数大概有这些:glEnable(GL_CULL_FACE);glCullFace(GL_FRONT/GL_BACK); glFrontFace(GL_CW/GL_CCW); 按照Alex所说,glFrontFace()使用不同的参数或者改变tex坐标次序(顺时针/逆时针)或者改变vertex坐标次序都可以使一个纹理y-inverted。现在pvr的driver改变坐标次序可以实现纹理翻转,glFrontFace的调用没有任何影响,比较了一下TG的code,发现glFrontFace的调用受到two sided lighting的影响,而且这个参数最后会被编译到fragment shader里,预想的是GPU里有一个类似MTE的寄存器可以直接控制,但是实际上shader最后是通过一个GPU的内部寄存器起作用的。有点复杂的哦,还没有彻底明白,这次理解到这里。

     还有一些opengl的函数调用很有意思,以前都是不熟的。比如下面的code可以手工创建并加载一个纹理。

     glGenTextures(1, &pixmapTexture);
     glBindTexture(GL_TEXTURE_2D, pixmapTexture);

     static GLubyte tex2[] = {
     0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 2, 2, 0, 0, 0,
     0, 0, 2, 0, 0, 2, 0, 0,
     0, 0, 0, 0, 0, 2, 0, 0,
     0, 0, 0, 0, 2, 0, 0, 0,
     0, 0, 0, 2, 0, 0, 0, 0,
     0, 0, 2, 2, 2, 2, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0 };

     GLubyte tex[64][3];
     GLint i, j;
     static int width=8, height=8;

     for (i=0;i<height;i++) {
      for (j=0;j<width;j++) {
         int p = i*width+j;
         if (tex2[(height-i-1)*width+j]) {
            tex[p][0] = 255;   tex[p][1] = 0;     tex[p][2] = 0;
         }
         else {
            tex[p][0] = 255;   tex[p][1] = 255;   tex[p][2] = 255;
         }
      }
   }

   glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0,
      GL_RGB, GL_UNSIGNED_BYTE, tex);
  
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

   注意最后纹理参数的设置很重要,如果没有正确设置可能导致纹理不能显示。

   还有一部分code是怎么给primitive贴图,两种方式,比较喜欢第二种方式,简洁明了。

   第一种:

   glBegin(GL_POLYGON)                                       

          glTexCoord2f(0.0, 0.0)                                         

          glVertex2f(-1.0, -1.0)                                           

          glTexCoord2f(1.0, 0.0)                                        

          glVertex2f(1.0, -1.0)                                           

          glTexCoord2f(1.0, 1.0)                                         

          glVertex2f(1.0, 1.0)                                            

          glTexCoord2f(0.0, 1.0)                                         

          glVertex2f(-1.0, 1.0)                                            

    glEnd()  

    第二种:

    static const GLfloat verts[][2] = {
      { -4, -4 },
      {  4, -4 },
      {  4,  4 },
      { -4,  4 }
    };

    static const GLfloat texs[][2] = {
      { 0, 0 },
      { 1, 0 },
      { 1, 1 },
      { 0, 1 }
    };

    glVertexPointer(2, GL_FLOAT, 0, verts);
    glTexCoordPointer(2, GL_FLOAT, 0, texs);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

 

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值