文章目录
- 前言
- 一、半透明
- 1.流程说明
- 2.方法说明
- 3.案例
前言
半透明物体是指在光线透过时,可以看到模糊的影像,但不完全透明的物体。这种物体通常具有一定的透明性,但不完全透明,仍然存在某种程度上的不透明性。
半透明物体的意义在于它可以在不影响视线的情况下,让光线穿过物体,使得我们能够观察到物体背后或者内部的部分。这种特性在许多应用中都非常有用,比如建筑物中的玻璃窗、医疗设备中的透明塑料、以及电子设备中的显示屏。此外,半透明物体还具有一定的艺术效果,可以让物体呈现出半透明的质感和神秘感,增强视觉体验。
一、半透明
1.流程说明
在WebGL中创建半透明物体需要遵循以下步骤:
-
在片元着色器中定义透明度属性,并使用gl_FragColor来设置颜色和透明度值。
-
使用gl.enable(gl.BLEND)启用混合模式,这样可以将透明物体正确地混合到场景中。
-
使用gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)设置混合函数,指定源颜色因子和目标颜色因子,以便正确地混合透明物体。
-
在渲染透明物体时,确保先渲染不透明的物体,再渲染半透明的物体。这样可以避免混合时受到前面物体的影响而导致不正确的结果。
2.方法说明
要实现透明,需要开启混合,会使用到下面的两个方法:
-
gl.enable(gl.BLEND):开启混合
-
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA):源因子和目标因子是可以通过gl.blendFunc函数来进行设置的,gl.blendFunc有两个参数,前者表示源因子,后者表示目标因子。这两个参数可以是多种值,下面介绍比较常用的几种。文章来源:https://uudwc.com/A/DNkGE
- gl.ZERO:表示使用0.0作为因子,实际上相当于不使用这种颜色参与混合运算。
- gl.ONE:表示使用1.0作为因子,实际上相当于完全的使用了这种颜色参与混合运算。
- gl.SRC_ALPHA:表示使用源颜色的alpha值来作为因子。
- gl.DST_ALPHA:表示使用目标颜色的alpha值来作为因子。
- gl.ONE_MINUS_SRC_ALPHA:表示用1.0减去源颜色的alpha值来作为因子。
- gl.ONE_MINUS_DST_ALPHA:表示用1.0减去目标颜色的alpha值来作为因子。
3.案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../lib/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
canvas{
margin: 50px auto 0;
display: block;
background: yellow;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持canvas
</canvas>
</body>
</html>
<script>
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
// 创建着色器源码
const VERTEX_SHADER_SOURCE = `
attribute vec4 aPosition;
attribute vec4 aNormal;
varying vec4 vColor;
uniform mat4 mat;
void main() {
// 定义点光源的颜色
vec3 uPointLightColor = vec3(1.0,1.0,0.0);
// 点光源的位置
vec3 uPointLightPosition = vec3(-5.0,6.0,10.0);
// 环境光
vec3 uAmbientLightColor = vec3(0.2,0.2,0.2);
// 物体表面的颜色
vec4 aColor = vec4(1.0,0.0,0.0,1.0);
// 顶点的世界坐标
vec4 vertexPosition = mat * aPosition;
// 点光源的方向
vec3 lightDirection = normalize(uPointLightPosition - vec3(vertexPosition));
// 环境反射
vec3 ambient = uAmbientLightColor * vec3(aColor);
// 计算入射角 光线方向和法线方向的点积
float dotDeg = dot(lightDirection, vec3(aNormal));
// 漫反射光的颜色
vec3 diffuseColor = uPointLightColor * vec3(aColor) * dotDeg;
gl_Position = vertexPosition;
vColor = vec4(ambient + diffuseColor, 0.5);
}
`; // 顶点着色器
const FRAGMENT_SHADER_SOURCE = `
precision lowp float;
varying vec4 vColor;
void main() {
gl_FragColor = vColor;
}
`; // 片元着色器
const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
const aPosition = gl.getAttribLocation(program, 'aPosition');
const aNormal = gl.getAttribLocation(program, 'aNormal');
const mat = gl.getUniformLocation(program, 'mat');
const vertices = new Float32Array([
// 0123
1, 1, 1,
-1, 1, 1,
-1,-1, 1,
1,-1, 1,
// 0345
1, 1, 1,
1,-1, 1,
1,-1,-1,
1, 1,-1,
// 0156
1, 1, 1,
1, 1, -1,
-1, 1,-1,
-1, 1,1,
// 1267
-1, 1, 1,
-1,1, -1,
-1, -1,-1,
-1,-1,1,
// 2347
-1,-1, 1,
1,-1, 1,
1,-1,-1,
-1,-1,-1,
// 4567
1,-1,-1,
1, 1,-1,
-1, 1,-1,
-1,-1,-1,
])
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aPosition)
// 法向量
const normals = new Float32Array([
0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,
0.0,0.0,-1.0,0.0,0.0,-1.0,0.0,0.0,-1.0,0.0,0.0,-1.0,
-1.0,0.0,0.0,-1.0,0.0,0.0,-1.0,0.0,0.0,-1.0,0.0,0.0,
1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,
0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,
0.0,-1.0,0.0,0.0,-1.0,0.0,0.0,-1.0,0.0,0.0,-1.0,0.0,
])
const normalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, normals, gl.STATIC_DRAW);
gl.vertexAttribPointer(aNormal, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aNormal)
const indeces = new Uint8Array([
0,1,2,0,2,3,
4,5,6,4,6,7,
8,9,10,8,10,11,
12,13,14,12,14,15,
16,17,18,16,18,19,
20,21,22,20,22,23,
])
const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indeces, gl.STATIC_DRAW);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
const vm = getViewMatrix(3,3,5,0.0,0.0,0.0,0.0,0.6,0.0);
const perspective = getPerspective(30, ctx.width / ctx.height, 100, 1);
gl.uniformMatrix4fv(mat, false, mixMatrix(perspective, vm));
gl.drawElements(gl.TRIANGLES, indeces.length, gl.UNSIGNED_BYTE, 0);
</script>
文章来源地址https://uudwc.com/A/DNkGE