【发布时间】:2021-09-15 09:23:17
【问题描述】:
该应用基于 PyOpenGL(核心配置文件)并使用正交投影。我必须在四边形(2 个三角形)上绘制几个不同的 2d 形状。
我发现了一个非常棒的article 使用 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 坐标来指定 borderThickness 和 radius,因此我没有得到一致的边框。如果您在图像中看到,水平边框比垂直边框稍宽。我更喜欢在像素大小中使用 borderThickness 和 radius。这个想法是在矩形周围获得一致的边框,而与屏幕尺寸无关。
问题 3 使外面的蓝色透明。
问题 4 正如我所提到的,我最近开始学习 GLSL,在某些地方我读到过多的“if”条件会极大地影响着色器的性能,并且您可能会不必要地使用它们。此代码中已经存在两个“if”条件,我不确定它们是否可以省略。
【问题讨论】:
标签: python opengl glsl pyopengl