基于屏幕GLSL中心角度的颜色片段

时间:2014-09-20 10:25:42

标签: opengl glsl

作为学习片段着色器/矢量数学的练习,我正在尝试编写一个后处理着色器,根据矢量PC的角度(以弧度表示),在P和中心之间为屏幕上的每个点P着色。屏幕C.

为了简单起见,我将以灰度方式进行此操作,但可以在这里看到我想要的效果的一个很好的例证,随着角度的变化色调变化,色调形成一个循环。

http://demosthenes.info/assets/images/hsl-color-wheel-trans.png

我四处搜寻,寻找有关找到矢量之间角度的信息,从这些例子中我已经到了这里:

#version 110

uniform sampler2D tex0; //Color info

void main()
{
    vec2 ScreenCenter = vec2(0.5 , 0.5);
    vec2 texCoord = gl_TexCoord[0].st;
    vec2 deltaTexCoord = ( texCoord - ScreenCenter.xy);    
    float angle = dot(deltaTexCoord , vec2(0,-1));

    //I've made attempts here to mess with acos as well as angle=pow(angle, somefloat) and
    //have not gotten desired results

    gl_FragColor = vec4( angle , angle, angle, 1.0 );
}

但是这段代码会产生线性渐变而不是我想要的效果。

2 个答案:

答案 0 :(得分:3)

最简单的方法是使用带有两个参数的内置GLSL函数atan()

float angle = atan(deltaTexCoord.y, deltaTexCoord.x);

这对应于您可能从C / C ++中熟悉的atan2 function。与使用acos()相比,主要优势在于它为您提供了全范围的角度[-pi,pi],而由acos()生成的角度仅在[0,pi]范围内,因此对于圆圈的下半部分是不正确的。使用atan(y, x)时,也无需规范化输入值。

答案 1 :(得分:0)

你几乎就在那里。两个向量的内积(也称为标量或点积)是向量之间的角度乘以向量长度乘积的余弦。因此,为了回到角度,你将点积映射到余弦的倒数,并首先对矢量进行归一化(0,1)已经是单位长度。

float angle = acos( dot(normalize(deltaTexCoord), vec2(0, -1)) );

请注意,角度以弧度为单位报告,从0到2pi。