OpenGL ES 2.0/3.0 中的虹彩效果。替换黑色区域
Iridescence effect in OpenGL ES 2.0/3.0. Replacing the black area
我正在尝试对对象应用彩虹色效果。为此,我使用了以下着色器:
顶点着色器:
#version 300 es
uniform mat4 u_mvpMatrix;
uniform mat4 u_mvMatrix;
uniform mat4 u_vMatrix;
in vec4 a_position;
in vec2 a_textureCoordinates;
in vec3 a_normal;
out vec2 v_textureCoordinates;
out float v_CosViewAngle;
out float v_LightIntensity;
void main() {
// transform normal orientation into eye space
vec3 modelViewNormal = mat3(u_mvMatrix) * a_normal;
vec3 modelViewVertex = vec3(u_mvMatrix * a_position);
mediump vec3 eyeDirection = normalize(-modelViewVertex);
vec3 lightVector = normalize(lightPosition - modelViewVertex);
lightVector = mat3(u_vMatrix) * lightVector;
v_LightIntensity = max(dot(lightVector, modelViewNormal), 0.0);
v_CosViewAngle = max(dot(eyeDirection, modelViewNormal), 0.1);
...
}
片段着色器:
#version 300 es
precision lowp float;
in vec2 v_textureCoordinates;
in float v_CosViewAngle;
in float v_LightIntensity;
out vec4 outColor;
uniform sampler2D s_texture;
// wave numbers for the iridescence effect: k = 2.0 * pi / wavelength (nm).
const mediump float PI = 3.141592654;
const mediump vec3 rgbK = 2.0 * PI * vec3(1.0/475.0, 1.0/510.0, 1.0/650.0);
const mediump float iridescence = 4.4;
const mediump float minThickness = 80.0;
const mediump float maxVariation = 50.0;
void main() {
float thickness = texture(s_texture, v_textureCoordinates).r
* maxVariation + minThickness; // or texture2D() - in OpenGL ES 2.0
float delta = (thickness / v_LightIntensity) + (thickness / v_CosViewAngle);
lowp vec3 color = cos(delta * rgbK) * iridescence * v_LightIntensity;
vec4 resultColor = vec4(color, 1.0);
outColor = resultColor;
}
结果:
问题:如何用普通贴图替换黑色区域?换句话说,要有一个共同的纹理而不是黑色。
注:我试id为:
vec4 resultColor = texture(s_texture, v_textureCoordinates) * (vec4(color, 1.0) + 0.5);
等等:
if (color == vec3(0.0, 0.0, 0.0)) { // if black color
resultColor = texture(s_texture, v_textureCoordinates);
} else {
resultColor = texture(s_texture, v_textureCoordinates) * (vec4(color, 1.0) + 0.5);
}
但这并没有解决问题。
提前致谢!
着色器的代码部分取自 PVRShamanGUI。
更新:
根据 Rabbid76 的回答,我也使用了 delta,但只是为了检查波长(以 nm 为单位):
...
if (delta > 1700.0 || delta < 370.0) {
resultColor = texture(s_texture, v_textureCoordinates) * v_commonLight;
} else {
resultColor = vec4(color, 1.0);
}
outColor = resultColor;
结果:
颜色不是全黑,颜色通道的值不完全是0.0。计算平均颜色(灰度)和mix
依赖于灰度的颜色和纹理颜色:
vec4 texturColor = texture(s_texture, v_textureCoordinates);
float gray_scale = (color.r + color.g + color.b) / 3.0;
resultColor = mix(texturColor, color, gray_scale);
另一种可能性是根据 delta
的值混合颜色:
vec4 texturColor = texture(s_texture, v_textureCoordinates);
resultColor = mix(texturColor, color, delta);
我正在尝试对对象应用彩虹色效果。为此,我使用了以下着色器:
顶点着色器:
#version 300 es
uniform mat4 u_mvpMatrix;
uniform mat4 u_mvMatrix;
uniform mat4 u_vMatrix;
in vec4 a_position;
in vec2 a_textureCoordinates;
in vec3 a_normal;
out vec2 v_textureCoordinates;
out float v_CosViewAngle;
out float v_LightIntensity;
void main() {
// transform normal orientation into eye space
vec3 modelViewNormal = mat3(u_mvMatrix) * a_normal;
vec3 modelViewVertex = vec3(u_mvMatrix * a_position);
mediump vec3 eyeDirection = normalize(-modelViewVertex);
vec3 lightVector = normalize(lightPosition - modelViewVertex);
lightVector = mat3(u_vMatrix) * lightVector;
v_LightIntensity = max(dot(lightVector, modelViewNormal), 0.0);
v_CosViewAngle = max(dot(eyeDirection, modelViewNormal), 0.1);
...
}
片段着色器:
#version 300 es
precision lowp float;
in vec2 v_textureCoordinates;
in float v_CosViewAngle;
in float v_LightIntensity;
out vec4 outColor;
uniform sampler2D s_texture;
// wave numbers for the iridescence effect: k = 2.0 * pi / wavelength (nm).
const mediump float PI = 3.141592654;
const mediump vec3 rgbK = 2.0 * PI * vec3(1.0/475.0, 1.0/510.0, 1.0/650.0);
const mediump float iridescence = 4.4;
const mediump float minThickness = 80.0;
const mediump float maxVariation = 50.0;
void main() {
float thickness = texture(s_texture, v_textureCoordinates).r
* maxVariation + minThickness; // or texture2D() - in OpenGL ES 2.0
float delta = (thickness / v_LightIntensity) + (thickness / v_CosViewAngle);
lowp vec3 color = cos(delta * rgbK) * iridescence * v_LightIntensity;
vec4 resultColor = vec4(color, 1.0);
outColor = resultColor;
}
结果:
问题:如何用普通贴图替换黑色区域?换句话说,要有一个共同的纹理而不是黑色。
注:我试id为:
vec4 resultColor = texture(s_texture, v_textureCoordinates) * (vec4(color, 1.0) + 0.5);
等等:
if (color == vec3(0.0, 0.0, 0.0)) { // if black color
resultColor = texture(s_texture, v_textureCoordinates);
} else {
resultColor = texture(s_texture, v_textureCoordinates) * (vec4(color, 1.0) + 0.5);
}
但这并没有解决问题。
提前致谢!
着色器的代码部分取自 PVRShamanGUI。
更新: 根据 Rabbid76 的回答,我也使用了 delta,但只是为了检查波长(以 nm 为单位):
...
if (delta > 1700.0 || delta < 370.0) {
resultColor = texture(s_texture, v_textureCoordinates) * v_commonLight;
} else {
resultColor = vec4(color, 1.0);
}
outColor = resultColor;
结果:
颜色不是全黑,颜色通道的值不完全是0.0。计算平均颜色(灰度)和mix
依赖于灰度的颜色和纹理颜色:
vec4 texturColor = texture(s_texture, v_textureCoordinates);
float gray_scale = (color.r + color.g + color.b) / 3.0;
resultColor = mix(texturColor, color, gray_scale);
另一种可能性是根据 delta
的值混合颜色:
vec4 texturColor = texture(s_texture, v_textureCoordinates);
resultColor = mix(texturColor, color, delta);