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

举报
鱼酱 发表于 2022/01/09 00:25:38 2022/01/09
【摘要】 文章目录 一.使用纹理过程二.疑惑:三.API:四.坐标五.纹理贴图的坐标变化:六.坐标对应表 一.使用纹理过程 使用FreeImage.lib 读取图片,获取调色板.(window...

一.使用纹理过程

  • 使用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);
​	

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
//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;"	 //加法是没有关系的颜色之间的叠加,而乘法是模拟光的照射过程
"}"
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26





二.疑惑:

// 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);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

问题来了,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
  );

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

四.坐标

屏幕坐标:就是应用在设备屏幕上的坐标系。也就是图形最终绘制的地方。
左上角为原点,箭头为正方向,大小又屏幕像素大小决定。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)
只要转动纹理坐标系,在与屏幕坐标系重合,就可以对应处顶点坐标,对应的纹理坐标。

文章来源: yujiang.blog.csdn.net,作者:鱼酱2333,版权归原作者所有,如需转载,请联系作者。

原文链接:yujiang.blog.csdn.net/article/details/83895629

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。