下面是一个输出纹素的GLSL片段着色器 如果给定的纹理坐标在一个框内,否则为a 颜色输出。这只是感觉愚蠢和那里 必须是一种没有分支的方法吗?
uniform sampler2D texUnit;
varying vec4 color;
varying vec2 texCoord;
void main() {
vec4 texel = texture2D(texUnit, texCoord);
if (any(lessThan(texCoord, vec2(0.0, 0.0))) ||
any(greaterThan(texCoord, vec2(1.0, 1.0))))
gl_FragColor = color;
else
gl_FragColor = texel;
}
下面是没有分支的版本,但它仍然感觉很笨拙。 “纹理坐标夹紧”的最佳实践是什么?
uniform sampler2D texUnit;
varying vec4 color;
varying vec4 labelColor;
varying vec2 texCoord;
void main() {
vec4 texel = texture2D(texUnit, texCoord);
bool outside = any(lessThan(texCoord, vec2(0.0, 0.0))) ||
any(greaterThan(texCoord, vec2(1.0, 1.0)));
gl_FragColor = mix(texel*labelColor, color,
vec4(outside,outside,outside,outside));
}
我将纹素夹在该区域,标签是 - 纹理s&在这种情况下,t坐标将介于0和1之间。否则,我使用棕色,而标签不是。
请注意,我还可以构建一个代码的分支版本,该代码在不执行纹理查找时不需要。这会比总是执行纹理查找的非分支版本更快吗?也许是时候进行一些测试......
答案 0 :(得分:14)
使用step
功能来避免分支并获得最佳性能:
// return 1 if v inside the box, return 0 otherwise
float insideBox(vec2 v, vec2 bottomLeft, vec2 topRight) {
vec2 s = step(bottomLeft, v) - step(topRight, v);
return s.x * s.y;
}
float insideBox3D(vec3 v, vec3 bottomLeft, vec3 topRight) {
vec3 s = step(bottomLeft, v) - step(topRight, v);
return s.x * s.y * s.z;
}
void main() {
vec4 texel = texture2D(texUnit, texCoord);
float t = insideBox(v_position, vec2(0, 0), vec2(1, 1));
gl_FragColor = t * texel + (1 - t) * color;
}
答案 1 :(得分:4)
基于damphat的回答,我实现了一个函数,用于在矩形内外之间平滑过渡:
float inside_rectangle_smooth(vec2 p, vec2 bottom_left, vec2 top_right, float transition_area)
{
vec2 s = smoothstep(bottom_left, bottom_left + vec2(transition_area), p) -
smoothstep(top_right - vec2(transition_area), top_right, p);
return(s.x * s.y);
}
使用“transition_area”参数调整矩形内外之间过渡区域的大小。转换在
我成功地使用此功能来淡化引擎中的阴影(使用阴影贴图坐标)。
演示:
上图是通过调用:
产生的
inside_rectangle_smooth(v_texture_coordinate, vec2(0.0), vec2(1.0), 0.1)
答案 2 :(得分:1)
我只是想解决这个问题。通过https://github.com/stackgl/shader-school
bool inBox(highp vec2 lo, highp vec2 hi, highp vec2 p) {
bvec4 b = bvec4(greaterThan(p, lo), lessThan(p, hi));
return all(b);
}
答案 3 :(得分:0)
以下是两个可能的实现:
(请评论它们的性能,尤其是当您碰巧对它们进行基准测试时。)
通过一次调用step()
完成比较:
bool rectContainsPoint(vec2 rectBottomLeft, vec2 rectTopRight, vec2 point)
{
vec4 pt = vec4(point, -point);
vec4 r = vec4(rectBottomLeft, -rectTopRight);
vec4 inside = step(r, pt);
return all(bvec4(inside));
}
这种简单的实现方式会更快吗?还是比较慢?
bool rectContainsPoint(vec2 rectBottomLeft, vec2 rectTopRight, vec2 point)
{
return all(point == clamp(point, rectBottomLeft, rectTopRight));
}