标签:
简而言之,在渲染管道中,有两个环节是开放给我们的,即Vertex Shader(顶点着色器)和Fragment/Pixel Shader(片段着色器)。
shader或pipeline相关的入门资料是非常多的,但没有多少中文资料是初学者真的能看懂的。如同国内外计算机书籍的区别一样,我们从小耳濡目染了把简单事情书(fu)面(za)化。所以,建议优先读英文资料。
本篇作为学习笔记,同时也考虑如何避开繁复艰涩的弯路,真正浅显入门。于是乎,这篇从这样一个问题开始吧:上面的图我们了解到了渲染流程,那么回头想想,在我们不懂这些知识,没有使用shader时我们不是也照常实现了图片的显示,动画的播放吗?是不是说明管道中的Vertex Shader和Fragment Shader是可以跳过的呢?首先回答,不能跳过。(什么?你说你学习openGL时没有使用shader也画出了三角形了啊,看看上面图片的标题"OpenGL 2.0"你就明白了吧)那么这时shader做了什么操作呢?往下看。
Vertex Shader作用于每一个顶点。看看做简单的Vertex Shader:
vColor = color; vTexCoord = texCoord; gl_Position = modelViewProjection * position;
逐行解读一下:
vColor = color;
color为输入量,顶点颜色值。vColor为输出量,我们没做任何操作,将输入量传出去,留给后来人使用,后来人当然就是Fragment Shader了。
vTexCoord = texCoord;
texCoord是输入量,纹理坐标。vTexCoord为输出量,同样没有任何操作。纹理坐标即该顶点对应的纹理(初学者暂理解为图片加载后的产物)的坐标,该坐标可以用来得到纹理中对应点的颜色值。
gl_Position = modelViewProjection * position;
gl_Position是该顶点的坐标,这是Vertex Shader最终要得到的东西,通知管道该顶点的坐标。modelViewProjection * position暂时不详解,我们明白它通过矩阵运算实现了坐标转换将我们的惯用坐标转换成了openGL坐标就可以了。
作用于每个光栅化后的像素点,如图所示,我们有四个顶点,却有36个片段/像素点。所以Vertex Shader和Fragment Shader运行次数并非一一对应,前者向后者传递的值用来差值运算而非对号入座。
lowp vec4 col = texture2D(texture, vTexCoord) * vColor ;
gl_FragColor = col;
lowp vec4 col = texture2D(texture, vTexCoord) * vColor ;
定义一个局部变量,差值运算获得纹理颜色。
gl_FragColor = col;
gl_FragColor即为该片段的颜色,即Fragment Shader最终要得到的东西。
如上,你看到的就是我们在游戏引擎中默认使用的两个“什么都没做”的shader,回答了前面的问题。
下面,我们可以简单熟悉语法规范,尝试修改小小地shader慢慢积累信心。比如实现一个水平镜像的shader怎么样?建议绕开望而生畏的复杂环境搭建,用下面提供的playground在线编辑。否则把float写作1而不是1.0这样初学者的错误导致没有任何结果且无迹可寻不是很头疼吗。
基本关键字和数据类型参考:
http://blog.csdn.net/hgl868/article/details/7846269
初级shader解析:
http://my.oschina.net/freeblues/blog/336055
playground:
http://www.babylonjs.com/cyos/
https://www.shadertoy.com/new
标签:
原文地址:http://www.cnblogs.com/wonderday/p/4533199.html