我正在用openGL编程GUI库,并决定添加圆角,因为我觉得它给单元带来了更专业的外观。 我已经实现了通用
length(max(abs(p) - b, 0.0)) - radius
该方法几乎可以完美地起作用,除了在角落处好像它们被拉伸一样。
我的片段着色器:
in vec2 passTexCoords;
uniform vec4 color;
uniform int width;
uniform int height;
uniform int radius;
void main() {
fragment = color;
vec2 pos = (abs(passTexCoords - 0.5) + 0.5) * vec2(width, height);
float alpha = 1.0 - clamp(length(max(pos - (vec2(width, height) - radius), 0.0)) - radius, 0.0, 1.0);
fragment.a = alpha;
}
拉伸对我来说确实有意义,但是当我替换为
vec2 pos = (abs(passTexCoords - 0.5) + 0.5) * vec2(width, height) * vec2(scaleX, scaleY);
和
float alpha = 1.0 - clamp(length(max(pos - (vec2(width, height) * vec2(scaleX, scaleY) - radius), 0.0)) - radius, 0.0, 1.0);
(其中scaleX和scaleY是介于0.0和1.0之间的标量,代表矩形相对于屏幕的宽度和高度),该矩形几乎完全消失了:
答案 0 :(得分:0)
我假设passTexCoords
是[0,1]范围内的纹理坐标。 width
和height
就是屏幕的大小。 scaleX
和scaleY
是绿色区域与屏幕尺寸的比率。
以像素为单位计算当前片段相对于绿色区域中心的绝对位置(pos
):
vec2 pos = (abs(passTexCoords - 0.5) + 0.5) * vec2(width*scaleX, height*scaleY);
计算从圆弧的中心点到当前片段的距离:
vec2 arc_cpt_vec = max(pos - vec2(width*scaleX, height*scaleY) + radius, 0.0);
如果向量的长度大于半径,则必须跳过片段:
float alpha = length(arc_cpt_vec) > radius ? 0.0 : 1.0;
答案 1 :(得分:0)
问题在于,距离没有按比例缩放到屏幕空间中,因此结果是沿最大窗口轴拉伸。如果将标准化位置乘以屏幕的长宽比以及框的其他参数,则可以解决此问题。我在Shadertoy上写了一个这样做的例子:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// Input info
vec2 boxPos; // The position of the center of the box (in normalized coordinates)
vec2 boxBnd; // The half-bounds (radii) of the box (in normalzied coordinates)
float radius;// Radius
boxPos = vec2(0.5, 0.5); // center of the screen
boxBnd = vec2(0.25, 0.25); // half of the area
radius = 0.1;
// Normalize the pixel coordinates (this is "passTexCoords" in your case)
vec2 uv = fragCoord/iResolution.xy;
// (Note: iResolution.xy holds the x and y dimensions of the window in pixels)
vec2 aspectRatio = vec2(iResolution.x/iResolution.y, 1.0);
// In order to make sure visual distances are preserved, we multiply everything by aspectRatio
uv *= aspectRatio;
boxPos *= aspectRatio;
boxBnd *= aspectRatio;
// Time varying pixel color
vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
// Output to screen
float alpha = length(max(abs(uv - boxPos) - boxBnd, 0.0)) - radius;
// Shadertoy doesn't have an alpha in this case
if(alpha <= 0.0){
fragColor = vec4(col,1.0);
}else{
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
}
}
执行此操作可能会花费较少的计算成本,但这是我准备的一个简单解决方案。