shader 广告牌(sprite)
1、position
vs:
vColor = position.x;
fs:
varying float vColor;
void main() {
gl_FragColor = vec4(vec3(vColor, 0., 0.), 1.);
}
可以看出来,x分布:
--------------->x
-10 0 10
如果:
vColor = position.x * -1;
那么:
也就是说,符号只会改变方向.
2、始终朝向屏幕
vs:
void main() {
// 模型的中心局部坐标 转换到 视图空间
vec4 mvPosition = modelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0);
// 在视图空间下,以模型中心做位置的上下偏移
mvPosition.xy += position.xy;
gl_Position = projectionMatrix * mvPosition;
}
3、尺寸不随相机距离变换
效果:
- 相机距离大了, mesh看着小了,为了大小保持不变, mesh就该放大
- 相机距离近了, mesh看着大了,为了大小保持不变, mesh就该缩小
可以看到mesh的缩放和相机距离成正比。
vec4 mvPosition = modelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0);
float camPos = mvPosition.z;
float scale = camPos;
mvPosition.xy += vec2(position.x*scale, position.y*scale);
gl_Position = projectionMatrix * mvPosition;
这样可以了, 但是缩放太大了,满屏都是。需要找个参数控制一下缩放大小。
vec4 mvPosition = modelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0);
//
float camPos = mvPosition.z;
float scale = camPos * 0.02;
mvPosition.xy += vec2(position.x*scale, position.y*scale);
gl_Position = projectionMatrix * mvPosition;
注意,-camPos 才是相机距离,但是因为最后乘以position, position.xy各一半都是负数,所以该值的正负并不影响。
// 这样也可以
float camPos = - mvPosition.z;
可以发现现在这个调节的参数很小,因为 camPos 一般很大。也可以先把position变小一些。
// 屏幕分辨率
uniform vec2 uSize;
uniform float uScale;
vec4 mvPosition = modelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0);
float camPos = mvPosition.z;
float aspect = uSize.x / uSize.y;
// 映射到屏幕,position就会很小了
vec2 temp = position.xy / uSize;
temp.x *= aspect;
temp *= camPos;
temp *= uScale;
mvPosition.xy += temp;
gl_Position = projectionMatrix * mvPosition;
4、合并所有功能
vs:
// 屏幕分辨率
uniform vec2 uSize;
uniform float uScale;
// 尺寸衰减
uniform float uSizeAttenuation;
void main() {
vec4 mvPosition = modelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0);
// 开启尺寸衰减
if (uSizeAttenuation == 1.) {
mvPosition.xy += position.xy;
} else {
// 关闭尺寸衰减
float aspect = uSize.x / uSize.y;
float camPos = mvPosition.z;
vec2 temp = position.xy / uSize;
temp *= camPos;
temp *= uScale;
temp.x *= aspect;
mvPosition.xy += temp;
}
gl_Position = projectionMatrix * mvPosition;
}
最后效果: