片段着色器三个js中的抗锯齿
Antialiasing in Fragment Shader Three js
我正在编写一个小着色器,它在 Three.js 中生成一个圆锥形渐变。
一切正常我通过添加一点噪音消除了条带,所以一般来说渐变看起来不错。我唯一的问题是在 2 个渐变色的边缘出现了丑陋的锯齿。见图片
然后我尝试在我的片段着色器中平滑边缘,效果很好但不是在渐变的最里面。
我知道我可以在更高分辨率下渲染场景并将其缩小或应用后期效果,但我想知道是否有更好的方法。
总的来说,我不是着色器编写方面的专家,也不是 three.js,所以也许您有一些意见可以优雅地解决这个问题。
感谢您的帮助,这里是 fiddle 和碎片着色器代码。
<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec4 colour1;
uniform vec4 colour2;
uniform sampler2D texture;
varying vec3 vUv;
void main() {
precision highp float;
//get Angle for textureCoordinate
float angleDeg = atan(vUv.y - 0.5,vUv.x - 0.5) * 180.0 / 3.147;
if (angleDeg < 0.0){
angleDeg = angleDeg+360.0 ;
}
//Generate Gradient
float lerpValue = angleDeg/360.0;
vec4 colour = mix(colour1,colour2,lerpValue);
//My approach to smooth the edge works well on the outside but
//not on the inside
if(lerpValue>0.9995){
float smoot = 1.0-lerpValue;
smoot = smoot*2000.00;
vec4 lerpColor = mix(colour1,colour2,0.9995);
colour = mix(colour1,lerpColor,smoot);
}
///done with gradient
//apply noise from noise texture to eliminate banding
vec2 textureCoord = vUv.xy;
vec4 noise = texture2D(texture,textureCoord.xy);
colour.xyz += mix(-0.05, 0.05, noise.x);
gl_FragColor = colour;
}
</script>
首先,您需要一种更准确的方法来计算抗锯齿。支持任意值 lerpLimit
的等式(你的魔法值 0.9995)
//Generate Gradient
float lerpValue = angleDeg/360.0;
float lerpLimit = 0.9995;
float invDiff = lerpLimit/(1.0-lerpLimit);
if(lerpValue>lerpLimit){
lerpValue = invDiff - lerpValue*invDiff;
}
vec4 colour = mix(colour1,colour2,lerpValue);
//My approach to smooth the edge works well on the outside but
//not on the inside
// ....
现在您可以根据距离pixel/center调制lerpLimit
,以获得恒定厚度的抗锯齿渐变
//Generate Gradient
float lerpValue = angleDeg/360.0;
// the constant thickness of the antialias gradient
// along the seam
float limit = .02;
float lerpLimit = 1.0 - limit / (6.283185*length(vUv.xy - 0.5));
// avoid negative limit at the center
lerpLimit = max( lerpLimit, 0.0 );
float invDiff = lerpLimit/(1.0-lerpLimit);
if(lerpValue>lerpLimit){
lerpValue = invDiff - lerpValue*invDiff;
}
vec4 colour = mix(colour1,colour2,lerpValue);
//My approach to smooth the edge works well on the outside but
我正在编写一个小着色器,它在 Three.js 中生成一个圆锥形渐变。 一切正常我通过添加一点噪音消除了条带,所以一般来说渐变看起来不错。我唯一的问题是在 2 个渐变色的边缘出现了丑陋的锯齿。见图片
然后我尝试在我的片段着色器中平滑边缘,效果很好但不是在渐变的最里面。
我知道我可以在更高分辨率下渲染场景并将其缩小或应用后期效果,但我想知道是否有更好的方法。
总的来说,我不是着色器编写方面的专家,也不是 three.js,所以也许您有一些意见可以优雅地解决这个问题。
感谢您的帮助,这里是 fiddle 和碎片着色器代码。
<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec4 colour1;
uniform vec4 colour2;
uniform sampler2D texture;
varying vec3 vUv;
void main() {
precision highp float;
//get Angle for textureCoordinate
float angleDeg = atan(vUv.y - 0.5,vUv.x - 0.5) * 180.0 / 3.147;
if (angleDeg < 0.0){
angleDeg = angleDeg+360.0 ;
}
//Generate Gradient
float lerpValue = angleDeg/360.0;
vec4 colour = mix(colour1,colour2,lerpValue);
//My approach to smooth the edge works well on the outside but
//not on the inside
if(lerpValue>0.9995){
float smoot = 1.0-lerpValue;
smoot = smoot*2000.00;
vec4 lerpColor = mix(colour1,colour2,0.9995);
colour = mix(colour1,lerpColor,smoot);
}
///done with gradient
//apply noise from noise texture to eliminate banding
vec2 textureCoord = vUv.xy;
vec4 noise = texture2D(texture,textureCoord.xy);
colour.xyz += mix(-0.05, 0.05, noise.x);
gl_FragColor = colour;
}
</script>
首先,您需要一种更准确的方法来计算抗锯齿。支持任意值 lerpLimit
的等式(你的魔法值 0.9995)
//Generate Gradient
float lerpValue = angleDeg/360.0;
float lerpLimit = 0.9995;
float invDiff = lerpLimit/(1.0-lerpLimit);
if(lerpValue>lerpLimit){
lerpValue = invDiff - lerpValue*invDiff;
}
vec4 colour = mix(colour1,colour2,lerpValue);
//My approach to smooth the edge works well on the outside but
//not on the inside
// ....
现在您可以根据距离pixel/center调制lerpLimit
,以获得恒定厚度的抗锯齿渐变
//Generate Gradient
float lerpValue = angleDeg/360.0;
// the constant thickness of the antialias gradient
// along the seam
float limit = .02;
float lerpLimit = 1.0 - limit / (6.283185*length(vUv.xy - 0.5));
// avoid negative limit at the center
lerpLimit = max( lerpLimit, 0.0 );
float invDiff = lerpLimit/(1.0-lerpLimit);
if(lerpValue>lerpLimit){
lerpValue = invDiff - lerpValue*invDiff;
}
vec4 colour = mix(colour1,colour2,lerpValue);
//My approach to smooth the edge works well on the outside but