如何使用着色器制作平滑区域
how to make a smooth region with shader
我想编写一个着色器来通过着色器裁剪一个圆形区域,但似乎不太好,它的边缘不平滑,代码如下:
版本文件:
varying vec3 normal;
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
normal = gl_NormalMatrix*gl_Normal;
gl_Position = ftransform();
}
片段文件:
varying vec3 normal;
uniform sampler2D tex;
uniform sampler2D tex1;
void main()
{
vec4 clr = texture2D(tex, gl_TexCoord[0].st);
float s = gl_TexCoord[0].s - 0.5;
float t = gl_TexCoord[0].t - 0.5;
if ( s<0.0 )
s = 0.0 - s;
if ( t < 0.0 )
t = 0.0 -t;
if ( s*s + t*t >0.5*0.5 )
clr = vec4(0.0, 0.0, 0.0, 0.0);
gl_FragColor = clr;
}
您应该通过在中间区域混合两种颜色来在两个区域之间进行小幅混合。
varying vec3 normal;
uniform sampler2D tex;
uniform sampler2D tex1;
void main()
{
vec4 insideColor = texture2D(tex, gl_TexCoord[0].st);
vec4 outsideColor = vec4(0.0, 0.0, 0.0, 0.0);
float s = gl_TexCoord[0].s - 0.5;
float t = gl_TexCoord[0].t - 0.5;
if ( s<0.0 )
s = 0.0 - s;
if ( t < 0.0 )
t = 0.0 -t;
const float radius = 0.5;
// scale represents the pixel width of the image.
// I used an arbitrary value of 128px but you should set this to
// the actual width.
// The smaller this value, the larger the blending zone will be.
const float scale = 128;
float mixFactor = clamp(scale * (s*s + t*t - radius*radius), 0, 1);
gl_FragColor = mix(insideColor, outsideColor, mixFactor);
}
另外,写着色器时尽量不要使用分支语句,使用向量演算代替多次浮点运算。此着色器的更高效(但仍可改进)版本为:
varying vec3 normal;
uniform sampler2D tex;
uniform sampler2D tex1;
void main()
{
vec4 insideColor = texture2D(tex, gl_TexCoord[0].st);
vec4 outsideColor = vec4(0.0, 0.0, 0.0, 0.0);
vec2 coord = gl_TexCoord[0].st - vec2(0.5, 0.5);
coord = abs(coord);
const float radius = 0.5;
// scale represents the pixel width of the image.
// I used an arbitrary value of 128px but you should set this to
// the actual width.
// The smaller this value, the larger the blending zone will be.
const float scale = 128;
float mixFactor = clamp(scale * (length(coord) - radius), 0, 1);
gl_FragColor = mix(insideColor, outsideColor, mixFactor);
}
我想编写一个着色器来通过着色器裁剪一个圆形区域,但似乎不太好,它的边缘不平滑,代码如下:
版本文件:
varying vec3 normal;
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
normal = gl_NormalMatrix*gl_Normal;
gl_Position = ftransform();
}
片段文件:
varying vec3 normal;
uniform sampler2D tex;
uniform sampler2D tex1;
void main()
{
vec4 clr = texture2D(tex, gl_TexCoord[0].st);
float s = gl_TexCoord[0].s - 0.5;
float t = gl_TexCoord[0].t - 0.5;
if ( s<0.0 )
s = 0.0 - s;
if ( t < 0.0 )
t = 0.0 -t;
if ( s*s + t*t >0.5*0.5 )
clr = vec4(0.0, 0.0, 0.0, 0.0);
gl_FragColor = clr;
}
您应该通过在中间区域混合两种颜色来在两个区域之间进行小幅混合。
varying vec3 normal;
uniform sampler2D tex;
uniform sampler2D tex1;
void main()
{
vec4 insideColor = texture2D(tex, gl_TexCoord[0].st);
vec4 outsideColor = vec4(0.0, 0.0, 0.0, 0.0);
float s = gl_TexCoord[0].s - 0.5;
float t = gl_TexCoord[0].t - 0.5;
if ( s<0.0 )
s = 0.0 - s;
if ( t < 0.0 )
t = 0.0 -t;
const float radius = 0.5;
// scale represents the pixel width of the image.
// I used an arbitrary value of 128px but you should set this to
// the actual width.
// The smaller this value, the larger the blending zone will be.
const float scale = 128;
float mixFactor = clamp(scale * (s*s + t*t - radius*radius), 0, 1);
gl_FragColor = mix(insideColor, outsideColor, mixFactor);
}
另外,写着色器时尽量不要使用分支语句,使用向量演算代替多次浮点运算。此着色器的更高效(但仍可改进)版本为:
varying vec3 normal;
uniform sampler2D tex;
uniform sampler2D tex1;
void main()
{
vec4 insideColor = texture2D(tex, gl_TexCoord[0].st);
vec4 outsideColor = vec4(0.0, 0.0, 0.0, 0.0);
vec2 coord = gl_TexCoord[0].st - vec2(0.5, 0.5);
coord = abs(coord);
const float radius = 0.5;
// scale represents the pixel width of the image.
// I used an arbitrary value of 128px but you should set this to
// the actual width.
// The smaller this value, the larger the blending zone will be.
const float scale = 128;
float mixFactor = clamp(scale * (length(coord) - radius), 0, 1);
gl_FragColor = mix(insideColor, outsideColor, mixFactor);
}