着色器是一段跑在GPU中的程序,使用GLSL语言编写(OpenGL Shading Language)
着色器又分为两种,顶点着色器和片元着色器
其中顶点点着色器负责计算每个顶点的位置/颜色等信息,片元着色器则用来计算这些顶点间每个片元(像素)的颜色
参考
The Book of Shaders
WebGLProgram threejs.org
翻译:非常详细易懂的法线贴图
lesson-webgl-shader-threejs
Three.js Beginners GLSL Tutorial
参数
varying 从顶点着色器传递变量到片元着色器
uniform 由js代码传递给顶点/片元着色器的变量,只读
attribute 由js代码传递给顶点着色器,只读
数据类型
- int 整数
- float 浮点数
- bool 布尔值(true|false|0|1)
- vec2,vec3,vec4 2,3,4维向量(浮点数)
- ivec2,ivec3,ivec4 2,3,4维向量(整数)
- mat2,mat3,mat4 2X2,3x3,4x4矩阵(浮点数)
- void 无返回值的函数
1 | void main(){ |
GLSL不会自动转换数据类型,如下代码会报错
1 | int eNum = 1.0; |
数据转换
1 |
|
内建变量
gl_FragColor
gl_FragCoord
precision(精度)
precision mediump float;
precision lowp float;
precision highp float;
uniform(统一值)
uniform是连通CPU和GPU的桥梁
1 | uniform vec3 u_color; |
uniform只读,不可修改
如下错误示范
1 | uniform vec3 u_color; |
varying
函数
dot 计算两向量的点积
1 | vec3 a = vec3(1, 1, 0); |
normalize 归一化
1 | vec3 vertex = normalize(vec3(2,3,4)); |
Vertex shaders(顶点着色器)
顶点着色器的作用是把3D数据转换为屏幕上的2D形状,即计算3维空间在2维屏幕上投影的坐标.
可以把顶点着色器放在html中,然后操作Dom来获取相关代码.
1 | // 顶点着色器 |
1 | // 获取顶点着色器 |
Fragment shaders(片元着色器)
例1
1 | // 片元着色器 |
Three.js内置参数
由Geometry和BufferGeometry提供的顶点属性
- attribute vec3 position 顶点在物体中的坐标位置
- attribute vec3 normal 法向量
- attribute vec2 uv uv坐标,可用uv.x和uv.y分别获取顶点的横纵坐标
1 | var planeGeo = new THREE.PlaneBufferGeometry(1,1); |
内置的uniform
- uniform mat3 normalMatrix; 法向矩阵,modelViewMatrix的反转
- uniform mat4 model modelMatrix; 模型空间矩阵
- uniform mat4 viewMatrix; 视图空间矩阵
- uniform mat4 modelViewMatrix; 模型空间矩阵和视图空间矩阵的组合(viewMatrix * modelMatrix)
- uniform mat4 projectionMatrix; 投影矩阵,用于转换3D坐标到2D平面
- uniform vec3 cameraPosition; 镜头在world space中的位置
也可用uniforms传入自定义的uniform
1 | shaderMaterial = new THREE.ShaderMaterial({ |
自己用uniforms属性塞进来的uniform需要声明才能使用
而内置的uniform不需要这样做,Three.js已经在顶点着色器里声明了.再声明会报错的,例如:
1 | <script id="vs" type="x-shader/x-vertex"> |
但这些内置的uniform并没有在片元着色器里声明(viewMatrix|cameraPosition除外)
要用的话需要自己声明一次,或者用varying从顶点着色器传过来
1 | <script id="fs" type="x-shader/x-vertex"> |
法线(normal)
法线是垂直于平面内某点的一条直线(曲面则为该点的切平面)
通常用一个向量来表示,称这个向量叫法向量
法线 维基百科
法向量通常位于-1,1之间
1 | // 无论Three.js正方形的大小如何变化,法向量距原点依然在[-1,1]区间内 |
可通过归一化将法向量映射到[0,1]间
1 | vec3 vNormal = normalize(normalMatrix * normal); |
在WebGL中,法向量用于表示模型顶点的朝向.常被用于计算光照/判断模型某一面的朝向
调试工具
firefox自带着色器调试工具,开启方式:
1 | Toolbox option > 勾选: Shader Editor |
附录
名词解释
-
uv坐标
-
view(eye/camera) space 视图空间
what is world space,eye space and loadl space?
转换顶点坐标到视图空间
1 | uniform mat4 modelViewMatrix; |
1 | // 注意,如果是光源的话不需要计算modelMatrix |
- 点积(又称为点乘/数量积/内积)
一个向量再另一个向量上的投影
结果为负时,两个向量方向相反
结果为0时,两向量互相垂直
需要注意的是,少个分号(;)也会导致着色器报错
示例
计算光照
1 | //顶点着色器 |
1 | //片元着色器 |