glsl片段着色器颜色添加逻辑
glsl fragment shader color addition logic
我正在尝试将滤镜应用于 WebGL 中的纹理,但我无法理解片段着色器中的颜色是如何叠加的。
比如说我有这个,像这样把红色和黑色加在一起:
vec3 red = vec3(1., 0., 0.);
color.rgb = vec3(0., 0., 0.) + red;
gl_FragColor = color;
如我所料,它输出红色。在红色通道上,我们有 0. + 1. = 1.
但是当对我当前的纹理颜色应用相同的逻辑时,alpha 通道 = 1。
vec3 red = vec3(1., 0., 0.);
color.rgb = texture.rgb + red;
gl_FragColor = color;
我之前和之后得到这个:
黑色保持黑色并使白色区域着色,这是怎么回事?为什么不遵循相同的逻辑?
如何给图像上色,使黑色成为我想要的颜色,而其他所有颜色都是所述颜色的较浅变体。
这是完整的片段着色器代码:
precision mediump float;
uniform sampler2D u_image;
uniform vec2 u_resolution;
uniform vec2 u_position;
uniform vec2 u_pointer;
uniform vec2 u_tex_size;
uniform float u_zoom;
uniform float u_mask_amplitude;
uniform float u_mask_top;
uniform float u_mask_bottom;
// the texCoords passed in from the this.vertex shader.
varying vec2 v_texCoord;
// scale from center
float scale(float a) {
return a / (1. / u_zoom) - (.5 / (1. / u_zoom));
}
vec4 toGrayscale(in vec4 color){
float average = (color.r + color.g + color.b) / 3.0;
return vec4(average, average, average, 1.0);
}
vec4 colorize(in vec4 grayscale, in vec4 color){
return grayscale * color ;
}
float luminance(vec3 rgb){
// Algorithm from Chapter 10 of Graphics Shaders.
const vec3 W = vec3(0.2125, 0.7154, 0.0721);
return dot(rgb, W);
}
float dist(vec2 a, vec2 b){
float x = a.x - b.x;
x = x * u_resolution.x / u_resolution.y;
float y = a.y - b.y;
return sqrt((x * x) + (y * y));
}
void main() {
// Look up a color from the texture.
vec4 color = texture2D(u_image, v_texCoord);
float x = v_texCoord.x;
float y = v_texCoord.y;
// map position
x = x + (u_position.x) / 3.;
y = y + u_position.y;
// repeat & scaling
float repeat_x = mod((x * 3.0), 1.0);
// texture
color = texture2D(u_image, vec2(repeat_x, y));
// mask_offset
vec2 pointer = (u_pointer + u_resolution / 2.) / u_resolution - 1.;
float tex_offset = u_tex_size.x / u_resolution.x;
pointer = pointer / u_zoom;
pointer.x = pointer.x + u_position.x * tex_offset;
pointer.y = pointer.y + u_position.y;
vec2 text_coor = vec2((x * 3.) - 1.5, y - .5);
text_coor.x = text_coor.x * tex_offset;
// text_coor.y = text_coor.y * tex_offset;
// should invert
float PI = 3.1415926535897932384626433832795;
float mask_top = u_mask_top / u_resolution.y;
float mask_bottom = u_mask_bottom / u_resolution.y;
mask_top = mask_top - .5; // .5 is center
mask_bottom = mask_bottom - .5; // .5 is center
float width = 10000./u_resolution.x;
float amplitude = u_mask_amplitude;
bool top = scale(v_texCoord.y) + mask_top > sin(scale(v_texCoord.x) * width - (PI / 2.)) * amplitude;
bool bottom = scale(v_texCoord.y) + mask_bottom < sin(scale(v_texCoord.x) * width - (PI / 2.)) * amplitude;
bool invert = top && bottom;
//
float dist = dist(pointer, text_coor) * 1.5;
if(!invert) dist = dist / 3.;
color.r = color.r + dist * u_zoom;
color.g = color.g + dist * u_zoom;
color.b = color.b + dist * u_zoom;
// greyscale
float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
color = vec4(vec3(gray), 1.0);
// invert
if(invert){
vec3 filter = vec3(0., 0.1215686275, 0.2039215686);
color.rgb = 1. - color.rgb; // invert
color.rgb = color.rgb + filter;
}
gl_FragColor = color;
}
我明白是怎么回事了。我有一个径向遮罩效果,我在应用滤色器之前将纹理乘以一个值,如下所示:
color.r = color.r + dist * u_zoom, 1.;
color.g = color.g + dist * u_zoom, 1.;
color.b = color.b + dist * u_zoom, 1.;
原来这样做每个通道的值都可以大于或小于1。所以当我去添加过滤器时,即使颜色在屏幕上显示为黑色它的值也必须小于,所以添加.2到 -.5 例如保持黑色。
我正在尝试将滤镜应用于 WebGL 中的纹理,但我无法理解片段着色器中的颜色是如何叠加的。
比如说我有这个,像这样把红色和黑色加在一起:
vec3 red = vec3(1., 0., 0.);
color.rgb = vec3(0., 0., 0.) + red;
gl_FragColor = color;
如我所料,它输出红色。在红色通道上,我们有 0. + 1. = 1.
但是当对我当前的纹理颜色应用相同的逻辑时,alpha 通道 = 1。
vec3 red = vec3(1., 0., 0.);
color.rgb = texture.rgb + red;
gl_FragColor = color;
我之前和之后得到这个:
黑色保持黑色并使白色区域着色,这是怎么回事?为什么不遵循相同的逻辑?
如何给图像上色,使黑色成为我想要的颜色,而其他所有颜色都是所述颜色的较浅变体。
这是完整的片段着色器代码:
precision mediump float;
uniform sampler2D u_image;
uniform vec2 u_resolution;
uniform vec2 u_position;
uniform vec2 u_pointer;
uniform vec2 u_tex_size;
uniform float u_zoom;
uniform float u_mask_amplitude;
uniform float u_mask_top;
uniform float u_mask_bottom;
// the texCoords passed in from the this.vertex shader.
varying vec2 v_texCoord;
// scale from center
float scale(float a) {
return a / (1. / u_zoom) - (.5 / (1. / u_zoom));
}
vec4 toGrayscale(in vec4 color){
float average = (color.r + color.g + color.b) / 3.0;
return vec4(average, average, average, 1.0);
}
vec4 colorize(in vec4 grayscale, in vec4 color){
return grayscale * color ;
}
float luminance(vec3 rgb){
// Algorithm from Chapter 10 of Graphics Shaders.
const vec3 W = vec3(0.2125, 0.7154, 0.0721);
return dot(rgb, W);
}
float dist(vec2 a, vec2 b){
float x = a.x - b.x;
x = x * u_resolution.x / u_resolution.y;
float y = a.y - b.y;
return sqrt((x * x) + (y * y));
}
void main() {
// Look up a color from the texture.
vec4 color = texture2D(u_image, v_texCoord);
float x = v_texCoord.x;
float y = v_texCoord.y;
// map position
x = x + (u_position.x) / 3.;
y = y + u_position.y;
// repeat & scaling
float repeat_x = mod((x * 3.0), 1.0);
// texture
color = texture2D(u_image, vec2(repeat_x, y));
// mask_offset
vec2 pointer = (u_pointer + u_resolution / 2.) / u_resolution - 1.;
float tex_offset = u_tex_size.x / u_resolution.x;
pointer = pointer / u_zoom;
pointer.x = pointer.x + u_position.x * tex_offset;
pointer.y = pointer.y + u_position.y;
vec2 text_coor = vec2((x * 3.) - 1.5, y - .5);
text_coor.x = text_coor.x * tex_offset;
// text_coor.y = text_coor.y * tex_offset;
// should invert
float PI = 3.1415926535897932384626433832795;
float mask_top = u_mask_top / u_resolution.y;
float mask_bottom = u_mask_bottom / u_resolution.y;
mask_top = mask_top - .5; // .5 is center
mask_bottom = mask_bottom - .5; // .5 is center
float width = 10000./u_resolution.x;
float amplitude = u_mask_amplitude;
bool top = scale(v_texCoord.y) + mask_top > sin(scale(v_texCoord.x) * width - (PI / 2.)) * amplitude;
bool bottom = scale(v_texCoord.y) + mask_bottom < sin(scale(v_texCoord.x) * width - (PI / 2.)) * amplitude;
bool invert = top && bottom;
//
float dist = dist(pointer, text_coor) * 1.5;
if(!invert) dist = dist / 3.;
color.r = color.r + dist * u_zoom;
color.g = color.g + dist * u_zoom;
color.b = color.b + dist * u_zoom;
// greyscale
float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
color = vec4(vec3(gray), 1.0);
// invert
if(invert){
vec3 filter = vec3(0., 0.1215686275, 0.2039215686);
color.rgb = 1. - color.rgb; // invert
color.rgb = color.rgb + filter;
}
gl_FragColor = color;
}
我明白是怎么回事了。我有一个径向遮罩效果,我在应用滤色器之前将纹理乘以一个值,如下所示:
color.r = color.r + dist * u_zoom, 1.;
color.g = color.g + dist * u_zoom, 1.;
color.b = color.b + dist * u_zoom, 1.;
原来这样做每个通道的值都可以大于或小于1。所以当我去添加过滤器时,即使颜色在屏幕上显示为黑色它的值也必须小于,所以添加.2到 -.5 例如保持黑色。