我正在使用着色器概念在OpenGL ES中使用着色器径向显示图像。最终目标是通过丢弃片段着色器中的片段来创建循环进度条,片段着色器呈现完整的圆形进度纹理。
我已将我的想法here in ShaderToy编码,以便您可以使用它。我似乎无法让它工作,因为没有办法调试我很难搞清楚原因。
这是片段着色器的glsl代码:
float magnitude(vec2 vec)
{
return sqrt((vec.x * vec.x) + (vec.y * vec.y));
}
float angleBetween(vec2 v1, vec2 v2)
{
return acos(dot(v1, v2) / (magnitude(v1) * magnitude(v2)));
}
float getTargetAngle()
{
return clamp(iGlobalTime, 0.0, 360.0);
}
// OpenGL uses upper left as origin by default
bool shouldDrawFragment(vec2 fragCoord)
{
float targetAngle = getTargetAngle();
float centerX = iResolution.x / 2.0;
float centerY = iResolution.y / 2.0;
vec2 center = vec2(centerX, centerY);
vec2 up = vec2(centerX, 0.0) - center;
vec2 v2 = fragCoord - center;
float angleBetween = angleBetween(up, v2);
return (angleBetween >= 0.0) && (angleBetween <= targetAngle);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / iResolution.xy;
if (shouldDrawFragment(fragCoord)) {
fragColor = texture2D(iChannel0, vec2(uv.x, -uv.y));
} else {
fragColor = texture2D(iChannel1, vec2(uv.x, -uv.y));
}
}
它从两侧的底部扫出来。我只是希望它从直接向上指向的矢量中扫出,并以顺时针方向移动。
答案 0 :(得分:3)
试试这段代码:
const float PI = 3.1415926;
const float TWO_PI = 6.2831852;
float magnitude(vec2 vec)
{
return sqrt((vec.x * vec.x) + (vec.y * vec.y));
}
float angleBetween(vec2 v1, vec2 v2)
{
return atan( v1.x - v2.x, v1.y - v2.y ) + PI;
}
float getTargetAngle()
{
return clamp( iGlobalTime, 0.0, TWO_PI );
}
// OpenGL uses upper left as origin by default
bool shouldDrawFragment(vec2 fragCoord)
{
float targetAngle = getTargetAngle();
float centerX = iResolution.x / 2.0;
float centerY = iResolution.y / 2.0;
vec2 center = vec2(centerX, centerY);
float a = angleBetween(center, fragCoord );
return a <= targetAngle;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / iResolution.xy;
if (shouldDrawFragment(fragCoord)) {
fragColor = texture2D(iChannel0, vec2(uv.x, -uv.y));
} else {
fragColor = texture2D(iChannel1, vec2(uv.x, -uv.y));
}
}
<强>解释强>
我做的主要改变是计算两个向量之间的角度的方式:
return atan( v1.x - v2.x, v1.y - v2.y ) + PI;
这是v1和v2之间的差矢量的角度。如果你交换x和y值,它将改变0角度的方向,即如果你试试这个:
return atan( v1.y - v2.y, v1.x - v2.x ) + PI;
圆圈从右边开始而不是向上开始。您还可以反转atan的值以更改动画的方向。
在计算两者之间的角度时,您也不必担心向上矢量,请注意代码只是采用中心与当前frag坐标之间的角度:
float a = angleBetween(center, fragCoord );
其他说明:
记住计算是以弧度为单位,而不是度数,所以我按时更改了钳位(尽管这并不会影响输出):
return clamp( iGlobalTime, 0.0, TWO_PI );
您有一个与您的某个功能同名的变量:
float angleBetween = angleBetween(up, v2);
应避免使用,因为并非所有实现都对此感到满意,在我更改此内容之前,我无法在当前计算机上编译着色器。
答案 1 :(得分:0)
仅更改
下面的两个功能float getTargetAngle()
{
return clamp(iGlobalTime, 0.0, 6.14);
}
bool shouldDrawFragment(vec2 fragCoord)
{
float targetAngle = getTargetAngle();
float centerX = iResolution.x / 2.0;
float centerY = iResolution.y / 2.0;
vec2 center = vec2(centerX, centerY);
vec2 up = vec2(centerX, 0.0) - center;
vec2 v2 = fragCoord - center;
if(fragCoord.x>320.0)// a half width
{
up += 2.0*vec2(up.x,-up.y);
targetAngle *= 2.;
}
else
{
up -= 2.0*vec2(up.x,-up.y);
targetAngle -= 1.57;
}
float angleBetween = angleBetween(up, v2);
return (angleBetween >= 0.0) && (angleBetween <= targetAngle);
}