|前端如何快速上手 Web 3D 游戏的开发( 四 )


|前端如何快速上手 Web 3D 游戏的开发
本文插图
整个 ShaderDefine 结构如下 , 其中 vertexShader 和 fragmentShader 分别存放顶点着色器和片元着色器代码 , 采用 GLSL ( OpenGL 着色语言 , OpenGL Shading Language )编写 。 states 用来定义渲染状态控制对象 , 对应上文提到的合并阶段 。
export const ShaderMaterial = { vertexShader: ``, fragmentShader: ``, states: {}, uniforms: {}, attributes: {}, };(3)如果要动态改变材质参数值 , 需要创建脚本 , 在节点每帧执行的回调函数中修改属性值 。
下面通过跑道滚动和光波两个示例来讲解 。
3、 跑道滚动如2.1中所述 , 跑道是一个静止的圆弧模型 , 通过改变纹理的UV值来实现跑道滚动的效果 。 为了实现给人物打光的效果 , 我们在基础颜色纹理上面叠加了一张渐变纹理 , 并给人物加上了一个静态的阴影(实际上是一个面片) 。
|前端如何快速上手 Web 3D 游戏的开发
本文插图
( 基础颜色纹理)
|前端如何快速上手 Web 3D 游戏的开发
本文插图
(渐变纹理)
|前端如何快速上手 Web 3D 游戏的开发
本文插图
( 叠加效果)
相关的Shader代码如下:
export const ShaderMaterial = { // Vertex Shader 代码 vertexShader: ` uniform mat4 matModelViewProjection; uniform float utime; attribute vec3 a_position; attribute vec2 a_uv; varying vec2 v_uv; varying vec2 v_uv_run; void main() { gl_Position = matModelViewProjection * vec4(a_position, 1.0 ); v_uv = a_uv; v_uv_run = vec2( v_uv.s, v_uv.t + utime ); } `, // Fragment Shader 代码 fragmentShader: ` varying vec2 v_uv; varying vec2 v_uv_run; uniform sampler2D texturePrimary; uniform sampler2D textureLight; void main() { vec4 texSample = texture2D( texturePrimary, v_uv_run ).rgba; vec4 texLightSample = texture2D( textureLight, v_uv ).rgba; gl_FragColor = vec4(texSample.rgb * texSample.a + texLightSample.rgb * texLightSample.a, texSample.a); } `, states: {}, }Vertex Shader 和 Fragment Shader 都包含了一个 mian 入口函数 。
初次看 Shader 代码会发现很多陌生的符号 , 其中 uniform、attribute 和 varying 都是变量限定符 , attribute 只能存在于 Vertex Shader 中 , 一般用来放置程序传过来的顶点、法线、颜色等数据;uniform 是程序传入到 Shader 中的全局数据;varying 主要负责在Vertex Shader 和 Fragment Shader 之间传递变量 。
mat4、vec3、sampler2D 都是基本变量类型 , 分别代表矩阵、向量和纹理 , 后面的数字代表n维 , 例如 mat4表示 4x4 矩阵 。
本例的 Vertex Shader 中 , 顶点位置 a_position 与 matModelViewProjection 矩阵相乘 , 其实是把三维世界的物体投影到二维的屏幕上 。 a_uv 存放了 UV 信息 , 我们想要把一张贴图贴到模型表面 , 需要纹理映射坐标 , 即UV坐标 , 分别代表横纵两个方向 。 为了使地面能滚动起来 , 我们需要每帧改变 UV 的纵坐标 , 并通过变量 v_uv_run 传递给 Fragment Shader 。
在 Fragment Shader 中 , texturePrimary 和 textureLight 都是从 CPU 程序传过来的纹理 。 通过 texture2D 采样基础颜色纹理 texturePrimary , 得到了纹理贴图在模型上滚动的效果 。 接着拿采样后的颜色值与透明渐变纹理 texLightSample 进行叠加 , 得到了近亮远暗的效果 。


推荐阅读