Three.js 在缩放期间更改WebGl屏幕空间投影线着色器的行为
我正在基于Three.js和stack构建2D图形结构,其中有一个问题与相机缩放期间屏幕空间投影线的行为有关。问题是,当我放大时,线条会明显变小,而当我缩小时,线条会变大 示例: 具有预定义厚度的法线: 缩小后的行: 放大后的行: 我还在着色器中构建的所有其他元素(圆、箭头的矩形)都具有“正常”行为,并根据相机位置线性地和相反方向改变其大小(放大时变大,缩小时变小)。我需要达到完全相同的行为与线在着色器,但不知道如何做到这一点,因为在这个领域相当新 “我的线顶点”着色器是WestLangley的线材质着色器的稍微修改版本,您可以看到下面的代码。我注意到的一点是: 如果删除dir=normalize(dir)line,线的缩放行为将变为正常,但它们的厚度开始取决于节点之间的距离,这也是不合适的 下面是VertexShader:Three.js 在缩放期间更改WebGl屏幕空间投影线着色器的行为,three.js,glsl,shader,vertex-shader,Three.js,Glsl,Shader,Vertex Shader,我正在基于Three.js和stack构建2D图形结构,其中有一个问题与相机缩放期间屏幕空间投影线的行为有关。问题是,当我放大时,线条会明显变小,而当我缩小时,线条会变大 示例: 具有预定义厚度的法线: 缩小后的行: 放大后的行: 我还在着色器中构建的所有其他元素(圆、箭头的矩形)都具有“正常”行为,并根据相机位置线性地和相反方向改变其大小(放大时变大,缩小时变小)。我需要达到完全相同的行为与线在着色器,但不知道如何做到这一点,因为在这个领域相当新 “我的线顶点”着色器是WestLangl
`precision highp float;
#include <common>
#include <color_pars_vertex>
#include <fog_pars_vertex>
#include <logdepthbuf_pars_vertex>
#include <clipping_planes_pars_vertex>
uniform float linewidth;
uniform vec2 resolution;
attribute vec3 instanceStart;
attribute vec3 instanceEnd;
attribute vec3 instanceColorStart;
attribute vec3 instanceColorEnd;
attribute float alphaStart;
attribute float alphaEnd;
attribute float widthStart;
attribute float widthEnd;
varying vec2 vUv;
varying float alphaTest;
void trimSegment( const in vec4 start, inout vec4 end ) {
// trim end segment so it terminates between the camera plane and the near plane
// conservative estimate of the near plane
float a = projectionMatrix[ 2 ][ 2 ]; // 3nd entry in 3th column
float b = projectionMatrix[ 3 ][ 2 ]; // 3nd entry in 4th column
float nearEstimate = - 0.5 * b / a;
float alpha = ( nearEstimate - start.z ) / ( end.z - start.z );
end.xyz = mix( start.xyz, end.xyz, alpha );
}
void main() {
#ifdef USE_COLOR
vColor.xyz = ( position.y < 0.5 ) ? instanceColorStart : instanceColorEnd;
alphaTest = ( position.y < 0.5 ) ? alphaStart : alphaEnd;
#endif
float aspect = resolution.x / resolution.y;
vUv = uv;
// camera space
vec4 start = modelViewMatrix * vec4( instanceStart, 1.0 );
vec4 end = modelViewMatrix * vec4( instanceEnd, 1.0 );
// special case for perspective projection, and segments that terminate either in, or behind, the camera plane
// clearly the gpu firmware has a way of addressing this issue when projecting into ndc space
// but we need to perform ndc-space calculations in the shader, so we must address this issue directly
// perhaps there is a more elegant solution -- WestLangley
bool perspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 ); // 4th entry in the 3rd column
if (perspective) {
if (start.z < 0.0 && end.z >= 0.0) {
trimSegment( start, end );
} else if (end.z < 0.0 && start.z >= 0.0) {
trimSegment( end, start );
}
}
// clip space
vec4 clipStart = projectionMatrix * start;
vec4 clipEnd = projectionMatrix * end;
// ndc space
vec2 ndcStart = clipStart.xy / clipStart.w;
vec2 ndcEnd = clipEnd.xy / clipEnd.w;
// direction
vec2 dir = ndcEnd - ndcStart;
// account for clip-space aspect ratio
dir.x *= aspect;
dir = normalize( dir );
// perpendicular to dir
vec2 offset = vec2( dir.y, - dir.x );
// undo aspect ratio adjustment
dir.x /= aspect;
offset.x /= aspect;
// sign flip
if ( position.x < 0.0 ) offset *= - 1.0;
// endcaps, to round line corners
if ( position.y < 0.0 ) {
// offset += - dir;
} else if ( position.y > 1.0 ) {
// offset += dir;
}
// adjust for linewidth
offset *= (linewidth * widthStart);
// adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ...
offset /= resolution.y;
// select end
vec4 clip = ( position.y < 0.5 ) ? clipStart : clipEnd;
// back to clip space
offset *= clip.w;
clip.xy += offset;
gl_Position = clip;
vec4 mvPosition = ( position.y < 0.5 ) ? start : end; // this is an approximation
#include <logdepthbuf_vertex>
#include <clipping_planes_vertex>
#include <fog_vertex>
}`
`precision highp float;
#包括
#包括
#包括
#包括
#包括
均匀浮动线宽;
均匀vec2分辨率;
属性vec3 instanceStart;
属性vec3 instanceEnd;
属性vec3 instanceColorStart;
属性vec3 instanceColorEnd;
属性开始;
属性浮点字母结束;
属性浮动宽度开始;
属性浮动宽度结束;
可变vec2 vUv;
可变浮动试验;
无效段(vec4开始时的常数,inout vec4结束时的常数){
//修剪端点段,使其在摄影机平面和近平面之间终止
//近平面的保守估计
float a=projectionMatrix[2][2];//第三列中的第三个条目
float b=projectionMatrix[3][2];//第4列中的第3个条目
浮动近估算=-0.5*b/a;
float alpha=(nearEstimate-start.z)/(end.z-start.z);
end.xyz=混合(start.xyz,end.xyz,alpha);
}
void main(){
#ifdef使用颜色
vColor.xyz=(位置y<0.5)?instanceColorStart:InstanceColorRend;
alphaTest=(位置y<0.5)?alphaStart:alphaEnd;
#恩迪夫
浮动纵横比=分辨率.x/分辨率.y;
vUv=紫外线;
//摄像机空间
vec4 start=modelViewMatrix*vec4(instanceStart,1.0);
vec4 end=modelViewMatrix*vec4(instanceEnd,1.0);
//透视投影和在摄影机平面内或后面终止的线段的特殊情况
//显然,gpu固件在投射到ndc空间时可以解决这个问题
//但是我们需要在着色器中执行ndc空间计算,所以我们必须直接解决这个问题
//也许有一个更优雅的解决方案——韦斯特兰利
bool perspective=(projectionMatrix[2][3]=-1.0);//第3列中的第4个条目
如果(透视图){
if(start.z<0.0&&end.z>=0.0){
修剪段(开始、结束);
}else if(end.z<0.0&&start.z>=0.0){
修剪段(结束,开始);
}
}
//剪辑空间
vec4 clipStart=projectionMatrix*start;
vec4 clipEnd=投影矩阵*结束;
//ndc空间
vec2 ndcStart=clipStart.xy/clipStart.w;
vec2 ndcEnd=clipEnd.xy/clipEnd.w;
//方向
vec2 dir=ndcEnd-ndcStart;
//说明剪辑空间纵横比
dir.x*=纵横比;
dir=标准化(dir);
//垂直于方向
vec2偏移量=vec2(方向y,-方向x);
//取消纵横比调整
dir.x/=aspect;
偏移量.x/=纵横比;
//标志翻转
如果(位置x<0.0)偏移量*=-1.0;
//端盖,到圆角
如果(位置y<0.0){
//偏移量+=-dir;
}否则如果(位置y>1.0){
//偏移量+=dir;
}
//调整线宽
偏移量*=(线宽*宽度开始);
//调整剪辑空间到屏幕空间的转换//也许分辨率应该基于视口。。。
偏移量/=分辨率y;
//选择结束
vec4剪辑=(位置y<0.5)?剪辑开始:剪辑结束;
//返回剪辑空间
偏移量*=clip.w;
clip.xy+=偏移量;
gl_位置=夹子;
vec4 mvPosition=(position.y<0.5)?开始:结束;//这是一个近似值
#包括
#包括
#包括
}`
碎片着色器:
`precision highp float;
#include <common>
#include <color_pars_fragment>
#include <fog_pars_fragment>
#include <logdepthbuf_pars_fragment>
#include <clipping_planes_pars_fragment>
uniform vec3 diffuse;
uniform float opacity;
varying vec2 vUv;
varying float alphaTest;
void main() {
if ( abs( vUv.y ) > 1.0 ) {
float a = vUv.x;
float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0;
float len2 = a * a + b * b;
if ( len2 > 1.0 ) discard;
}
vec4 diffuseColor = vec4( diffuse, alphaTest );
#include <logdepthbuf_fragment>
#include <color_fragment>
gl_FragColor = vec4( diffuseColor.rgb, diffuseColor.a );
#include <premultiplied_alpha_fragment>
#include <tonemapping_fragment>
#include <encodings_fragment>
#include <fog_fragment>
}`
`precision highp float;
#包括
#包括
#包括
#包括
#包括
均匀vec3扩散;
均匀浮动不透明度;
可变vec2 vUv;
可变浮动试验;
void main(){
如果(绝对值(vUv.y)>1.0){
浮点数a=vUv.x;
dir = normalize( dir );
vec2 offset = vec2( dir.y, - dir.x );
vec2 offset = vec2( dir.y, - dir.x );
dir = normalize( dir );