Shader(glsl) 纯在乱说(一)

136 阅读6分钟

shader(glsl) 乱谈

最近看了thebookofshaders.com这个网站,就想着写一篇水文,自己记录一下自己大概学习了什么。

简介

我先简单的介绍一下我理解中的shader,shader就是一种计算机程序,就是让gpu知道如何去绘画的一种指令。通俗一点,就是让计算机知道哪里是亮的哪里是不亮的,哪里是有颜色的,是有什么颜色的。

在这节课和后续的章节里面我们编写的shader的语言是用,glsl来编写,同时这里举例介绍一下其他的着色器语言,比如HLSL、CG等。

简单介绍一下glsl,glsl是一种可以编写shader的着色器语言,它的一个语法基于C语言,是专门为opengl语言来编写的。并且不需要任何的扩展。

这里补充一句我的工作大多数都是web3d的工作所以大部分案例主要是基于opengl es下面的webgl。

最简单的第一步

在编程语言中我们通常的第一个例子就是”Hello World!“(掌握各种语言的Hello World)。

类比我们的hello world在glsl中我们最简单的第一步就是刷屏幕颜色。

首先我们来看一下展示效果

01red.png

大家看到了这个效果,可能有的童鞋就问了,说了半天浪费我这些时间,就这?我用css刷个红色不也行?

那我们就来介绍一下区别

  • 1.我这个是拿glsl写的,而不是css写的(废话文学)

  • 2.这个效果是在支持opgl es的图形库或者代码中才能执行,而css是直接用于浏览器

    接下来我们看一下这个效果具体在glsl中怎么实现的。

#ifdef GL_ES
precision mediump float;
#endif


void main(){
    gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}

条件判断

首先我们来看一下#ifdef GL_ES 这个代码如果,这个代码有的童鞋使用过宏、预处理器指令的,肯定不需要我去班门弄斧,但是有的童鞋的主语言可能没有这种写法,就可以简单把这种语言当成一个if的判断语句来理解。glsl执行的时候会优先处理所有的#开头的指令。

接下来我们看一下 precision mediump float;这一步是干嘛的,我们先使用翻译软件来简单的翻译一下    精度中等的浮点数,那这不就见名知意了吗(所以打败某一类程序员的并不是思维,而是死于英语,嘿嘿),那么咱就可以类比那是不是还有高精度,低精度呢,哎,巧了还真有precision highp float; precision lowp float;

最后的#endif 那就不用说了就是结束判断。

那么问题来了,我为什么要写这个东西,原因那咱也能反推出来就是在GL_ES 也就是opengl es中每一个shader必须指定浮点数的精准级别,否则就报错,但是在opengl的其他版本又没有问题。所以要单独来编译。

那么问题又来了,为什么我在opengl es中就要指定呢,答案其实也很简单,如果你在没看到我这段话之前百度了opengl es那你就知道了这个是主要是为了嵌入式和移动设备和webgl,那么这些设备它的硬件性能不太行,所以它就寻思让开发者你自己控制控制吧,我就不给你控制了。

同时你可以把它想象成一种优化的方法,因为不同的精度级别会影响shader的性能和内存占用。在OpenGL ES中,你可以根据你的需求选择合适的精度级别,比如:

  • 如果你需要高精度的计算,比如光照或阴影,你可以使用highp float,这样可以得到更好的效果,但是也会消耗更多的资源,别问为什么高精度,问就是渲染的逼格一定要高。
  • 如果你只需要中等精度的计算,比如颜色或纹理,你可以使用mediump float,这样可以平衡效果和性能,适合大多数情况,你也不希望你看到的老婆是马赛克吧(手动狗头)。
  • 如果你只需要低精度的计算,比如透明度或噪声,你可以使用lowp float,这样可以节省资源,但是也会降低效果,就是这种效果可以说是意思一下就可以了。

在其他的OpenGL环境中,你不需要指定精度级别,因为它会自动根据硬件和驱动来决定,这就很舒服。

主函数

说了这一溜十三招,咱么这终于进入了主函数,大多数语言都有主函数,主函数是什么呢,就是一个程序的入口,代表了程序就是从这里执行的。void是什么意思呢就是没有返回值。

gl_FragColor = vec4(1.0,0.0,0.0,1.0);这代代码可以说是这个函数中的核心中的核心(废话就一这一句有用的代码)。gl_FragColor就是一个内置的输出变量,用于表示当前像素的颜色。那么vec4是什么呢他表示一个四维的向量,在这里你可以理解成rgba四个通道然后塞进去。

行了,到这咱就完成了shader的hello world了。

你以为到这我要说再见了??? 不不不,咱还得小说一个那么问题来了,为什么你了解的js和python没有主函数呢,这里说一下我自己的猜测,因为js和python都是解释型语言不同于编译型语言(这里咱不提汇编语言),编译型语言需要将代码编译成机器码,为了准确的生成机器码,那么编译器需要知道程序的入口也就是主函数,即从上往下解释和执行代码,直到文件的结束,当然比如js,你也可以使用window.onload 然后让他在一加载就执行一些东西,那么证明什么问题呢,哎glsl是一门编译型语言。

okok,看到这的,都是勇士,因为你们连我写的水文你们都不放过,你们对于知识的渴望已经让人panic!

如果你看完了,觉得我写的很棒,那么问题来了你千万别催我写下一节,因为我很懒惰,但是也别失望,因为我说不定什么时候会勤奋。

但是如果你对这方面的知识很饥渴,thebookofshaders.com 我感觉这个网站是你的不二选择。

封面图片 ANTIPOLYGON YOUTUBE 来自于 Unsplash