# 如何使用WebGL渲染一簇水晶

·  阅读 1999

### 制作随机水晶体生成器

• 生成单个水晶顶点

• 生成水晶簇顶点

• 一个圆周上取多边形点，使用随机角度，形成不同宽度面
``````  ...
angle = i / faceNumber * PI * 2 + r * angleDithringFactor * angleDithringUnit;
px = Math.sin(angle) * polygonCircleRadius;
py = Math.cos(angle) * polygonCircleRadius;
...

• 随机缩放圆半径，圆周上同角度取多边形点，形成不同柱体半径
``````  ...
...

• 形成多边形棱柱的上下两层顶点
``````  ...
vertexs.topPositions.push(px);
vertexs.topPositions.push(py);
...

• 增加正对圆心的顶点，形成水晶柱顶点
``````  ...
vertexsCon = [0, cylinderHeight+conHeight, 0];
...

• 生成一个水晶体几何体
``````  ...
vertexs = [...vertexsCylinderDown, ...vertexsCylinderTop, ...vertexsCon];
...

• 矩阵变换缩放、旋转单个水晶体的顶点，并复制顶点
``````  ...
let scaleMatrix = new Matrix4();
scaleMatrix.setScale(scaleFactor, scaleFactor, scaleFactor);
let rotateMatrix = new Matrix4();
rotateMatrix.setRotate(rotateAngle, rotateCenter.x, rotateCenter.y, rotateCenter.z);
...
let vScaledRotated = rotateMatrix.multiplyVector4(vScaled);
...

• 生成水晶簇几何体
``````  ...
let extendedIndices = extendIndices(cristalTransformed.indices, currentIndicesLength);
cluster.indices = cluster.indices.concat(extendedIndices);
cluster.positions = cluster.positions.concat(cristalTransformed.positions);
cluster.uvs = cluster.uvs.concat(cristal.uvs);
...

### 渲染几何体

• 片元着色器
``````  fragColor = vec4(0.6, 0.6, 0.6, 1.0);

### 添加光照

• 片元着色器
``````  vec3 diffuse = max(dot(normal, ec_lightDirection), 0.0) * lightColor * lightIntensity * baseColor;

vec3 viewDirection = -normalize(ec_position);
vec3 halfAngle = normalize(viewDirection + ec_lightDirection);
float specularFactor = clamp(dot(normal, halfAngle), 0.0, 1.0);
float spec = pow(specularFactor, specularIntensity);
vec3 specular = clamp(spec * specularColor, 0.0, 1.0);

fragColor = vec4(diffuse + specular + ambient, 1.0);

### 着色器添加渐变的祖母绿效果

• 片元着色器
``````  ...
float colorMixFactor = pow(v_uv.y, 3.0);
...
vec3 baseColor = mix(CRISTAL_COLOR, GEM_COLOR_GREEN,  colorMixFactor);
...

### 使用贴图增强表面细节

• 片元着色器
``````  ...
fragColor = vec4(diffuse + diffuse * textureFilter + specular + AMB_COLOR, 1.0);

### 参考文献

Webgl Programing Guide