glCullFace & texture Y-inverted

本文探讨了3D渲染中遇到的纹理Y-inverted问题,分析了如何通过改变顶点Y坐标、调整纹理坐标顺序及使用OpenGL函数来解决此问题,并提供了具体的代码示例。

     上个礼拜一直在调试一个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);

#include&lt;stdio.h&gt; #include&lt;stdlib.h&gt; #include&lt;gl/glaux.h&gt; #include&lt;GL/glut.h&gt; #include&quot;../../wgGameLib03/dms/FileImage.h&quot; #include&quot;../../wgGraphLib/GraphElemenfs.h&quot; GLint iWidth, iHeight, iGomponents.h; GLenum eFormat; GLfloat xRot,yRot; GLfloat noLight[4]={0.0f,0.0f,0.0f,1.0f}; GLfloat ambientLight[4]={0.3f,0.3f,0.3f,0.2f}; GLfloat brightLight[4]={1.0f,1.0f,1.0f,0.3f}; static GLfloat lightPos[]={5.0f,5.0f,5.0f,1.0f}; void Init() { glClearColor(0.0f,0.0f,0.0f,1.0f); glCullFace(GL_BACK); glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glLigntModelfv(GL_LIGHT_MODEL_AMBIENT,noLight); glLightfv(GL_LIGHTO,GL_AMBIENT,ambientLight); glLightfv(GL_LIGHTO,GL_DIFFUSE,diffuseLight); glLightfv(GL_LIGHTO,GL_SPECULAR,brightLight); glLightfv(GL_LIGHTO,GL_POSITION,lightPos); glEnable(GL_COLOR_MATERIAL); glColorMateriali(GL_FRONT,GL_AMBIENT_AND_DIFFUSE); glMaterialfv(GL_FRONT,GL_SPECULAR,brightLight); glMateriali(GL_FRONT,GL_SHININESS,30); glPixelStorei(GL_UNPACK_ALIGHMENT,1); dms::FileImage image(&quot;stone.jpg&quot;); if(image.data()) { glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,image.width(),image.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,image.data()); //glTexImage2D(GL_TEXTURE_2D,0,iComponents,iWidth,iHeight,0,eFormat,GL_UNSIGNED_BYTE,pImage); free(image.data()); } float colorl[4]={1.0,0.1,0.1,1.0}; glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_BLEND); glEnable(GL_TEXTURE_2D); } void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); float vertices[5][3]={{0.0f,0.8f,0.0f}, {-0.50f,0.0f,-0.50f}, {0.5f,0.0f,-0.5f}, {0.50f,0.0f,0.50f}}; float normal[3]; glPushMatrix(); glTranslatef(0.0f,-0.3f,-4.0f); if(xRot&gt;360.5f) { xRot=0.0f; } if(yRot&gt;360.5f) { yRot=0.0f; } glBotatef(xROt,1.0f,0.0f,0.0f); glRotatef(yRot,0.0f,1.0f,0.0f); xRot+=0.5f; yRot+=0.5f; glBegin(GL_TRIANGLES); glColor3f(1.0f,0.0f,0.0f); glNormal3f(0.0f,-1.0f,0.0f); glTexCoord2f(0.0f,1.0f); glVertex3fv(vertices[1]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[2]); glTexCoord2f(0.0f,1.0f); glVertex3fv(vertices[4]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[4]); glTexCoord2f(0.0f,0.0f); glVertex3fv(vertices[3]); glTexCoord2f(0.0f,1.0f); glVertex3fv(vertices[1]); glColor3f(0.0f,0.0f,1.0f); wgGetNormal(vertices[1],vertices[3],vertices[0],normal); glNormal3f(normal); glTexCoord2f(0.0f,0.0f); glVertex3fv(vertices[1]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[3]); glTexCoord2f(0.5f,0.5f); glVertex3fv(vertices[0]); glColor3f(0.0f,1.0f,1.0f); wgGetNormal(vertices[0],vertices[4],vertices[2],normal); glNormal3f(normal); glTexCoord2f(0.5f,0.5f); glVertex3fv(vertices[0]); glTexCoord2f(0.0f,0.0f); glVertex3fv(vertices[4]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[2]); glColor3f(1.0f,0.0f,1.0f); wgGetNormal(vertices[0],vertices[2],vertices[1],normal); glNormal3f(normal); glTexCoord2f(0.5f,0.5f); glVertex3fv(vertices[0]); glTexCoord2f(0.0f,0.0f); glVertex3fv(vertices[2]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[1]); glEnd(); glPopMatrix(); glutSwapBuffers(); } voidReshape(GLsizei w,GLsizei h) { if(h==0) h=1; glViewport(0,0,w,h); float fAspect=(GLfloat)w/(GLfloat)h; glMatrixMade(GL_PROJECTION); glLoadIdentity(); glutPostRedisplay(); } void TimerFunc(int value) { glutPostRedisplay(); glutTimerFunc(60,TimerFunc,1); } int main(int args,char *argv[]) { glutInit(&amp;args,argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(512,512); glutCreatWindow(&quot;example&quot;); glutDisplayFunc(display); glutReshapeFunc(Reshape); Init(); glutTimerFunc(50,TimerFunc,1); //tTexture glutMainLoop(); return 0; }
#include &quot;Cone.h&quot; Cone::Cone(std::string vs, std::string fs, std::string texName) :Object(vs, fs, texName) { } Cone::~Cone() { } void Cone::initData(DataParam *param) { dataParam = *param; GLfloat radius = dataParam.radius; GLuint longSegments = dataParam.longSegments; //GLuint latSegments = param-&gt;latSegments; GLfloat height = dataParam.height; //float fPhi = glm::pi&lt;float&gt;() / latSegments; //纬度上角度差:Phi float fTheta = (glm::pi&lt;float&gt;() * 2.0f) / longSegments; //经度上角度差:Theta //生成顶点数据 verticesSize = 2 * (longSegments + 2);// *sizeof(TextureColorVertex); vertices = new TextureColorVertex[verticesSize]; verticesSize *= sizeof(TextureColorVertex); int start = 0; //生成侧面数据 vertices[start].coordinate.x = 0; vertices[start].coordinate.y = height / 2.0f; vertices[start].coordinate.z = 0; vertices[start].texture.s = 0.5; vertices[start].texture.t = 0.5; vertices[start].color.r = vertices[start].color.g = vertices[start].color.b = 1.0f; ++start; for (int i = start; i &lt; start + longSegments + 1; i++) { vertices[i].coordinate.x = radius * cos(glm::pi&lt;float&gt;() * 2 - i * fTheta); vertices[i].coordinate.y = -height / 2.0f; vertices[i].coordinate.z = radius * sin(glm::pi&lt;float&gt;() * 2 - i * fTheta); vertices[i].texture.s = 0.5f + 0.5f * cos(glm::pi&lt;float&gt;() * 2 - i * fTheta); vertices[i].texture.t = 0.5f + 0.5f * sin(glm::pi&lt;float&gt;() * 2 - i * fTheta); vertices[i].color.r = vertices[i].color.g = vertices[i].color.b = 1.0f; } start += longSegments + 1; //生成下底顶点数据 vertices[start].coordinate.x = 0; vertices[start].coordinate.y = -height / 2.0f; vertices[start].coordinate.z = 0.0f; vertices[start].texture.s = 0.5f; vertices[start].texture.t = 0.5f; vertices[start].color.r = vertices[start].color.g = vertices[start].color.b = 1.0f; ++start; for (int i = start; i &lt; start + longSegments + 1; i++) { vertices[i].coordinate.x = radius * cos(i * fTheta); vertices[i].coordinate.y = -height / 2.0f; vertices[i].coordinate.z = radius * sin(i * fTheta); vertices[i].texture.s = 0.5f + 0.5f * cos(i * fTheta); vertices[i].texture.t = 0.5f + 0.5f * sin(i * fTheta); vertices[i].color.r = vertices[i].color.g = vertices[i].color.b = 1.0f; } createBuffer(sizeof(TextureColorVertex)); delete[]vertices; revolutionAngle = 0.0f; rotationAngle = 0.0f; revolutionSpeed = 0.1f; rotationSpeed = 0.5f; } void Cone::renderObject() { glBindVertexArray(VAO); GLint first = 0; glDrawArrays(GL_TRIANGLE_FAN, first, dataParam.longSegments + 2); first += dataParam.longSegments + 2; glDrawArrays(GL_TRIANGLE_FAN, first, dataParam.longSegments + 2); } void Cone::update(float dt) { revolutionAngle += revolutionSpeed; rotationAngle += rotationSpeed; model = glm::mat4(1.0f); model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(0.0f, 0.0f, 1.0f)); model = glm::translate(model, glm::vec3(0.0f, 4.0f, 0.0f)); model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(1.0f, 0.0f, 0.0f)); model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f)); } #pragma once #include &quot;Object.h&quot; class Cone :public Object { public: Cone(std::string vs, std::string fs, std::string texName = &quot;&quot;); ~Cone(); void initData(DataParam *param = nullptr); void renderObject(); void update(float dt); private: DataParam dataParam; }; #include &quot;Cube18.h&quot; Cube18::Cube18(std::string vs, std::string fs, std::string texName) :Object(vs, fs, texName) { } Cube18::~Cube18() { } void Cube18::initData(DataParam *param) { TextureColorVertex verticesData[] = { // positions // colors // texture coords //top glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(1.0f, 0.0f), //0 glm::vec3(0.5f, 0.5f, -0.5f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(1.0f, 1.0f), //1 glm::vec3(-0.5f, 0.5f, 0.5f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(0.0f, 0.0f), //2 glm::vec3(-0.5f, 0.5f, -0.5f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f), //3 //side glm::vec3(0.5f, -0.5f, 0.5f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(4.0f, 0.0f), //7// bottom right glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(4.0f, 1.0f), //6// top right glm::vec3(-0.5f, -0.5f,0.5f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(3.0f, 0.0f), //5// bottom left glm::vec3(-0.5f, 0.5f, 0.5f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(3.0f, 1.0f), //4// top left glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(2.0f, 0.0f), //8 glm::vec3(-0.5f, 0.5f, -0.5f), glm::vec3(1.0f, 0.0f, 1.0f), glm::vec2(2.0f, 1.0f), //9 glm::vec3(0.5f, -0.5f, -0.5f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f,0.0f), //10 glm::vec3(0.5f, 0.5f, -0.5f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(1.0f,1.0f), //11 glm::vec3(0.5f, -0.5f, 0.5f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 0.0f), //12 glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(0.0f, 1.0f), //13 //bottom glm::vec3(0.5f, -0.5f, -0.5f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(1.0f, 0.0f), //14 glm::vec3(0.5f, -0.5f, 0.5f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f), //15 glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(0.0f, 0.0f), //16 glm::vec3(-0.5f, -0.5f, 0.5f), glm::vec3(1.0f, 0.0f, 1.0f), glm::vec2(0.0f, 1.0f) //17 }; vertices = new TextureColorVertex[18]; verticesSize = sizeof(verticesData);//sizeof(TextureColorVertex) * 18; memcpy(vertices, verticesData, verticesSize); createBuffer(sizeof(TextureColorVertex)); revolutionAngle = 0.0f; rotationAngle = 0.0f; revolutionSpeed = 5.0f; rotationSpeed = 0.5f; } void Cube18::renderObject() { glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 4, 10); glDrawArrays(GL_TRIANGLE_STRIP, 14, 4); } void Cube18::update(float dt) { rotationAngle += rotationSpeed; model = glm::mat4(1.0f); model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f)); model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(1.0f, 1.0f, 1.0f)); model = glm::scale(model, glm::vec3(3.0f, 3.0f, 3.0f)); }#pragma once #include &quot;Object.h&quot; class Cube18 :public Object { public: Cube18(std::string vs, std::string fs, std::string texName = &quot;&quot;); ~Cube18(); void initData(DataParam *param = nullptr); void renderObject(); void update(float dt); }; #include &quot;Cylinder.h&quot; Cylinder::Cylinder(std::string vs, std::string fs, std::string texName) :Object(vs, fs, texName) { } Cylinder::~Cylinder() { } void Cylinder::initData(DataParam *param) { dataParam = *param; GLfloat radius = dataParam.radius; GLuint longSegments = dataParam.longSegments; GLfloat height = dataParam.height; float fTheta = (glm::pi&lt;float&gt;() * 2.0f) / longSegments; //经度上角度差:Theta //生成顶点数据 verticesSize = //计算顶点数量 vertices = //创建顶点数组 verticesSize *= sizeof(TextureColorVertex); TextureColorVertex * p = vertices; //生成侧面顶点数据,请补充代码 for (int i = 0; i &lt; (longSegments + 1); i++) { } int start = 2 * (longSegments + 1); //生成上底顶点数据,请补充代码 vertices[start].coordinate.x = ; vertices[start].coordinate.y = ; vertices[start].coordinate.z = ; vertices[start].texture.s = ; vertices[start].texture.t = ; vertices[start].color.r = ; vertices[start].color.g = ; vertices[start].color.b = ; ++start; for (int i = 0; i &lt; longSegments + 1; i++) { vertices[i + start].coordinate.x = ; vertices[i + start].coordinate.y = ; vertices[i + start].coordinate.z = ; vertices[i + start].texture.s = ; vertices[i + start].texture.t = ; vertices[i + start].color.r = ; vertices[i + start].color.g = ; vertices[i + start].color.b = ; } start += longSegments + 1; //生成下底顶点数据,请补充代码 vertices[start].coordinate.x = ; vertices[start].coordinate.y = ; vertices[start].coordinate.z = ; vertices[start].texture.s = ; vertices[start].texture.t = ; vertices[start].color.r = ; vertices[start].color.g = ; vertices[start].color.b = ; ++start; for (int i = 0; i &lt; longSegments + 1; i++) { vertices[i + start].coordinate.x = ; vertices[i + start].coordinate.y = ; vertices[i + start].coordinate.z = ; vertices[i + start].texture.s = ; vertices[i + start].texture.t = ; vertices[i + start].color.r = ; vertices[i].color.g = ; vertices[i].color.b = ; } createBuffer(sizeof(TextureColorVertex)); delete[]vertices; revolutionAngle = 0.0f; //补注释 rotationAngle = 0.0f; //补注释 revolutionSpeed = 5.0f; //补注释 rotationSpeed = 1.0f; //补注释 } void Cylinder::renderObject() { glBindVertexArray(VAO); GLint first = 0; glDrawArrays(GL_TRIANGLE_STRIP, first, (dataParam.longSegments + 1) * 2); first += (dataParam.longSegments + 1) * 2; glDrawArrays(GL_TRIANGLE_FAN, first, dataParam.longSegments +2); first += dataParam.longSegments + 2; glDrawArrays(GL_TRIANGLE_FAN,first, dataParam.longSegments + 2); } void Cylinder::update(float dt) { revolutionAngle += revolutionSpeed * dt; rotationAngle += rotationSpeed * dt * 3; model = glm::mat4(1.0f); model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(1.0f, 0.0f, 0.0f)); model = glm::translate(model, glm::vec3(0.0f, 0.0f,3.0f)); model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(0.0f, 0.0f,1.0f)); //model = glm::rotate(model, glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)); model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f)); }#pragma once #include &quot;Object.h&quot; class Cylinder :public Object { public: Cylinder(std::string vs, std::string fs, std::string texName = &quot;&quot;); ~Cylinder(); void initData(DataParam *param = nullptr); void renderObject(); void update(float dt); private: DataParam dataParam; }; #include &quot;Demo.h&quot; Demo::Demo() { cullMode = GL_BACK; frontFace = GL_CCW; enableCullFace = false; } Demo::~Demo() { } void Demo::setRenderParameter(bool enableCullFace, GLenum cullMode, GLenum frontFace) { this-&gt;enableCullFace = enableCullFace; this-&gt;cullMode = cullMode; this-&gt;frontFace = frontFace; } void Demo::beginRender() { if (enableCullFace) { glEnable(GL_CULL_FACE); } else { glDisable(GL_CULL_FACE); } glCullFace(cullMode); glFrontFace(frontFace); }#ifndef DEMO_H_ #define DEMO_H_ #include &lt;glad/glad.h&gt; class Demo { public: Demo(); ~Demo(); private: bool enableCullFace; GLenum cullMode; GLenum frontFace; protected: const char* vertexShaderSource; const char* fragmentShaderSource; public: virtual void setRenderParameter(bool enableCullFace = false, GLenum cullMode = GL_FRONT, GLenum frontFace = GL_CCW); virtual void beginRender(); virtual void render() = 0; virtual void update(float deltaTime) = 0; }; #endif #include &quot;Demo08.h&quot; #include &quot;TexturePool.h&quot; Demo08::Demo08(int scr_width, int scr_height) { screen_height = scr_height; screen_width = scr_width; } Demo08::~Demo08() { cleanUp(); } void Demo08::init() { TexturePool* textPool = TexturePool::getInstance(); TexturePool::getInstance()-&gt;addTexture(&quot;sun&quot;, &quot;./texture/sun.jpg&quot;); TexturePool::getInstance()-&gt;addTexture(&quot;earth&quot;, &quot;./texture/earth.jpg&quot;); TexturePool::getInstance()-&gt;addTexture(&quot;cube&quot;, &quot;./texture/container.jpg&quot;); TexturePool::getInstance()-&gt;addTexture(&quot;saturn&quot;, &quot;./texture/saturn.jpg&quot;); objects[0] = ; //定义立方体对象 objects[1] = ; //定义球对象 objects[2] = ; //定义圆柱对象 objects[3] = new Cone(&quot;star.vs&quot;, &quot;star.fs&quot;, &quot;saturn&quot;); //定义圆锥对象 objects[0]-&gt;initData(); DataParam earthParam = { 20,20,1.0f }; objects[1]-&gt;initData(&amp;earthParam); DataParam cylinderParam = { 20,20,1.0f,4.0f }; objects[2]-&gt;initData(&amp;cylinderParam); DataParam coneParam = { 10,10,1.0f,2.0f }; objects[3]-&gt;initData(&amp;coneParam); } void Demo08::cleanUp() { if (earth) { delete earth; } if (cube) { delete cube; } if (cylinder) { delete cylinder; } if (cone) { delete cone; } for (int i = 0; i &lt; 4; ++i) { if (objects[i]) { delete objects[i]; } } } void Demo08::update(float dt) //补注释 { for (int i = 0; i &lt; 4; ++i) { objects[i]-&gt;update(dt); //补注释 } } void Demo08::render() { glClearColor(0.2, 0.3, 0.2, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); beginRender(); glEnable(GL_DEPTH_TEST); // create transformations glm::mat4 view = glm::mat4(1.0f); glm::mat4 projection = glm::mat4(1.0f); view = glm::translate(view, glm::vec3(0.0f, 0.0f, -12.0f)); if (screen_height &lt;= 0 || screen_width &lt;= 0) { return; } //补注释 projection = glm::perspective(glm::radians(45.0f), (float)screen_width / (float)screen_height, 0.1f, 100.0f); for (int i = 0; i &lt; 4; ++i) { objects[i]-&gt;render(view, projection); } } void Demo08::setViewport(int width, int height) { screen_width = width; screen_height = height; }#pragma once #include &quot;Demo.h&quot; #include &quot;Cube18.h&quot; #include &quot;Sphere.h&quot; #include &quot;Cylinder.h&quot; #include &quot;Cone.h&quot; class Demo08 : public Demo { public: Demo08(int scr_width,int scr_height); ~Demo08(); private: Cube18* cube; Sphere* earth; Cylinder* cylinder; Cone* cone; Object* objects[4]; int screen_width; int screen_height; public: void render(); void update(float deltaTime); void init(); void cleanUp(); void setViewport(int width, int height); }; #include &lt;glad/glad.h&gt; #include &lt;GLFW/glfw3.h&gt; #include &lt;iostream&gt; #include &quot;Demo08.h&quot; unsigned int scr_width = 1200; unsigned int scr_height = 800; GLFWwindow* window; void framebuffer_size_callback(GLFWwindow* window, int width, int height); void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods); void processInput(GLFWwindow* window); void update(float dt); void render(); void init(); void cleanup(); bool enableCullFace = true; GLenum cullMode = GL_BACK; GLenum frontFace = GL_CCW; Demo08* demo08 = nullptr; int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X #endif window = glfwCreateWindow(scr_width, scr_height, &quot;Lab3-3&quot;, NULL, NULL); if (window == NULL) { std::cout &lt;&lt; &quot;Failed to create GLFW window&quot; &lt;&lt; std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSetKeyCallback(window, key_callback); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout &lt;&lt; &quot;Failed to initialize GLAD&quot; &lt;&lt; std::endl; return -1; } int nrAttributes; glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &amp;nrAttributes); std::cout &lt;&lt; &quot;Maximum nr of vertex attributes supported: &quot; &lt;&lt; nrAttributes &lt;&lt; std::endl; init(); double t = 0.5; while (!glfwWindowShouldClose(window)) { processInput(window); double dt = glfwGetTime() - t; t = glfwGetTime(); update(dt); render(); glfwSwapBuffers(window); glfwPollEvents(); } cleanup(); glfwTerminate(); return 0; } void cleanup() { if (demo08) { delete demo08; } } void init() { demo08 = new Demo08(scr_width, scr_height); demo08-&gt;setRenderParameter(enableCullFace, cullMode, frontFace); demo08-&gt;init(); } void update(float dt) { if (demo08) { demo08-&gt;update((float)dt); } } void render() { if (demo08) { demo08-&gt;render(); } } void processInput(GLFWwindow* window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } void framebuffer_size_callback(GLFWwindow* window, int width, int height) { scr_width = width; scr_height = height; glViewport(0, 0, width, height); } void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { // 判断按键是否被释放 if (action == GLFW_RELEASE) { } }#include &lt;glad/glad.h&gt; #include &quot;TexturePool.h&quot; #include &quot;Object.h&quot; Object::Object(std::string vs, std::string fs, std::string texName) { createShader(vs.c_str(), fs.c_str()); if (texName != &quot;&quot;) { texture = TexturePool::getInstance()-&gt;getTexture(texName); // activate shader shader-&gt;use(); shader-&gt;setInt(&quot;tex&quot;, 0); shader-&gt;setVec4(&quot;testColor&quot;, glm::vec4(255, 0, 0, 255)); } vertices = nullptr; indices = nullptr; stride = 0; } Object::~Object() { glDeleteVertexArrays(1, &amp;VAO); glDeleteBuffers(1, &amp;VBO); glDeleteBuffers(1, &amp;EBO); if (shader) { delete shader; } /*if (vertices) { delete[]vertices; }*/ } void Object::createShader(const char* vs, const char* fs) { if (shader) { delete shader; } shader = new Shader(vs, fs); } void Object::setTexture(std::string texName) { texture = TexturePool::getInstance()-&gt;getTexture(texName); } void Object::createBuffer(GLsizei stride, bool createEBO , GLenum ussage) { glGenVertexArrays(1, &amp;VAO); glGenBuffers(1, &amp;VBO); if (createEBO) { glGenBuffers(1, &amp;EBO); } glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, verticesSize, vertices, ussage); if (createEBO) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, indices, ussage); } this -&gt; stride = stride; updateDataBuffer(); } void Object::render(glm::mat4&amp; view, glm::mat4&amp; projection) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glBindVertexArray(VAO); shader-&gt;use(); shader-&gt;setMat4(&quot;model&quot;, model); shader-&gt;setMat4(&quot;view&quot;, view); shader-&gt;setMat4(&quot;projection&quot;, projection); renderObject(); } void Object::updateDataBuffer() { //position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(1 * sizeof(glm::vec3))); glEnableVertexAttribArray(1); // texture coord attribute glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(2 * sizeof(glm::vec3))); glEnableVertexAttribArray(2); }#pragma once #include &lt;glm/glm.hpp&gt; #include &lt;glm/gtc/matrix_transform.hpp&gt; #include &lt;glm/gtc/type_ptr.hpp&gt; #include &lt;string&gt; #include &quot;Shader.h&quot; typedef struct { glm::vec3 coordinate; glm::vec3 color; glm::vec2 texture; } TextureColorVertex; typedef struct { GLuint latSegments; GLuint longSegments; GLfloat radius; GLfloat height; }DataParam; class Object { public: Object(std::string vs, std::string fs, std::string texName = &quot;&quot;); virtual ~Object(); protected: Shader* shader; TextureColorVertex* vertices; GLushort * indices; GLuint indexCount; GLint verticesSize; GLuint indexSize; GLuint texture; GLuint VBO, VAO, EBO; protected: glm::mat4 model; float rotationSpeed; float revolutionSpeed; float rotationAngle; float revolutionAngle; glm::vec3 translation; GLsizei stride; void createBuffer(GLsizei stride,bool createEBO = false, GLenum ussage = GL_STATIC_DRAW); public: void createShader(const char* vs, const char* fs); virtual void initData(DataParam *param = nullptr) = 0; void setTexture(std::string texName); void render(glm::mat4&amp; view, glm::mat4&amp; projection); virtual void update(float dt) {} virtual void renderObject() = 0; virtual void updateDataBuffer(); }; #include &quot;Sphere.h&quot; Sphere::Sphere(std::string vs, std::string fs, std::string texName) :Object(vs,fs,texName ) { } Sphere::~Sphere() { } void Sphere::initData(DataParam *param) { GLfloat radius = param-&gt;radius; GLuint longSegments = param-&gt;longSegments; GLuint latSegments = param-&gt;latSegments; float fPhi = ; //纬度上角度差:Phi float fTheta = ; //经度上角度差:Theta //生成顶点数据,请补充代码 verticesSize = ; vertices = new TextureColorVertex[(longSegments + 1) * (latSegments + 1)]; //创建顶点数组 TextureColorVertex * p = vertices; for (GLuint i = 0; i &lt; latSegments + 1; i++) { float latitude = ; //纬度 for (GLuint j = 0; j &lt; longSegments + 1; j++) { float longitude = ; //经度 p-&gt;coordinate.x = ; p-&gt;coordinate.y = ; p-&gt;coordinate.z = ; p-&gt;color.r = ; p-&gt;color.g = ; p-&gt;color.b = ; p-&gt;texture.s = ; p-&gt;texture.t = ; p++; } } //生成索引数据 indexCount = ; //计算索引数量 indices = new GLushort[indexCount]; indexSize = indexCount * sizeof(GLushort); GLushort * pIdx = indices; for (GLuint i = 0; i &lt; latSegments + 1; i++) { for (GLuint j = 0; j &lt; longSegments + 1; j++) { //补代码 } } createBuffer(sizeof(TextureColorVertex),true); delete[]vertices; delete[]indices; revolutionAngle = 0.0f; //写注释 rotationAngle = 0.0f; //写注释 revolutionSpeed = 0.01f; //写注释 rotationSpeed = 0.5f; //写注释 } void Sphere::renderObject() { glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_SHORT, 0); } void Sphere::update(float dt) { revolutionAngle += revolutionSpeed; rotationAngle += rotationSpeed; model = glm::mat4(1.0f); model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(0.0f, 1.0f, 0.0f)); model = glm::translate(model, glm::vec3(5.0f,0.0f,0.0f)); model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(0.0f, 1.0f, 0.0f)); model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f)); } #pragma once //#ifndef SHADER_H //#define SHADER_H #include &lt;glad/glad.h&gt; #include &lt;glm/glm.hpp&gt; #include &lt;string&gt; #include &lt;fstream&gt; #include &lt;sstream&gt; #include &lt;iostream&gt; class Shader { public: unsigned int ID; Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr) { // 1. retrieve the vertex/fragment source code from filePath std::string vertexCode; std::string fragmentCode; std::string geometryCode; std::ifstream vShaderFile; std::ifstream fShaderFile; std::ifstream gShaderFile; // ensure ifstream objects can throw exceptions: vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); gShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { // open files vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); std::stringstream vShaderStream, fShaderStream; // read file&#39;s buffer contents into streams vShaderStream &lt;&lt; vShaderFile.rdbuf(); fShaderStream &lt;&lt; fShaderFile.rdbuf(); // close file handlers vShaderFile.close(); fShaderFile.close(); // convert stream into string vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); // if geometry shader path is present, also load a geometry shader if (geometryPath != nullptr) { gShaderFile.open(geometryPath); std::stringstream gShaderStream; gShaderStream &lt;&lt; gShaderFile.rdbuf(); gShaderFile.close(); geometryCode = gShaderStream.str(); } } catch (std::ifstream::failure e) { std::cout &lt;&lt; &quot;ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ&quot; &lt;&lt; std::endl; } const char* vShaderCode = vertexCode.c_str(); const char * fShaderCode = fragmentCode.c_str(); unsigned int vertex, fragment; // vertex shader vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &amp;vShaderCode, NULL); glCompileShader(vertex); checkCompileErrors(vertex, &quot;VERTEX&quot;); // fragment Shader fragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment, 1, &amp;fShaderCode, NULL); glCompileShader(fragment); checkCompileErrors(fragment, &quot;FRAGMENT&quot;); // if geometry shader is given, compile geometry shader unsigned int geometry; if (geometryPath != nullptr) { const char * gShaderCode = geometryCode.c_str(); geometry = glCreateShader(GL_GEOMETRY_SHADER); glShaderSource(geometry, 1, &amp;gShaderCode, NULL); glCompileShader(geometry); checkCompileErrors(geometry, &quot;GEOMETRY&quot;); } // shader Program ID = glCreateProgram(); glAttachShader(ID, vertex); glAttachShader(ID, fragment); if (geometryPath != nullptr) glAttachShader(ID, geometry); glLinkProgram(ID); checkCompileErrors(ID, &quot;PROGRAM&quot;); // delete the shaders as they&#39;re linked into our program now and no longer necessery glDeleteShader(vertex); glDeleteShader(fragment); if (geometryPath != nullptr) glDeleteShader(geometry); } // activate the shader // ------------------------------------------------------------------------ void use() { glUseProgram(ID); } // utility uniform functions // ------------------------------------------------------------------------ void setBool(const std::string &amp;name, bool value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); } // ------------------------------------------------------------------------ void setInt(const std::string &amp;name, int value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ void setFloat(const std::string &amp;name, float value) const { glUniform1f(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ void setVec2(const std::string &amp;name, const glm::vec2 &amp;value) const { glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &amp;value[0]); } void setVec2(const std::string &amp;name, float x, float y) const { glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y); } // ------------------------------------------------------------------------ void setVec3(const std::string &amp;name, const glm::vec3 &amp;value) const { glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &amp;value[0]); } void setVec3(const std::string &amp;name, float x, float y, float z) const { glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); } // ------------------------------------------------------------------------ void setVec4(const std::string &amp;name, const glm::vec4 &amp;value) const { glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &amp;value[0]); } void setVec4(const std::string &amp;name, float x, float y, float z, float w) { glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w); } // ------------------------------------------------------------------------ void setMat2(const std::string &amp;name, const glm::mat2 &amp;mat) const { glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &amp;mat[0][0]); } // ------------------------------------------------------------------------ void setMat3(const std::string &amp;name, const glm::mat3 &amp;mat) const { glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &amp;mat[0][0]); } // ------------------------------------------------------------------------ void setMat4(const std::string &amp;name, const glm::mat4 &amp;mat) const { glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &amp;mat[0][0]); } private: // utility function for checking shader compilation/linking errors. // ------------------------------------------------------------------------ void checkCompileErrors(GLuint shader, std::string type) { GLint success; GLchar infoLog[1024]; if (type != &quot;PROGRAM&quot;) { glGetShaderiv(shader, GL_COMPILE_STATUS, &amp;success); if (!success) { glGetShaderInfoLog(shader, 1024, NULL, infoLog); std::cout &lt;&lt; &quot;ERROR::SHADER_COMPILATION_ERROR of type: &quot; &lt;&lt; type &lt;&lt; &quot;\n&quot; &lt;&lt; infoLog &lt;&lt; &quot;\n -- --------------------------------------------------- -- &quot; &lt;&lt; std::endl; } } else { glGetProgramiv(shader, GL_LINK_STATUS, &amp;success); if (!success) { glGetProgramInfoLog(shader, 1024, NULL, infoLog); std::cout &lt;&lt; &quot;ERROR::PROGRAM_LINKING_ERROR of type: &quot; &lt;&lt; type &lt;&lt; &quot;\n&quot; &lt;&lt; infoLog &lt;&lt; &quot;\n -- --------------------------------------------------- -- &quot; &lt;&lt; std::endl; } } } }; //#endif#pragma once #include &quot;Object.h&quot; class Sphere : public Object { public: Sphere(std::string vs, std::string fs, std::string texName = &quot;&quot;); ~Sphere(); void initData(DataParam *param = nullptr); void renderObject(); void update(float dt); }; #version 460 core out vec4 FragColor; in vec2 TexCoord; uniform sampler2D tex; void main() { FragColor = texture(tex, TexCoord); }#version 330 core layout(location = 0) in vec3 aPos; layout(location = 1) in vec3 aColor; layout(location = 2) in vec2 aTextCoord; out vec2 TexCoord; uniform mat4 model; uniform mat4 view; uniform mat4 projection; uniform vec4 testColor; out vec4 color; void main() { gl_Position = projection * view * model * vec4(aPos,1.0f); TexCoord = vec2(aTextCoord.x,1-aTextCoord.y); color = testColor; }#include &quot;TexturePool.h&quot; #include &lt;SOIL2/SOIL2.h&gt; #include &lt;iostream&gt; TexturePool::TexturePool() { } TexturePool::~TexturePool() { for (Textures::iterator ite = textures.begin(); ite != textures.end(); ++ite) { glDeleteTextures(1, &amp;ite-&gt;second); } } void TexturePool::addTexture(string name, string path) { GLuint texID; if (name.empty()) { return; } texID = SOIL_load_OGL_texture(path.c_str(), 0, 0, SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y); if (texID != 0) { textures[name] = texID; } else { std::cout &lt;&lt; &quot;Failed to load texture&quot; &lt;&lt; path &lt;&lt;&quot; &quot; &lt;&lt;std::endl; } glBindTexture(GL_TEXTURE_2D, texID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // set texture filtering parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } TexturePool* TexturePool::getInstance() { static TexturePool instance; return &amp;instance; } GLuint TexturePool::getTexture(string name) { if (textures.find(name) != textures.end()) { return textures[name]; } return 0; }#pragma once #include &lt;glad/glad.h&gt; #include &lt;GLFW/glfw3.h&gt; #include &lt;map&gt; #include &lt;string&gt; using namespace std; typedef map&lt;string, GLuint&gt; Textures; class TexturePool { public: virtual ~TexturePool(); private: TexturePool(); Textures textures; public: void addTexture(string name, string path); static TexturePool *getInstance(); GLuint getTexture(string name); };
最新发布
10-31
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值