opengl纹理贴图,opengl纹理
纹理可以理解为一个二维数组,可以存储大量的数据,这些数据可以发送给着色器。一般情况下,纹理是2D图像,纹理存储的数据是该图像的像素数据。
所谓纹理映射就是用Opengl来渲染这些纹理数据。这个过程有点像装修工在墙上贴瓷砖,瓷砖就像纹理。
坐标如果要在Opengl绘制的矩形上粘贴纹理贴图,需要解决一个问题。怎么知道矩形的某个特定点对应纹理图的某个点?为了解决这个问题,引入了纹理坐标,矩形的顶点坐标与纹理坐标相关联,从而明确了每个顶点应该显示纹理图的像素数据。
纹理坐标在X和Y轴上,范围在0和1之间。使用纹理坐标来获得纹理颜色称为采样。纹理的坐标从纹理图片的左下角(0,0)开始,到纹理图片的右上角(1,1)结束,如下图所示:
纹理坐标周围的纹理值介于0和1之间。如果我们设置纹理坐标大于1会怎么样?OpenGL的默认行为是重复这个纹理图像,那么我们可以用这个默认特性做什么呢?那么现在流行的Tik Tok四屏和九屏滤镜就可以巧妙的用这个功能实现了。
下面是通过改变纹理坐标实现四屏九屏的小技巧:
//4分屏
const static GL float TEXTURE _ COORD[]={
2.0f,2.0f,//右下角
2.0f,0.0f,//右上
0.0f,2.0f,//左下方
0.0f,0.0f //左上
};
//九分屏
const static GL float TEXTURE _ COORD[]={
3.0f,3.0f,//右下方
3.0f,0.0f,//右上
0.0f,3.0f,//左下方
0.0f,0.0f //左上
};当然,当纹理坐标超过1的范围时,Opengl还提供了其他选项,例如:
GL_REPEAT //纹理的默认行为。重复纹理图像。
GL_MIRRORED_REPEAT //和GL_REPEAT一样,只是每次重复的时候图片都是镜像的。
GL_CLAMP_TO_EDGE //纹理坐标会被约束在0和1之间,超出的部分会重复纹理坐标的边缘,造成边缘被拉伸的效果。
GL_CLAMP_TO_BORDER //超出的坐标是用户指定的边缘颜色。
上述特性可通过函数glTexParameteri进行设置:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL _ MIRRORED _ REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL _ MIRRORED _ REPEAT);纹理过滤纹理过滤实际上是在放大和缩小纹理的过程中对像素的处理方法。Opengl ES中常用的两种纹理过滤方法是GL_NEAREST(近似过滤)和GL_LINEAR(也叫线性过滤)。
GL_NEAREST是OpenGL默认的纹理过滤方法。当设置为GL_NEAREST时,OpenGL将选择中心点最接近纹理坐标的像素。GL_LINEAR(也称为线性过滤,(双)线性过滤)它将根据纹理坐标附近的纹理元素计算插值,并近似这些纹理元素之间的颜色。纹理元素的中心越靠近纹理坐标,该纹理元素的颜色对最终样本颜色的贡献就越大。GL_NEAREST产生的是颗粒状的图案,我们可以清楚的看到组成纹理的像素,而GL_LINEAR可以产生更平滑的图案,很难看到单个的纹理像素。
类似地,纹理过滤特性也由函数gltexparameter 1设置:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL _ NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL _ LINEAR);纹理单元的主要目的是允许我们在着色器中使用多个纹理。通过给采样器分配纹理单元,我们可以一次绑定多个纹理,只要先激活相应的纹理单元。比如视频解码后使用Opengl ES渲染YUV,就需要纹理单元的相关知识点。
Opengl中纹理的使用在Opengl中使用纹理有以下步骤:
创建纹理glGenTextures激活纹理glActiveTexture绑定纹理glBindTexture,传递特定纹理id进行绑定,上传纹理数据glTexImage2D解除绑定纹理,glBindTexture,传递0解除绑定纹理坐标映射关系。在了解纹理贴图之前,我们先来回顾三个坐标系,分别是纹理坐标系、手机屏幕坐标系和Opengl坐标系。这三个坐标系的原点是不同的。上面已经介绍了纹理坐标系,这里不再赘述。手机屏幕坐标系是原点在左上角,X轴向右为正,Y轴向下为正的坐标系。Opengl坐标系是一组原点位于中心,X轴向右为正,Y轴向下为正的坐标系,其值在-1到1之间。
由于纹理映射类似于装饰工人粘贴瓷砖,因此您可以将纹理坐标直接对应到Opengl顶点坐标,如下图所示:
我们根据这个映射关系建立一个映射:
//顶点坐标,用画两个三角形的形式形成一个矩形(三角带)
//第一、二、三点构成三角形,第二、三、四点构成三角形。
const static GLfloat顶点[]={
0.5f,-0.5f,//右下方
0.5f,0.5f,//右上
-0.5f,-0.5f,//左下方
-0.5f,0.5f //左上
};
//纹理坐标(原点在左下角,这样贴图看到的就会反过来
const static GL float TEXTURE _ COORD[]={
1.0f,0.0f,//右下方
1.0f,1.0f,//右上
0.0f,0.0f,//左下方
0.0f,1.0f //左上
};发现跑分图贴上来了,但是看到的地图是倒置的,如下图:
这是为什么呢?
因为纹理是由图片的像素生成的,图像是从左上角开始存储的,但是纹理坐标的原点在左下角(不知道为什么这么奇怪),所以出现了反转现象。所以正确的映射关系应该是以图片左上角为原点,刚好与手机屏幕的坐标系相匹配。
也就是说,正确的映射关系是把以左下角为原点的纹理坐标反过来,然后建立映射关系,这也是为什么有些博客说纹理坐标原点在左上角(其实这不是真的,纹理坐标在图片左下角,说在左上角是技巧),所以把纹理坐标反过来再映射,如图:
!
废话少说,把代码放在这里。
#包含“TextureMapOpengl.h”
#包含./utils/Log.h
//顶点着色器
静态常量char *ver=#version 300 es\n
在vec4位置;\n
在vec2 aTexCoord中;\n
out vec2 TexCoord\n
void main() {\n
TexCoord=aTexCoord\n
gl _ Position=aPosition\n
};
//片段着色器
静态常量char *fragment=#version 300 es\n
精密中间浮动;\n
out vec4 FragColor\n
在vec2 TexCoord中;\n
均匀样品ourTexture\n
void main()\n
的意思
FragColor=texture(ourTexture,tex coord);\n
};
//用画两个三角形的形式组成一个矩形(三角带)
//第一、二、三点构成三角形,第二、三、四点构成三角形。
const static GLfloat顶点[]={
0.5f,-0.5f,//右下方
0.5f,0.5f,//右上
-0.5f,-0.5f,//左下方
-0.5f,0.5f //左上
};
//纹理坐标(原点在左下角,这样贴图看到的就会反过来
//const static GL float TEXTURE _ COORD[]={
//1.0f,0.0f,//右下方
//1.0f,1.0f,//右上
//0.0f,0.0f,//左下方
//0.0f,1.0f //左上角
//};
//贴图纹理坐标(参考手机屏幕坐标系,原点在左上角)
//至于一个OpenGL纹理,它没有固有的方向性,所以我们可以用不同的坐标,把它定向到任何我们喜欢的方向。然而,大多数计算机图像都有一个默认的方向,通常指定Y轴向下,X轴向右。
const static GL float TEXTURE _ COORD[]={
1.0f,1.0f,//右下方
1.0f,0.0f,//右上
0.0f,1.0f,//左下方
0.0f,0.0f //左上
};
//四屏GL_REPEAT环绕模式
//const static GL float TEXTURE _ COORD[]={
//2.0f,2.0f,//右下
//2.0f,0.0f,//右上
//0.0f,2.0f,//左下
//0.0f,0.0f //左上
//}:
//九分屏GL _重复(重复)环绕方式
//常量静态GLfloat纹理_ coord[]=>
//3.0f,3.0f,//右下
//3.0f,0.0f,//右上
//0.0f,3.0f,//左下
//0.0f,0.0f //左上
//}:
纹理贴图OpenGL:纹理贴图OpenGL():base OpenGL()& gt;
initGlProgram(参见碎片);
position handle=glgetatliblocation(程序,清除);
纹理句柄=glgetatlib位置(程序, atex coord );
纹理采样器=glgetuniformlocation(程序,"纹理");
LOGD(’程序:%d,程序);
LOGD(positionHandle:%d,位置句柄);
LOGD(textureHandle:%d ,纹理句柄);
LOGD(textureSample:%d,纹理样本);
}
请参阅纹理贴图:setpixel(请参阅*data、int width、int height、int length)>
logd(设定像素纹理):
grund xts(1,纹理id);
//激活纹理,注意以下这个两句是搭配的,冰川纹理激活的是那个纹理,就设置的2D采样器是那个
//默认是0个,如果不是0的话,需要在昂德劳的时候重新激活一下?
//glaactive texture(GL _ texture 0):
//glucniorm 1i(纹理采样器,0);
//例如,一样的
GL _ texture 2(GL _ texture 2):
glucniorm 1i(纹理采样器,2);
//绑定纹理
glBindTexture(GL_TEXTURE_2D,textureId):
//为当前绑定的纹理对象设置环绕~我爱你~过滤方式
GL_TEXTURE_2D、GL_TEXTURE_WRAP_S、GL_REPEAT参数:
GL_TEXTURE_2D、GL_TEXTURE_WRAP_T、GL _重复参数:
GL _纹理_2D、GL _纹理_最小_过滤器、GL _线性参数:
glt x参数(GL _ texture _ 2d、GL_TEXTURE_MAG_FILTER、GL_LINEAR):
二维GL_TEXTURE_2D、0、GL_RGBA、宽度、高度、0、GL_RGBA、GL_UNSIGNED_BYTE、数据
//生成米普贴图
glGenerateMipmap(GL_TEXTURE_2D):
glBindTexture(GL_TEXTURE_2D,textureId):
//解绑定
glBindTexture(GL_TEXTURE_2D,0):
}
请参阅纹理贴图:ondraw()& gt;
glClearColor(0.0f,1.0f,0.0f,1.0f);
GL _ color _ buffer _ bit(GL _ color _ buffer _位元):
葡萄糖程序(程序);
//激活纹理
GL _ texture 2(GL _ texture 2):
glucniorm 1i(纹理采样器,2);
//绑定纹理
glBindTexture(GL_TEXTURE_2D,textureId):
/**
*大小几个数字表示一个点,显示是两个数字表示一个点
*标准化是否需要归一化,不用,这里已经归一化了
*步幅步长,连续顶点之间的间隔,如果顶点直接是连续的,也可填0
*/
//启用顶点数据
glenablevertxatiribarray(位置手柄);
glverticalpointer(位置句柄,2,GL_FLOAT,GL_FALSE,0,顶点);
//纹理坐标
glenablevertxatiribarray(纹理手柄);
glverticalpointer(纹理句柄,2,GL_FLOAT,GL_FALSE,0,TEXTURE_COORD):
//4个顶点绘制两个三角形组成矩形
glDrawArrays(GL_TRIANGLE_STRIP,0.4);
Glu sep程序(0);
//禁用顶点
gldisablevertexattribarray(位置句柄);
如果(零精度!=eghelper .]
eglhelper交换缓冲区();
}
glBindTexture(GL_TEXTURE_2D,0):
}
纹理贴图OpenGL:~纹理贴图OpenGL()& gt;
LOGD(“texture mapengl析构函数);
}仔细看注释多理解-我.
往期笔记计算机图形学是之-他环境搭建计算机图形学是之着色器
计算机图形学是之三角形绘制
计算机图形学是之四边形绘制
关注我,一起进步,人生不止编码!编码!
来自51吨重博客作者思想觉悟的原创作品,
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。