Geometry 带可变边框的GLSL圆角矩形

Geometry 带可变边框的GLSL圆角矩形,geometry,glsl,shader,rectangles,Geometry,Glsl,Shader,Rectangles,我正在尝试编写一个GLSL着色器,它生成一个带边框的圆角矩形,类似于下面的示例,但每个边框边(顶部、底部、左侧、右侧)的厚度可能不同 因此,与均匀的边界厚度不同,我们应该: 边界厚度x0、边界厚度x1、边界厚度y0、边界厚度y1 我看过许多使用有符号距离场(SDF)在着色器中创建圆角矩形的示例,但还没有找到如何调整代码以允许可变边界边厚度 似乎许多方法都涉及碎片坐标的abs(),因此假设一致性 有人能就如何实现这一目标提供指导吗? 谢谢 例如: 示例:与shadertoy着色器()相比,您必须

我正在尝试编写一个GLSL着色器,它生成一个带边框的圆角矩形,类似于下面的示例,但每个边框边(顶部、底部、左侧、右侧)的厚度可能不同

因此,与均匀的边界厚度不同,我们应该: 边界厚度x0、边界厚度x1、边界厚度y0、边界厚度y1

我看过许多使用有符号距离场(SDF)在着色器中创建圆角矩形的示例,但还没有找到如何调整代码以允许可变边界边厚度

似乎许多方法都涉及碎片坐标的abs(),因此假设一致性

有人能就如何实现这一目标提供指导吗? 谢谢

例如:
示例:

与shadertoy着色器()相比,您必须根据片段计算
u\fHalfBorderThickness

定义左侧、右侧、底部和顶部的厚度:

float u_厚度top=20.0;
浮动u_厚度底部=30.0;
浮动u_厚度左=25.0;
浮动u_厚度右=35.0;
根据截面计算边缘的厚度:

vec2 uv=fragCoord/iResolution;
vec2边缘厚度=vec2(
uv.x>0.5?u_厚度右:u_厚度左,
uv.y>0.5?u_厚度顶部:u_厚度底部);
根据碎片和碎片到边界中心的距离(
fHalfBorderDist
)计算
fHalfBorderThickness

float fHalfBorderDist=0.0;
浮球厚度=0.0;
如果(fragCoord.x>最大值(u_fRadiusPx,u_厚度左)和
fragCoord.x最大值(u_fRadiusPx,u_厚度底部)和
fragCoord.y0.5?iResolution.x-fragCoord.x:fragCoord.x,
uv.y>0.5(溶液y-fragCoord.y:fragCoord.y));
vec2椭圆_ab=u_fRadiusPx-v2边缘厚度;
vec2椭圆_isect=(v2edgeThickness.x>u_fRadiusPx | | v2edgeThickness.y>u_fRadiusPx)?vec2(0.0):
edgeVec.xy*椭圆x*椭圆y/长度(椭圆x*edgeVec.yx);
fHalfBorderThickness=(u_fRadiusPx-长度(椭圆))2.0;
fHalfBorderDist=长度(edgeVec)-(u_fRadiusPx-fHalfBorderDist厚度);
}
请注意,边框的内部圆角为椭圆。要验证某个点是否在边界上,必须将圆的中心点到当前片段的直线与椭圆相交。看

vec2椭圆_ab=u_fRadiusPx-v2edgeThickness;
vec2 ellipse_isect=edgeVec.xy*ellipse_ab.x*ellipse_ab.y/长度(ellipse_ab*edgeVec.yx);
请参见示例:

(函数loadscene(){
变量画布,gl,vp_大小,prog,bufObj={};
函数initScene(){
canvas=document.getElementById(“ogl画布”);
gl=canvas.getContext(“实验性webgl”);
如果(!gl)
返回;
progDraw=gl.createProgram();
for(设i=0;i<2;++i){
让source=document.getElementById(i==0?“绘制着色器vs”:“绘制着色器fs”).text;
让shaderObj=gl.createShader(i==0?gl.VERTEX\u着色器:gl.FRAGMENT\u着色器);
gl.shaderSource(shaderObj,source);
总编编辑主任(shaderObj);
let status=gl.getShaderParameter(shaderObj,gl.COMPILE_status);
如果(!状态)警报(gl.getShaderInfoLog(shaderObj));
总承包商attachShader(progDraw,shaderObj);
总账链接程序(progDraw);
}
status=gl.getProgramParameter(progDraw,gl.LINK\u status);
如果(!状态)警报(总账getProgramInfoLog(progDraw));
progDraw.inPos=gl.getAttribLocation(progDraw,“inPos”);
progDraw.u_分辨率=gl.getUniformLocation(progDraw,“u_分辨率”);
progDraw.u_厚度顶部=gl.getUniformLocation(progDraw,“u_厚度顶部”);
progDraw.u_厚度底部=gl.getUniformLocation(progDraw,“u_厚度底部”);
progDraw.u_厚度左=gl.getUniformLocation(progDraw,“u_厚度左”);
progDraw.u_ThicknessRight=gl.getUniformLocation(progDraw,“u_ThicknessRight”);
总账使用程序(progDraw);
var pos=[-1,-1,1,-1,1,1,1];
var inx=[0,1,2,0,2,3];
bufObj.pos=gl.createBuffer();
gl.bindBuffer(gl.ARRAY\u BUFFER,bufObj.pos);
总账缓冲数据(总账数组缓冲区、新Float32Array(pos)、总账静态绘图);
bufObj.inx=gl.createBuffer();
bufObj.inx.len=inx.length;
gl.bindBuffer(gl.ELEMENT\u ARRAY\u BUFFER,bufObj.inx);
gl.bufferData(gl.ELEMENT\u ARRAY\u BUFFER、新UINT16阵列(inx)、gl.STATIC\u DRAW);
gl.EnableVertexAttributeArray(progDraw.inPos);
gl.VertexAttributePointer(progDraw.inPos,2,gl.FLOAT,false,0,0);
总帐启用(总帐深度测试);
gl.clearColor(0.0,0.0,0.0,1.0);
window.onresize=调整大小;
调整大小();
请求动画帧(渲染);
}
函数resize(){
//vp_大小=[gl.drawingBufferWidth,gl.drawingBufferHeight];
vp_size=[window.innerWidth,window.innerHeight];
//vp_大小=[256,256]
canvas.width=vp_大小[0];
canvas.height=vp_大小[1];
}
函数渲染(deltaMS){
var top=document.getElementById(“top”).value;
var bottom=document.getElementById(“bottom”).value;
var left=document.getElementById(“left”).value;
var right=document.getElementById(“right”).value;
总图视口(0,0,canvas.width,canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.uniform2f(progDraw.u_分辨率、canvas.width、canvas.height);
德国劳埃德船级社。