十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

OpenGL(十四)- 压缩纹理

OpenGL(十四)- 压缩纹理 压缩纹理为了利用OpenGL对压缩纹理的支持纹理数据一开始并不需要进行压缩。我们可以在加载一幅纹理图像时请求OpenGL对它进行压缩这是通过在glTexImage函数中设置internalFormat参数实现的。可选参数如下通过这种方式进行图像压缩增加了纹理加载的开销但却能够通过更有效地使用纹理存储空间来增加纹理性能。如果由于某些原因而无法对纹理进行压缩OpenGL就会使用上表所列出的基本内部格式并加载未经压缩的纹理。当我们试图按照这种方式加载并压缩一个纹理时可以使用glGetTexLevelParameteriv函数以GL_TEXTURE_COMPRESSED为参数来判断这个纹理是否被成功压缩。GLint compFlag;……glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_COMPRESSED,compFlag);glGetTexLevelParameteriv函数可以接受几个新的参数名它们都和压缩纹理有关。当纹理进行压缩之后OpenGL会选择最适当的纹理压缩格式。我们可以使用glHint指定希望OpenGL根据最快速度还是最佳质量算法来选择压缩格式。glHint(GL_TEXTURE_COMPRESSION_HINT,GL_FASTEST);glHint(GL_TEXTURE_COMPRESSION_HINT,GL_NICEST);glHint(GL_TEXTURE_COMPRESSION_HINT,GL_DONT_CARE);加载压缩纹理用glGetCompressedTexImage函数相当于未压缩纹理的glTexImage函数提取经过压缩的数据并把它保存到磁盘中。在后续的纹理加载中可以使用原始压缩数据从而极大地提高纹理的加载速度。为了加载预先经过压缩的纹理数据可以使用下列函数:voidglCompressedTexImage1D(GLenum target,GLint level,GLenum internalFormat,GLsizei width,GLint border,GLsizei imageSize,void*data);voidglCompressedTexImage2D(GLenum target,GLint level,GLenum internalFormat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,void*data);voidglCompressedTexImage3D(GLenum target,GLint level,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLint border,Glsizei imageSize,GLvoid*data);纹理压缩是一种非常流行的纹理特性。较小的纹理所占据的空间更小、通过网络传输的速度更快、从磁盘加载的速度更快、复制到图形内存也更加快速并且允许更多的纹理加载到硬件中而且使纹理的启用更加快速但是不要忘了和生活中的很多事情一样天下没有免费的午餐。使用纹理压缩也要付出一些代价。例如GL_EXT_texture_compression_s3tc方法是通过从每个纹理单元提取颜色数据进行工作的。对于有些纹理这样可能会导致图像质量的损失尤其是那些包含了平滑颜色过渡的纹理。在其他一些时候具有大量细节的纹理在视觉上几乎与未压缩的源纹理相同颜色的变化几乎无法察觉。纹理压缩方法的选择或选择不使用纹理压缩可能极大地依赖于底层图像的本质。示例在此前分享的SphereWorld示例基础上扩展代码如下#includesphereworld5.h#includeGLTools.h#includeGLShaderManager.h#includeGLFrustum.h#includeGLBatch.h#includeGLMatrixStack.h#includeGLGeometryTransform.h#includeStopWatch.h#includemath.h#includestdio.h#ifndefFREEGLUT_STATIC#defineFREEGLUT_STATIC#endif#includeGL/glut.h#defineNUM_SPHERES50namespacesphereworld5{GLFrame spheres[NUM_SPHERES];GLShaderManager shaderManager;GLMatrixStack modelViewMatrix;GLMatrixStack projectionMatrix;GLFrustum viewFrustum;GLGeometryTransform transformPipeline;GLFrame cameraFrame;GLTriangleBatch torusBatch;GLTriangleBatch sphereBatch;GLBatch floorBatch;GLuint uiTextures[3];voidDrawSongAndDance(floatyRot){staticGLfloat vWhite[]{1.0f,1.0f,1.0f,1.0f};staticGLfloat vLightPos[]{0.0f,3.0f,0.0f,1.0f};// 获取眼空间中的光源位置M3DVector4f vLightTransformed;M3DMatrix44f mCamera;modelViewMatrix.GetMatrix(mCamera);m3dTransformVector4(vLightTransformed,vLightPos,mCamera);// 绘制光源modelViewMatrix.PushMatrix();modelViewMatrix.Translatev(vLightPos);shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vWhite);sphereBatch.Draw();modelViewMatrix.PopMatrix();glBindTexture(GL_TEXTURE_2D,uiTextures[2]);for(inti0;iNUM_SPHERES;i){modelViewMatrix.PushMatrix();modelViewMatrix.MultMatrix(spheres[i]);shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,modelViewMatrix.GetMatrix(),transformPipeline.GetProjectionMatrix(),vLightTransformed,vWhite,0);sphereBatch.Draw();modelViewMatrix.PopMatrix();}modelViewMatrix.Translate(0.0f,0.2f,-2.5f);modelViewMatrix.PushMatrix();modelViewMatrix.Rotate(yRot,0.0f,1.0f,0.0f);// 绘制与相机相关的内容glBindTexture(GL_TEXTURE_2D,uiTextures[1]);shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,modelViewMatrix.GetMatrix(),transformPipeline.GetProjectionMatrix(),vLightTransformed,vWhite,0);torusBatch.Draw();modelViewMatrix.PopMatrix();modelViewMatrix.Rotate(yRot*-2.0f,0.0f,1.0f,0.0f);modelViewMatrix.Translate(0.8f,0.0f,0.0f);glBindTexture(GL_TEXTURE_2D,uiTextures[2]);shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,modelViewMatrix.GetMatrix(),transformPipeline.GetProjectionMatrix(),vLightTransformed,vWhite,0);sphereBatch.Draw();}boolLoadTGATexture(constchar*szFileName,unsignedintminFilter,unsignedintmagFilter,unsignedintwrapMode){GLbyte*pBits;intnWidth,nHeight,nComponents;GLenum eFormat;pBitsgltReadTGABits(szFileName,nWidth,nHeight,nComponents,eFormat);if(pBitsNULL)returnfalse;glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,wrapMode);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,wrapMode);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,minFilter);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,magFilter);glPixelStorei(GL_UNPACK_ALIGNMENT,1);glTexImage2D(GL_TEXTURE_2D,0,GL_COMPRESSED_RGB,nWidth,nHeight,0,eFormat,GL_UNSIGNED_BYTE,pBits);free(pBits);if(minFilterGL_LINEAR_MIPMAP_LINEAR||minFilterGL_LINEAR_MIPMAP_NEAREST||minFilterGL_NEAREST_MIPMAP_LINEAR||minFilterGL_NEAREST_MIPMAP_NEAREST)glGenerateMipmap(GL_TEXTURE_2D);returntrue;}voidSetupRC(){glewInit();shaderManager.InitializeStockShaders();glEnable(GL_DEPTH_TEST);glEnable(GL_CULL_FACE);glClearColor(0.0f,0.0f,0.0f,1.0f);gltMakeTorus(torusBatch,0.4f,0.15f,40,20);gltMakeSphere(sphereBatch,0.1f,26,13);GLfloat texSize10.0f;floorBatch.Begin(GL_TRIANGLE_FAN,4,1);floorBatch.MultiTexCoord2f(0,0.0f,0.0f);floorBatch.Vertex3f(-20.0f,-0.41f,20.0f);floorBatch.MultiTexCoord2f(0,texSize,0.0f);floorBatch.Vertex3f(20.0f,-0.41f,20.0f);floorBatch.MultiTexCoord2f(0,texSize,texSize);floorBatch.Vertex3f(20.0f,-0.41f,-20.0f);floorBatch.MultiTexCoord2f(0,0.0f,texSize);floorBatch.Vertex3f(-20.0f,-0.41f,-20.0f);floorBatch.End();glGenTextures(3,uiTextures);glBindTexture(GL_TEXTURE_2D,uiTextures[0]);LoadTGATexture(./src/chapter_5/src/SphereWorld/marble.tga,GL_LINEAR_MIPMAP_LINEAR,GL_LINEAR,GL_REPEAT);glBindTexture(GL_TEXTURE_2D,uiTextures[1]);LoadTGATexture(./src/chapter_5/src/SphereWorld/marslike.tga,GL_LINEAR_MIPMAP_LINEAR,GL_LINEAR,GL_CLAMP_TO_EDGE);glBindTexture(GL_TEXTURE_2D,uiTextures[2]);LoadTGATexture(./src/chapter_5/src/SphereWorld/moonlike.tga,GL_LINEAR_MIPMAP_LINEAR,GL_LINEAR,GL_CLAMP_TO_EDGE);for(inti0;iNUM_SPHERES;i){GLfloat x((GLfloat)((rand()%400)-200)*0.1f);GLfloat z((GLfloat)((rand()%400)-200)*0.1f);spheres[i].SetOrigin(x,0.0f,z);}}voidShutdownRC(){glDeleteTextures(3,uiTextures);}voidRenderScene(){staticCStopWatch rotTimer;floatyRotrotTimer.GetElapsedSeconds()*60.0f;glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);modelViewMatrix.PushMatrix();M3DMatrix44f mCamera;cameraFrame.GetCameraMatrix(mCamera);modelViewMatrix.MultMatrix(mCamera);modelViewMatrix.PushMatrix();modelViewMatrix.Scale(1.0f,-1.0f,1.0f);modelViewMatrix.Translate(0.0f,0.8f,0.0f);glFrontFace(GL_CW);DrawSongAndDance(yRot);glFrontFace(GL_CCW);modelViewMatrix.PopMatrix();glEnable(GL_BLEND);glBindTexture(GL_TEXTURE_2D,uiTextures[0]);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);staticGLfloat vFloorColor[]{1.0f,1.0f,1.0f,0.75f};shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE,transformPipeline.GetModelViewProjectionMatrix(),vFloorColor,0);floorBatch.Draw();glDisable(GL_BLEND);DrawSongAndDance(yRot);modelViewMatrix.PopMatrix();glutSwapBuffers();glutPostRedisplay();}voidSpecialKeys(intkey,intx,inty){floatlinear0.1f;floatangularfloat(m3dDegToRad(5.0f));if(keyGLUT_KEY_UP)cameraFrame.MoveForward(linear);if(keyGLUT_KEY_DOWN)cameraFrame.MoveForward(-linear);if(keyGLUT_KEY_LEFT)cameraFrame.RotateWorld(angular,0.0f,1.0f,0.0f);if(keyGLUT_KEY_RIGHT)cameraFrame.RotateWorld(-angular,0.0f,1.0f,0.0f);}voidChangeSize(intw,inth){glViewport(0,0,w,h);transformPipeline.SetMatrixStacks(modelViewMatrix,projectionMatrix);viewFrustum.SetPerspective(35.0f,float(w)/float(h),1.0f,100.0f);projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());modelViewMatrix.LoadIdentity();}intsphereworld5_test(intargc,char*argv[]){gltSetWorkingDirectory(argv[0]);glutInit(argc,argv);glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);glutInitWindowSize(800,600);glutCreateWindow(OpenGL SphereWorld);glutReshapeFunc(ChangeSize);glutDisplayFunc(RenderScene);glutSpecialFunc(SpecialKeys);SetupRC();glutMainLoop();ShutdownRC();return0;}}效果预览
返回列表