在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
看这篇之前,建议先看之前几篇,这几篇是基础。 Go Mobile 例子 basic 源码分析 OpenGL ES 着色语言 仿射变换矩阵(这是glimage包最核心的矩阵算法变换逻辑基础知识)
glutil 包中重要的类是 Image 类, 它实现了 *image.RGBA 和 OpenGL纹理图形之间的桥梁,而Image类中最关键的就是完成绘图,我们重点也是分析这个函数。
precision用来确定默认精度修饰符,precision mediump float; 基本相当于中等精度。 varying 标示是从顶点着色器传递过来的变量。 vec2 2个浮点的向量 UV uniform 只读变量 sampler2D sampler2D是个啥?其实在CG中,sampler2D就是和texture所绑定的一个数据容器接口。这个说法还是太复杂了,简单理解的话,所谓加载以后的texture(贴图)说白了不过是一块内存存储的,使用了RGB(也许还有A)通道,且每个通道8bits的数据。而具体地想知道像素与坐标的对应关系,以及获取这些数据,我们总不能一次一次去自己计算内存地址或者偏移,因此可以通过sampler2D来对贴图进行操作。更简单地理解,sampler2D就是GLSL中的2D贴图的类型,相应的,还有sampler1D,sampler3D,samplerCube等等格式。 texture2D(textureSample, UV) 通过texture2D函数我们可以得到一个纹素(texel),这是一个纹理图片中的像素。函数参数分别为simpler2D以及纹理坐标。 参考: http://blog.csdn.net/racehorse/article/details/6664717
绘图用的顶点着色器参数类型说明:
gl_Position 相关计算gl_Position 变量是一个四维 (vec4) 变量,包含顶点的 x、y、z 和 w 值。上面代码中 w 值恒定为 1,其他值为 mvp * p 计算出来。 mvp 是坐标转换的矩阵,具体计算逻辑请看后面。 p是 z 轴恒定为1 的 三维变量, 其他两维 由 pos 参数传入。 pos 是由 quadXYCoords 传入的,它是 OpenGl 坐标系的四个顶点坐标。
UV 顶点对应颜色计算在颜色着色器中, 颜色和位置的对应关系由UV传入。 UV 的计算在顶点着色器中完成计算。 UV 由 uvp 转换矩阵 * 具体坐标 inUV 计算而来。 inUV 传递的值是由 quadUVCoords 传入的,它是 手机屏幕坐标系的坐标四个顶点。
绘图函数参数分析
// Draw draws the srcBounds part of the image onto a parallelogram, defined by 这个函数通过给定的三个点(左上角、右上角、左下角)来画出一个平行四边形。
这个函数输出参数的坐标系是手机屏幕的坐标系,如下图: 在 golang.org/x/mobile/geom 包中有 pixel 和 pt 的转换函数。 px是像素,屏幕中最小元素单位。
传递给OpenGL的 mvp 矩阵值的计算We are drawing a parallelogram PQRS, defined by three of its corners, onto the entire GL framebuffer ABCD. The two quads may actually be equal, but in the general case, PQRS can be smaller, and PQRS is not necessarily axis-aligned.
There are two co-ordinate spaces: geom space and framebuffer space. In geom space, the ABCD rectangle is: (0, 0) (geom.Width, 0) and the PQRS quad is: PQRS 的坐标是: (topLeft.X, topLeft.Y) (topRight.X, topRight.Y) In framebuffer space, the ABCD rectangle is: (-1, +1) (+1, +1) First of all, convert from geom space to framebuffer space. px2 := -0.5 + float32(topLeft.X/sz.WidthPt) 这个坐标转换请看下图: Next, solve for the affine transformation matrix 有关 仿射变换矩阵 的知识请参看: http://www.cnblogs.com/ghj1976/p/5199086.html 我们现在要通过计算 A点通过一个矩阵转换成 P 点坐标, B点转换成 Q点坐标, D点转换成 S点坐标,如下图: 这个转换肯定是一个 仿射变换 。 A点的坐标是 (-1,+1) P 的坐标是 (2*PX2, 2*PY2) ,这个转换可以用下面公式表示。 同理有 B –> Q , D->S 的 公式。 从公式中提取6个表达式如下:
通过合并运算,可以推理得到
即mvp这个转换矩阵应该是
传递给OpenGL的uvp 的矩阵值的计算这个的计算逻辑过程跟 mvp的过程一样, 不过是 屏幕坐标系 跟 贴图纹理的坐标是类似的, 不过在纹理坐标系中, ABCD 的坐标是: // (0,0) (1,0) PQRS 四个轴跟坐标系是对齐的。如下图效果所示: 由于是轴对齐的, 所以存在: px=sx qy=py 跟上面一样做 A到P的转换 和 B到Q的转换。 矩阵运算如下: 最后可以得到这个转换矩阵为,这也是 uvp 传入的值。
给 OpenGL 传递顶点数据下面这三行代码经常一起出现,含义解释如下: glctx.BindBuffer(gl.ARRAY_BUFFER, glimage.quadXY) glctx.EnableVertexAttribArray(glimage.pos) glctx.VertexAttribPointer(glimage.pos, 2, gl.FLOAT, false, 0, 0)
的第一个参数是表明buffer的类型,gl.ARRAY_BUFFER表明存储vertex data。 EnableVertexAttribArray(a Attrib) 激活该属性
VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int)
整个这个过程可以用下图表示,图来自: https://github.com/fem-d/webGL/blob/master/blog/WebGL%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AF%87%EF%BC%88Lesson%202%EF%BC%89.md
https://github.com/fem-d/webGL/tree/master/blog
数据流程图顶点数据传递流程图
颜色渲染数据传递流程图
纹理操作BindTexture(target Enum, t Texture) 为了把一个名为texture的纹理对象绑定为一个2D纹理对象。 p.glctx.BindTexture(gl.TEXTURE_2D, img.gltex) TexImage2D(target Enum, level int, width, height int, format Enum, ty Enum, data []byte)
必须是2的n次方。纹理图片至少要支持64个材质元素的宽度
//format 像素数据的颜色格式,必须和internalformatt取值必须相同。可选的值有
TexParameteri(target, pname Enum, param int) 指定纹理格式。这里包括纹理横向和纵向的重复方式,这里我们看到设置了4个。 p.glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) p.glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) p.glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) p.glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) TEXTURE_MAG_FILTER 当图片缩放时就需要重新计算每一像素的颜色,而缩放后的图片和原图的像素是无法对上的,因此颜色的分配就有很多算法。最基本的两种算法是“就近取色(NEAREST)”和“线性插值(LINEAR)”,这也是“TEXTURE_MAG_FILTER”和“TEXTURE_MIN_FILTER”的值。下面咱也来说说这个两个值。 下面是效果图,这个东西比较精细,可能很难看清,仔细看文字的边缘 “TEXTURE_WRAP_S”和“TEXTURE_WRAP_T”。这两个东西是用来指定图片平铺的。“TEXTURE_WRAP_S”是横向的设置,“TEXTURE_WRAP_T”是纵向的设置。他们有三个值: 这三个值很容易理解的,测试也很容易看出结果。贴图默认都是平铺的,也就是第一个值。如果我们需要不平铺就可以设置成“CLAMP_TO_EDGE”,就像CSS中的“no-repeat”一样。中间“MIRRORED_REPEAT”也是平铺,只不过是正反交替的。看下面的截图就很容易明白。 参考: https://www.web-tinker.com/article/20163.html TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) writes a subregion of a 2D texture image.
参考: OpenGL ES 2 封装库说明 glutil 包说明文档
|
请发表评论