该应用程序基于PyOpenGL(岩心剖面)并使用正交投影。我必须在四边形(2个三角形)上绘制几个不同的2d形状
我发现在使用SDF渲染2d/3d形状方面有一个非常好的方法。我尝试的第一个形状是带边框的圆角矩形。这个Shadertoy示例完全符合我的要求。以下是我的两个着色器:
顶点着色器
#version 330 core
// VERTEX SHADER
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 tex_coord;
uniform mat4 mvp;
void main()
{
gl_Position = mvp * vec4(aPos, 1.0);
tex_coord = aTexCoord;
}
片段着色器
#version 330 core
// FRAGMENT SHADER
uniform vec4 in_color;
in vec2 tex_coord;
vec2 resolution = vec2(800, 600);
float aspect = resolution.x / resolution.y;
const float borderThickness = 0.01;
const vec4 borderColor = vec4(1.0, 1.0, 0.0, 1.0);
const vec4 fillColor = vec4(1.0, 0.0, 0.0, 1.0);
const float radius = 0.05;
float RectSDF(vec2 p, vec2 b, float r)
{
vec2 d = abs(p) - b + vec2(r);
return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - r;
}
void main() {
// https://www.shadertoy.com/view/ltS3zW
vec2 centerPos = tex_coord - vec2(0.5, 0.5); // <-0.5,0.5>
//vec2 centerPos = (tex_coord/resolution - vec2(0.5)) * 2.0;
//centerPos *= aspect; // fix aspect ratio
//centerPos = (centerPos - resolution.xy) * 2.0;
float fDist = RectSDF(centerPos, vec2(0.5, 0.5), radius);
vec4 v4FromColor = borderColor; // Always the border color. If no border, this still should be set
vec4 v4ToColor = vec4(0.0, 0.0, 1.0, 1.0); // Outside color
if (borderThickness > 0.0)
{
if (fDist < 0.0)
{
v4ToColor = fillColor;
}
fDist = abs(fDist) - borderThickness;
}
float fBlendAmount = smoothstep(-0.01, 0.01, fDist);
// final color
gl_FragColor = mix(v4FromColor, v4ToColor, fBlendAmount);
}
以及两个输出之间的差异:
问题1 在Shadertoy的例子中,边界是整洁的,没有模糊,我的边界是模糊的
问题2 我使用ndc坐标来指定边界厚度和半径,因此我没有得到一致的边界。如果您在图像中看到,水平边框比垂直边框略宽。我更喜欢在像素大小中使用边界厚度和半径。其思想是在矩形周围获得一致的边框,而与屏幕尺寸无关
问题3 使外部蓝色透明
问题4 正如我所提到的,我最近开始学习GLSL,在一些地方我读到过太多的“如果”条件将极大地影响着色器性能,并且很可能您可能不必要地使用它们。这段代码中已经存在两个“if”条件,我不确定它们是否可以省略
使用Uniform(
rectSize
)以像素为单位指定矩形的大小。纹理坐标(tex_coord
)需要在[0.0,1.0]范围内。计算矩形(rectSize * tex_coord
)中的像素位置。现在可以指定半径和边缘厚度(以像素为单位):使用Blending使外部透明。为此,外部颜色的alpha通道必须为0。(例如
vec4(0.0)
)最简单的例子:
相关问题 更多 >
编程相关推荐