GLSL 是(OPEN)GL 的标准着色语言。这个编程语言可以用来为OPENGL/WebGL着色,Three.js 库中刚好包含的有这部分内容,当然,这个语言可以在任何你喜欢的WebGl中使用,但是,这次我关注的重点在Three.js上,这个语言有点像 C,但是是用来描述着色(需要一些顶点函数)。基本上,你可以用GLSL来解决着色你运行的那些几何形状。和着色其他的可以操作的相邻的东西。
着色流程
当我们要着色一些3D场景时。在这个流程中有多个不同的阶段。我们可以修改vertex shader 和 fragment shader这两个阶段来达到一些自定义的要求。这个图片来展示一些流程中的基本概念。
你看,首先,CPU会加载一些基础代码,然后他会通过geometries 把所有的objects(camera/light信息) 加载到GPU。
GPU接收到这些信息后,会通过vertex shader来发送每一个vertex,你可以在你喜欢的地方修改他们。
然后修改vertices发送后,一些操作会在前端执行一些对象,裁剪摄像头视图外的内容,以及其他的内容。然后会发送到fragment shader,基本上是大量的三角形和决定颜色在像素上的处理。这些处理后,就可能显示在你的显示器上了。
Uniform,Varying 和 attribute
我们已经展示了流程图解,和一些奇怪的变量,这里会介绍GLSL中的三中不同的变量类型(像本地变量,全局变量,静态变量,等等,但是可能不太一样)。
- Uniform ,是两个 shader 共用的变量,例如,灯光的位置和颜色,因此,他是只读的。
- Varying ,是处理 vertex shader, 他是可以修改的,它可以把新的值传递给fragment shader,例如,你想修改顶点的位置。你必须改变他们的常量才能让着色器正常工作。
- Attribute 是vertex shader 中用到的,他是只读的,这是一些标准的变量,如着色位置,常量,等等。
最简单的Shader
shader的基本概念你已经了解了,下面为你带来一个最基本的着色器,只需要保留顶点位置,并为整个对象提供一种整体的颜色。
顶点着色器(gl_Position)
//这里是变量的空间
//内置的主函数
void main(){ //每个顶点着色器必须最终设置'gl\_Position'
//在这种情况下,我们将顶点位置与摄像机视图和屏幕矩阵相乘得到最终的输出。
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
片段着色器(gl_FragColor):
//再次,变量空间
void main(){ //就像顶点着色器一样,片段着色器必须在最后设置这个变量(gl\_FragColor)
//我们将它设置为粉红色。
gl_FragColor = vec4(1.0, // R
0.0, // G
1.0, // B
1.0); // A
}
此着色器只显示具有颜色的对象,仅此而已。 顶点着色器按原样保留位置,并将其提供给片段着色器。 这个给碎片他们的颜色,我们完成了!
但是,我们在哪里放置着色器代码?
好问题! 有多种可能性,但最常用的是将着色器代码放入“
//顶点着色器代码
<script id = "cubeVertexShader" type="x-shader/x-vertex" >
// codehere ...
</script>
//片段着色器代码
<script id = "cubeFragmentShader" type="x-shader/x-fragment" >
// codehere ...
</script>
<script>
//从中获取文本
var vShader = $('#cubeVertexShader').text();
var fShader = $('#cubeFragmentShader').text();
//或者,对于非jQuery类的人
var vShader = document.getElementById('cubeVertexShader').innerHTML;
var fShader = document.getElementById('cubeFragmentShader').innerHTML;
</script>
在编辑器中尝试代码!
最后一点:将它添加到场景中
最后但同样重要的是:我们必须将着色器添加到Three.js可以使用的材料中。
//使用我们的代码创建一个新的着色器材质
var itemMaterial = new THREE.ShaderMaterial({ //可选,这里你可以提供uniform和attributes
vertexShader:vShader, fragmentShader:fShader}); //与我们的材料创建一个新的项
var item = new THREE.Mesh(new THREE.CubeGeometry(100, 10, 10), itemMaterial);
那是…基础知识。
你还没有真正完成任何成就。 我不是说这会让你对自己感觉不好,我的意思是:我们刚刚重新创造了一个可以用Three.js标准材料做的事情。 现在,是时候开始添加更多的乐趣了,我们在下一部分就是这么做的。
原文链接