OpenGL第五节:纹理贴图和像素操作

LOpengGL.h不变

 

LTexture.h

#include "LOpenGL.h"
#include <stdio.h>

class LTexture
{
public:
LTexture();

~LTexture();

bool loadTextureFromPixels32( GLuint* pixels, GLuint width, GLuint height );//根据像素创建或者说加载纹理

void freeTexture();//释放

void render( GLfloat x, GLfloat y );//渲染

GLuint getTextureID();

GLuint textureWidth();

GLuint textureHeight();

private:
GLuint mTextureID;//纹理ID

GLuint mTextureWidth;//纹理宽
GLuint mTextureHeight;//纹理高
};

 

LUtil.h

bool loadMedia();//添加加载资源的方法

 

LTexture.cpp

LTexture::LTexture()//构造函数
{
  mTextureID = 0;
  mTextureWidth = 0;
  mTextureHeight = 0;
}

LTexture::~LTexture()//析构函数
{
  freeTexture();
}

void LTexture::freeTexture()
{
  if( mTextureID != 0 )//删除纹理
  {
    glDeleteTextures( 1, &mTextureID );
    mTextureID = 0;
  }

  mTextureWidth = 0;
  mTextureHeight = 0;
}

bool LTexture::loadTextureFromPixels32( GLuint* pixels, GLuint width, GLuint height )
{
  freeTexture();//如果存在了就先释放

  mTextureWidth = width;
  mTextureHeight = height;

  glGenTextures( 1, &mTextureID );//生成一个纹理ID

  glBindTexture( GL_TEXTURE_2D, mTextureID );//然后绑定到TEXTURE_2D

  glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels );//生成纹理,参数:纹理类型,映射级别,纹理存储像素格式,宽度,高度,边框宽度,传进来的像素格式,传进来的像素的数据类型,传进来的像素

  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );//设置参数,magnify放大时按线性放大
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );//设置参数,minify缩小时按线性缩小

  glBindTexture( GL_TEXTURE_2D, NULL );//解除绑定

  GLenum error = glGetError();
  if( error != GL_NO_ERROR )
  {
    printf( "Error loading texture from %p pixels! %s\n", pixels, gluErrorString( error ) );
    return false;
  }

  return true;
}

void LTexture::render( GLfloat x, GLfloat y )
{
  if( mTextureID != 0 )
  {
    glLoadIdentity();//重置为单位矩阵,去掉之前的移动等操作

    glTranslatef( x, y, 0.f );

    glBindTexture( GL_TEXTURE_2D, mTextureID );

    glBegin( GL_QUADS );
      glTexCoord2f( 0.f, 0.f ); glVertex2f( 0.f, 0.f );//glTexCoord2f方法的参数分别是s,t,取值0~1 。s代表水平方向,t代表竖直方向,(0,0)代表左上角,(1,0)代表右上角,(1,1)代表右下角,(0,0)代表左下角
      glTexCoord2f( 1.f, 0.f ); glVertex2f( mTextureWidth, 0.f );
      glTexCoord2f( 1.f, 1.f ); glVertex2f( mTextureWidth, mTextureHeight );
      glTexCoord2f( 0.f, 1.f ); glVertex2f( 0.f, mTextureHeight );
    glEnd();
  }
}

纹理坐标如下图所示:

  

GLuint LTexture::getTextureID()
{
  return mTextureID;
}

GLuint LTexture::textureWidth()
{
  return mTextureWidth;
}

GLuint LTexture::textureHeight()
{
  return mTextureHeight;
}

 

LUtil.cpp

LTexture gCheckerBoardTexture;

bool loadMedia()
{
  const int CHECKERBOARD_WIDTH = 128;//棋盘的宽,需要是2的幂次方
  const int CHECKERBOARD_HEIGHT = 128;//期盼的高
  const int CHECKERBOARD_PIXEL_COUNT = CHECKERBOARD_WIDTH * CHECKERBOARD_HEIGHT;//总的像素数
  GLuint checkerBoard[ CHECKERBOARD_PIXEL_COUNT ];

  for( int i = 0; i < CHECKERBOARD_PIXEL_COUNT; ++i )//遍历每个像素,然后复制
  {
    GLubyte* colors = (GLubyte*)&checkerBoard[ i ];//一个像素是32位,rgba各8位,强制转化为一个8位的指针指向它,这样可以分别操作r,g,b,a每种颜色

    if(i / 128 & 16   ^   i % 128 & 16 )//间隔
    {//设置为白色
      colors[ 0 ] = 0xFF;//r
      colors[ 1 ] = 0xFF;//g
      colors[ 2 ] = 0xFF;//b
      colors[ 3 ] = 0xFF;//a
    }
    else
    {//设置为红色
      colors[ 0 ] = 0xFF;
      colors[ 1 ] = 0x00;
      colors[ 2 ] = 0x00;
      colors[ 3 ] = 0xFF;
    }
  }

  if( !gCheckerBoardTexture.loadTextureFromPixels32( checkerBoard, CHECKERBOARD_WIDTH, CHECKERBOARD_HEIGHT ) )//创建纹理
  {
    printf( "Unable to load checkerboard texture!\n" );
    return false;
  }

  return true;
  }

void render()
{
  glClear( GL_COLOR_BUFFER_BIT );

  GLfloat x = ( SCREEN_WIDTH - gCheckerBoardTexture.textureWidth() ) / 2.f;//中心点
  GLfloat y = ( SCREEN_HEIGHT - gCheckerBoardTexture.textureHeight() ) / 2.f;

  gCheckerBoardTexture.render( x, y );//绘制

  glutSwapBuffers();//更新屏幕
}

 

main.cpp

int main( int argc, char* args[] )
{
  glutInit( &argc, args );

  glutInitContextVersion( 2, 1 );

  glutInitDisplayMode( GLUT_DOUBLE );
  glutInitWindowSize( SCREEN_WIDTH, SCREEN_HEIGHT );
  glutCreateWindow( "OpenGL" );

  if( !initGL() )//初始化OpenGL
  {
    printf( "Unable to initialize graphics library!\n" );
    return 1;
  }

  if( !loadMedia() )//加载媒体,该方法根据像素创建纹理
  {
    printf( "Unable to load media!\n" );
    return 2;
  }

  glutDisplayFunc( render );

  glutTimerFunc( 1000 / SCREEN_FPS, runMainLoop, 0 );

  glutMainLoop();

  return 0;
}

 

posted @   yongfengnice  阅读(2710)  评论(3编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示