OpenGL中控制纹理绘制区域
来源:互联网 发布:java中size是什么意思 编辑:程序博客网 时间:2024/04/30 09:07
在OpenGL上绘制图像时,有时候需要控制图像形状,比如圆形,方形,裁处各种形状。
如下效果
最简单的方法就是在上面加个遮罩
其实遮罩也很麻烦,需要对View进行重绘。于是打算从根源出发,控制OpenGL的绘制区域。
矩形剪裁就很简单了,这里不多说了。主要说说圆形,圆形是通过无限细分来逐渐逼近圆形。细分等分越大,线条看起来越光滑。下面是10等分,51等分和100等分的效果图。
OpenGL中,纹理和顶点坐标是对应的。只改变定点坐标的话,得到剪裁后的结果会偏移。所以需要同时改变定点坐标和纹理坐标,来控制绘制区域。
其中,定点坐标的坐标系是以屏幕中心为原点的普通坐标系,最大长度为单位长度1。而纹理坐标有点不同,其原点在屏幕左下角,最大长度为单位长度1。
所以,顶点对应的纹理坐标只需要做相应的坐标转换。
基本关系是:
for(GLuint i = 0; i < num_vertex ; i++) { texcoord[0] = (cos(delta_angle * i) + 1.0) * 0.5; texcoord[1] = (sin(delta_angle * i) + 1.0) * 0.5; glTexCoord2fv(texcoord); vertex[0] = cos(delta_angle * i) * radius; vertex[1] = sin(delta_angle * i) * radius; vertex[2] = 0.0; vertex[3] = 1.0; glVertex4fv(vertex); }
矩形和圆形的处理如下:
AGLKVertexAttribArrayBuffer *temvertexBuffer; if (mask == ovglview_mask_none) { numOfVertext = 4; drawModel = GL_TRIANGLE_STRIP; temvertexBuffer = [[AGLKVertexAttribArrayBuffer alloc] initWithAttribStride:sizeof(SceneVertex) numberOfVertices:sizeof(vertices) / sizeof(SceneVertex) bytes:vertices usage:GL_STATIC_DRAW]; } else if (mask == ovglview_mask_rectangle){ numOfVertext = 4; drawModel = GL_TRIANGLE_STRIP; SceneVertex temVertex[4]; for (int i = 0; i < 4; i++) { temVertex[i].textureCoords.s = vertices[i].textureCoords.s/scale_1 + (1.0f - 1.0f/scale_1)/2.0; temVertex[i].textureCoords.t = vertices[i].textureCoords.t/scale_1 + (1.0f - 1.0f/scale_1)/2.0; temVertex[i].positionCoords.x = vertices[i].positionCoords.x/scale_1; temVertex[i].positionCoords.y = vertices[i].positionCoords.y/scale_1; temVertex[i].positionCoords.z = vertices[i].positionCoords.z/scale_1; } temvertexBuffer = [[AGLKVertexAttribArrayBuffer alloc] initWithAttribStride:sizeof(SceneVertex) numberOfVertices:sizeof(temVertex) / sizeof(SceneVertex) bytes:temVertex usage:GL_STATIC_DRAW]; } else if (mask == ovglview_mask_circle){ SceneVertex circleVertex[100]; GLsizei num = 100; GLfloat angle = 2*PI/num; GLfloat r = 1.0/scale_1; for (GLint i = 0; i < num; i++) { circleVertex[i].textureCoords.s = 1.0 - (GLfloat)((r * cos(angle * i)) +1.0)*0.5; circleVertex[i].textureCoords.t = (GLfloat)((r * sin(angle * i)) +1.0)*0.5; circleVertex[i].positionCoords.x = (GLfloat)(r * cos(angle * i)); circleVertex[i].positionCoords.y = (GLfloat)(r * sin(angle * i)); circleVertex[i].positionCoords.z = 0; } temvertexBuffer = [[AGLKVertexAttribArrayBuffer alloc] initWithAttribStride:sizeof(SceneVertex) numberOfVertices:sizeof(circleVertex) / sizeof(SceneVertex) bytes:circleVertex usage:GL_STATIC_DRAW]; numOfVertext = num; drawModel = GL_TRIANGLE_FAN; }
还需要强调的是,顶点的绘制模式也需要随之改变
常见的模式有三种:
#define GL_TRIANGLES 0x0004
#define GL_TRIANGLE_STRIP 0x0005
#define GL_TRIANGLE_FAN 0x0006
OpenGL中绘制的是三角面片(基本单位)图像是由若干三角面片组成的
三种绘制模式如图所示:
GLAPI void APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
图片来自【OpenGL】理解GL_TRIANGLE_STRIP等绘制三角形序列的三种方式
GL_TRIANGLES
是以每三个顶点绘制一个三角形。第一个三角形使用顶点v0,v1,v2,第二个使用v3,v4,v5,以此类推。如果顶点的个数n不是3的倍数,那么最后的1个或者2个顶点会被忽略。
这是最基本的绘制方式,单纯以三个顶点来绘制三角形,但是比较浪费资源,其顶点不能重用。
GL_TRIANGLE_STRIP
是可以进行顶点重用的,规则有点拗口:
构建当前三角形的顶点的连接顺序依赖于要和前面已经出现过的2个顶点组成三角形的当前顶点的序号的奇偶性(如果从0开始):
如果当前顶点是奇数:
组成三角形的顶点排列顺序:T = [n-1 n-2 n].
如果当前顶点是偶数:
组成三角形的顶点排列顺序:T = [n-2 n-21 n].
以上图为例,第一个三角形,顶点v2序号是2,是偶数,则顶点排列顺序是v0,v1,v2。第二个三角形,顶点v3序号是3,是奇数,则顶点排列顺序是v2,v1,v3,第三个三角形,顶点v4序号是4,是偶数,则顶点排列顺序是v2,v3,v4,以此类推。
这个顺序是为了保证所有的三角形都是按照相同的方向绘制的,使这个三角形串能够正确形成表面的一部分。对于某些操作,维持方向是很重要的,比如剔除。
注意:顶点个数n至少要大于3,否则不能绘制任何三角形。
例如:一个矩形由两个三角形组成,按照GL_TRIANGLES模式需要6个顶点,而按照GL_TRIANGLE_STRIP只需要4个顶点,但是需要注意顶点的顺序
GL_TRIANGLE_FAN
顾名思义,有个fan,是和扇形相关的,方便绘制扇形。可以以某一点为圆心进行绘制
它的三角形的顶点排列顺序是T = [n-1 n-2 n].各三角形形成一个扇形序列。
所以,在改变顶点坐标和纹理坐标的同时,还需要改变绘制模式
个人见解,有误之处还请指正
- OpenGL中控制纹理绘制区域
- opengl 三角纹理绘制
- opengl绘制纹理立方体
- opengl 开发笔记-绘制纹理
- opengl 清除部分绘制区域
- opengl中添加纹理
- OpenGL纹理绘制时色偏的问题
- WinCE OpenGL绘制立方体和纹理贴图
- android opengl es绘制三角形+纹理
- Android OpenGL ES 2.0绘图:绘制纹理
- OpenGL ES绘制3D纹理贴图
- Android OpenGL 纹理绘制图像---基础知识
- Android OpenGL 纹理绘制图像---JAVA实现
- Android OpenGL 纹理绘制图像---Native实现
- Android OpenGL 纹理绘制图像---总结
- Android OpenGL ES 2.0绘图:绘制纹理
- [OpenGL] 基于纹理绘制的透明精灵(透明纹理)
- OpenGL中纹理贴图总结
- OPenCV 图像拼接之------stitching和stitching_detailed
- Anaconda3初试
- 作业4.2:ORACLE特殊数据查询技术
- 不同包的解压包方法
- mysql数据库表卡死怎么办
- OpenGL中控制纹理绘制区域
- 线程同步的四种方式(MFC线程同步4种方式)
- HMM模型用在词性标注、分词
- JSON 数据格式
- js之页面渲染
- 货物移动_免费收货(MvT511)
- 5种单例模式
- Proud Merchants
- Android之在子线程更新UI(超详细)