https://img-blog.csdnimg.cn/32db9ce43ef64316a2e37a31f4cee033.gif
编程小鱼酱yu612.com,点击前往

Opengl es2.0 学习笔记(七)基础纹理

一.使用纹理过程

  • 使用FreeImage.lib 读取图片,获取调色板.(windows颜色不是rgb是bgr,此处需要转换)

  • glGenTextures创建一个纹理句柄

  • glBindTexture关联纹理

  • glTexParameteri设置纹理参数

  • glTexImage2D上传到opengl

经过上述步骤我们的纹理句柄就可以使用了

绘制过程

//! 清空缓冲区
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
//! 视口,在Windows窗口指定的位置和大小上绘制OpenGL内容
glViewport(0,0,_width,_height);
//绑定纹理
glBindTexture(GL_TEXTURE_2D,_textureId);
//传入正交投影矩阵 4*4
glUniformMatrix4fv(_shader._MVP, 1, false, matMVP.data());
//传入纹理ID,并且设置为0级纹理
glUniform1i(_shader._texture, 0);
//传入顶点坐标
glVertexAttribPointer(_shader._position,2,  GL_FLOAT,         false,  sizeof(Vertex),vertex);
//传入uv坐标,即纹理坐标
glVertexAttribPointer(_shader._uv,2,        GL_FLOAT,         false,  sizeof(Vertex),&vertex[0].uv);
//传入顶点颜色
glVertexAttribPointer(_shader._color,   4,  GL_UNSIGNED_BYTE, true,   sizeof(Vertex),&vertex[0].color);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
​	
//shader中代码
const char* vs  =   
{
"precision lowp float; "	//指明精度
"uniform   mat4 _MVP;"		//正交投影
"attribute vec2 _position;"	//传入顶点位置
"attribute vec4 _color;"	//颜色
"varying   vec4 _outColor;"	//传递给片段着色器

"void main()"
"{"
"   vec4    pos =   vec4(_position,0,1);"//获取位置
"   _outColor   =   _color;"		//输出颜色赋值
"   gl_Position =   _MVP * pos;"	//输出的位置
"}"
};
const char* ps  =   
{
"precision  lowp float; "
"varying   vec4 _outColor;"
"void main()"
"{"
 "vec4    tColor  =   texture2D(_texture,_outUV);\n"//取颜色
"   gl_FragColor   =   tColor*_outColor;"	 //加法是没有关系的颜色之间的叠加,而乘法是模拟光的照射过程
"}"
};





二.疑惑:

// index: 着色器脚本对应变量ID
// size : 此类型数据的个数
// type : 此类型的sizeof值
// normalized : 是否对非float类型数据转化到float时候进行归一化处理
// stride : 此类型数据在数组中的重复间隔宽度,byte类型计数
// ptr    : 数据指针
glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);glDrawArrays(GL_TRIANGLE_STRIP,0,4);

问题来了,opengl上哪知道数据取多少呢?
答案:
我们使用这个函数,会指明我们要画的点的数量,这样opengl就知道我们需要取多少个元素了
glDrawArrays (GLenum mode, GLint first, GLsizei count);

三.API:

//产生一个纹理Id,可以认为是纹理句柄,后面的操作将书用这个纹理id
glGenTextures( 1, &textureId );

//使用这个纹理id,或者叫绑定(关联)
glBindTexture( GL_TEXTURE_2D, textureId );

/**
  *指定纹理的放大,缩小滤波,使用线性方式,即当图片放大的时候插值方式 
*/
//GL_TEXTURE_MAG_FILTER放大滤波
//GL_TEXTURE_MIN_FILTER缩小滤波
//GL_LINEAR 指定线性算法,效率低一些,质量好一些
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

/**

- 将图片的rgb数据上传给opengl.
  */
  glTexImage2D( 
  GL_TEXTURE_2D,      //! 指定是二维图片
  0,                  //! 指定为第一级别,纹理可以做mipmap,即lod,离近的就采用级别大的,远则使用较小的纹理
  GL_RGB,             //! 纹理的使用的存储格式
  width,              //! 宽度,老一点的显卡,不支持不规则的纹理,即宽度和高度不是2^n。
  height,             //! 宽度,老一点的显卡,不支持不规则的纹理,即宽度和高度不是2^n。
  0,                  //! 是否的边
  GL_RGB,             //! 数据的格式,bmp中,windows,操作系统中存储的数据是bgr格式
  GL_UNSIGNED_BYTE,   //! 数据是8bit数据,RGBA是8bit位
  pixels
  );

四.坐标

屏幕坐标:就是应用在设备屏幕上的坐标系。也就是图形最终绘制的地方。
左上角为原点,箭头为正方向,大小又屏幕像素大小决定。openGL的屏幕坐标系,Y轴向上为正。相当于上面那个三维坐标系截取一个二维的XY。
在这里插入图片描述

opengl坐标:
分3个轴,x,y,z 中心点为o, 箭头方向为正方向,最大与最小值为1和-1,这是经过归一化处理的。这样设计是为了显卡计算方便。
在这里插入图片描述

texture坐标

也做了归一化处理。这个坐标就代表了一个纹理。openGL是基于定点的网格绘制。就是说,openGL的图形都是由很多顶点,按照一定的规则链接起来构成的图形。那么纹理坐标的4个坐标点,映射到顶点上。openGL就会把这个纹理应用到4个定点构成的图形上。
在这里插入图片描述

五.纹理贴图的坐标变化:

我们通常使用顶点坐标是 :
屏幕坐标和 mvp矩阵,传入shader,然后 shader中输出点的变量
gl_Position = 屏幕坐标 X mvp矩阵 ,转换为了opengl坐标即-1~+1,屏幕中心点0,0为中心的坐标系

六.坐标对应表

纹理坐标的坐标系如下:

  • 纹理坐标的 0,1相等于屏幕坐标的0,0
  • 纹理坐标的1,0 相等于屏幕坐标的x,y
  • 纹理坐标的1,1 相等于屏幕坐标的x,0
  • 纹理坐标的0,0 相等于屏幕坐标的 0,y

如下表:

顶点坐标 纹理坐标
CELL::float2(x,y) CELL::float2(0 ,1)
CELL::float2(x + w,y) CELL::float2(1 ,1)
CELL::float2(x,y + h) CELL::float2(0 ,0)
CELL::float2(x + w, y + h) CELL::float2(1 ,0)

如果纹理要顺时针转动:

屏幕坐标 纹理坐标
CELL::float2(x,y) CELL::float2(0 ,0)
CELL::float2(x + w,y), CELL::float2(0 ,1)
CELL::float2(x,y + h) CELL::float2(1 ,0)
CELL::float2(x + w, y + h) CELL::float2(1 ,1)
只要转动纹理坐标系,在与屏幕坐标系重合,就可以对应处顶点坐标,对应的纹理坐标。
posted @ 2018-11-15 18:11  鱼酱  阅读(627)  评论(0编辑  收藏  举报

https://img-blog.csdnimg.cn/32db9ce43ef64316a2e37a31f4cee033.gif
编程小鱼酱yu612.com,点击前往