Shader学习笔记p1——基础概念
最近项目需求接触到了Shader,而Shader也是出了名的不好学,我便以此笔记来记录一下学习过程,若有可能,也希望对迷茫中的新手有些帮助。PS:因为是学习笔记,自然是想到什么记什么,过程不免有些流水账,还望见谅。
学习一样新东西,先要知道它是什么,为什么要用它,那么就先来了解一下Shader是什么?为什么要用Shader?
先来看看万能的Wiki是怎么说的
着色器(英语:shader)应用于计算机图形学领域,指一组供计算机图形资源在执行渲染任务时使用的指令,用于计算图像的颜色或明暗。但近来,它也能用于处理一些特殊效果,或者视频后处理。通俗地说,着色器告诉电脑如何用特有的一种方法去绘制物体。程序员将着色器应用于图形处理器(GPU)的可编程流水线,来实现三维应用程序。这样的图形处理器有别于传统的固定流水线处理器,为GPU编程带来更高的灵活性和适应性。以前固有的流水线只能进行一些几何变换和像素灰度计算。现在可编程流水线还能处理所有像素、顶点、纹理的位置、色调、饱和度、明度、对比度并实时地绘制图像。着色器还能产生如模糊、高光、有体积光源、失焦、卡通渲染、色调分离、畸变、凹凸贴图、边缘检测、运动检测等效果
看着有些抽象,再看看另一篇文章是怎么说的
Shader(着色器)实际上就是一小段程序,它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出。绘图单元可以依据这个输出来将图像绘制到屏幕上。(参考1)
OK,结合两者整理下大概能知道Shader是一个能处理图像输入并输出提供给GPU进行绘制的脚本程序。
那么为什么会出现Shader这东西呢,我继续往下深入,还是先看Wiki
停一下从技术的角度来看,着色器是渲染器的一个部分,它负责计算目标的颜色。随着图形处理单元的进步,主要的图形软件库,像OpenGL和Direct3D都开始将目光投向更高阶的功能,即用着色器给新型的GPU编程,这就需要开发一系列的应用程序接口(API)满足着色功能。这样的改动出现在OpenGL的1.5版本和Direct3D的8版本。
渲染器?OpenGL?Direct3D?看着这些陌生又熟悉的名词我的大脑一阵颤抖,硬着头皮继续谷歌...
渲染(英语:render,或称“绘制”)在电脑绘图中,是指:用软件从模型生成图像的过程。模型是用语言或者数据结构进行严格定义的三维物体或虚拟场景的描述,它包括几何、视点、纹理、照明和阴影等信息。图像是数字图像或者位图图像。渲染用于描述:计算视频编辑软件中的效果,以生成最终视频的输出过程。
哦哦哦哦哦!渲染器就是Renderer嘛!这个我在Unity菜单里面见过,好吧其实我也没什么概念,按照Wiki上面的解释来看,我们平时说的3D模型其实是一个3D物体或者3D场景按照一定约束描述的集合,这个集合中包含了一些信息,而渲染器读取这些信息后就会把这个物体或者场景还原出来并绘制成我们能看到的画面,说得更简单一些,渲染器就像是一个画家,把我们需要画的东西的信息告诉他,他就能帮我们画出来。
而渲染又有预渲染(Pre-rendering)和实时渲染(Real-time rendering),预渲染就是计算机以CPU为主进行渲染,显示效果好但是画出来比较耗时,实时渲染是以GPU为主,效果较差但胜在画的快,于是就能理解为什么在游戏中提到都是说实时渲染,而听到做设计的朋友整天抱怨渲染等很久是因为用的是与渲染了。
然后又把OpenGL和Direct3D给谷歌了一番,这俩货都是绘图API,区别就是OpenGL是开源的,用在多个平台,Direct3D是必源的,并且仅用于Windows平台,他们针对Shader都有自己的一套GPU编程语言,OpenGL对应的是GLSL(OpenGLShading Language,也叫GLslang) ,Direct3D对应的是HLSL(High Level ShadingLanguage),除了它们两个外还有一个著名卡商NVIDIA的GPU编程语言Cg(C for graphic),三者算是流行三巨头了
解决了这几个看着头大的名词,我接着往下看看为什么会出现需要Shader的情况,首先是一张固定的硬件的渲染流水线图
来自《计算机图形学基础知识-----渲染流水线》这张图描述的是GPU层的渲染的流程,可以看到有个片段的着色,如果我们需要高效的去实现一些成像的变换操作,那么比如成像之后再改变,显然在这里处理是最效率的,于是就有了把着色模块变为可编程化的需求,根据之前所了解到的信息,Shader编程本质上就是对可编程化的着色器进行编程,那么再来看看可编程化后的渲染流水线图,
来自《计算机图形学基础知识-----渲染流水线》我们可以看到可编程的部分有两个,一个是针对顶点,一个是针对片断(图上称为片段,查了下英文原文为Fragment,故还是用片断来称呼),顶点比较好理解,一个模型,会存在很多顶点,这些顶点通过连接形成线,一组封闭的线组成面,许许多多的面组成最后我们看到的模型,而变换顶点可以在一定程度上改变模型的形成效果,举个栗子,
举个栗子我们看到一个正方形,如果把四个顶点的位置进行不同程度的便宜,那么正方形就会变成一个梯形,视觉上就有一种类似透视的效果
简单的顶点坐标变换扩展想一下,变换的顶点数更多的情况,甚至可以形成凹凸面等效果,看到这里我忽然发现,虽然这玩意叫着色器,但实际上能做的事情不仅仅是着色,还兼职了包括坐标位置在内的一些工作,拿着跟别人一样的工资,做了其他人几倍的工作。
而另一个片断着色器的片断一眼看不出个所以然,于是来看看Wiki上的说明
像素着色器(Direct3D),常常又称为片断着色器(OpenGL),处理来自光栅化器的数据。光栅化器已经将多边形填满并通过流水线传送至像素着色器,后者逐像素计算颜色。像素着色器常用来处理场景光照和与之相关的效果,如凸凹纹理映射和调色。名称片断着色器似乎更为准确,因为对于着色器的调用和屏幕上像素的显示并非一一对应。举个例子,对于一个像素,片断着色器可能会被调用若干次来决定它最终的颜色,那些被遮挡的物体也会被计算,直到最后的深度缓冲才将各物体前后排序。
像素着色引擎(Pixel Shader)是以每像素(Pixel)为单位的图形处理功能。像素着色引擎不是最迫切需要的,拥有较低的优先权,当顶点着色引擎负荷大时,像素着色引擎可能被闲置著。大多数情况下,可使用顶点着色法代替像素着色法。Direct3D 9.0 扩充像素着色引擎,有多达1536个指令。
emmmmmm...大概意思应该是针对像素来进行着色,但是可以被顶点着色器以某种算法取代,但是要展现出更好的效果,则需要它来处理每一个像素,比如有一个面,会先对这个面的像素点颜色进行计算,然后如果这个面被光照着了,那么就再计算被光照后的像素点颜色,这样调用两次片断着色器,就算出最终这个像素点的成像颜色。当然,现实情况肯定会更复杂,不过通过这两段说明大致上已经了解片断着色器是做什么的了。
而时代在进步,科技在升华,为了应对一些新的需要,展现出更好的画面,现在的渲染流水线中已经增加了更加细分的着色器,比如可以从几何面中增删顶点的几何着色器(Geometry shaders),Direct3D 11新增用来处理表面细分的曲面细分表面着色器(Tessellation shaders)
Direct3D 11 Graphics Pipeline看了这么多,也大概了解了Shader是什么,以及为什么要用Shader了,下一篇就从代码入手开始学习。
PS:由于本人没有学过计算机图形相关专业课程,若有理解不准确的地方还望指正m(_ _)m
参考: