Webgl 在顶点着色器中计算颜色值?
因此,我目前正在使用一些噪波函数来创建一些程序性地形。根据我的理解,我们可以使用一个噪波函数,它接受一个2D向量并返回一个浮点。然后,我们可以将该浮动解释为空间中该点的“高度”。我们还可以将此浮动解释为相应片段的颜色。结果,我们最终得到了顶部为白色,底部为黑色的山脉 现在,我基本上在顶点和片段着色器中进行相同的计算,以获得相同的值: 顶点着色器:Webgl 在顶点着色器中计算颜色值?,webgl,Webgl,因此,我目前正在使用一些噪波函数来创建一些程序性地形。根据我的理解,我们可以使用一个噪波函数,它接受一个2D向量并返回一个浮点。然后,我们可以将该浮动解释为空间中该点的“高度”。我们还可以将此浮动解释为相应片段的颜色。结果,我们最终得到了顶部为白色,底部为黑色的山脉 现在,我基本上在顶点和片段着色器中进行相同的计算,以获得相同的值: 顶点着色器: uniform sampler2D texture; uniform float time; uniform float speed; varyin
uniform sampler2D texture;
uniform float time;
uniform float speed;
varying vec3 pos;
varying vec2 vUv;
float random (in vec2 st) {
return fract(sin(dot(st.xy,
vec2(12.9898,78.233)))*
43758.5453123);
}
// Based on Morgan McGuire @morgan3d
// https://www.shadertoy.com/view/4dS3Wd
float noise (in vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);
// Four corners in 2D of a tile
float a = random(i);
float b = random(i + vec2(1.0, 0.0));
float c = random(i + vec2(0.0, 1.0));
float d = random(i + vec2(1.0, 1.0));
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(a, b, u.x) +
(c - a)* u.y * (1.0 - u.x) +
(d - b) * u.x * u.y;
}
#define OCTAVES 8
float fbm ( vec2 st) {
// Initial values
float value = 0.;
float amplitud = .5;
float frequency = 0.;
//
// Loop of octaves
for (int i = 0; i < OCTAVES; i++) {
value += amplitud * noise(st);
st *= 2.1;
amplitud *= .6;
}
return value;
}
float pattern( in vec2 p )
{
vec2 q = vec2( fbm( p + vec2(0.0,0.0) ),
fbm( p + vec2(5.2,1.3) ) );
vec2 r = vec2( fbm( p + 4.0*q + vec2(1.7,9.2) ),
fbm( p + 4.0*q + vec2(8.3,2.8) ) );
return fbm( p + 4.0*r );
}
void main(){
vUv = uv + time;
pos = position;
float n = pattern(pos.xy);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position +
normal*n*.035, 1.);
}
但是,当我尝试此操作时,传递的值似乎并不相同。高度贴图完全消失。我猜这与片段着色器计算每个片段的颜色有关,而不是每个顶点?到底发生了什么?有哪些方法可以优化此代码?我觉得不必重复这么多代码。对网格缓冲区顶点的每个顶点执行时,对绘制的每个片段至少执行一次。来自的输出变量被传递到管道的下一个阶段。如果下一个阶段是(在WebGL中是这种情况),则的输出变量将根据渲染原语上的插值,并传递到的输入变量 注意,
gl\u位置
每个顶点只计算一次,gl\u FragColor
每个片段计算一次。这导致定义几何体和定义片段的颜色
出于优化的原因,可以对每个顶点计算一次高度贴图的高度,并让图形管道为顶点之间的碎片着色插值高度
您的代码应该是这样的:
顶点着色器
Frgament着色器
注意,我添加了一个函数,该函数将高度贴图的颜色设置为类似彩虹的颜色。你说的“高度贴图完全消失”是什么意思。也许可以添加第一个案例和第二个案例的图片?你的简历似乎有很多细节。如果在片段着色器中计算,您将看到顶点之间的细节。如果只是从顶点着色器传递它,则只会看到每个顶点之间的插值。顶点之间的距离越远,你看到的细节就越少。那么,是否有一种解决方法可以在避免在顶点和片段着色器中运行噪波计算的同时实现相同的细节级别?最初,我的平面看起来是这样的:这是当我计算每个顶点和每个片段的噪波时。使用下面Rabbi76的解决方案,我似乎得到了每个顶点之间的插值,正如您所说:有没有任何方法可以在第一个屏幕截图中以更优化的方式实现效果?非常感谢您的反馈!接下来,我将考虑两种生成上述纹理的方法。一个选项是在平面上绘制高度贴图,截屏并在运行时将其用作高度贴图/颜色贴图。另一个选项是使用Javascript进行高度计算,并将值作为属性传递到着色器中。
uniform sampler2D texture;
uniform float time;
varying vec2 vUv;
varying vec3 pos;
float random (in vec2 st) {
return fract(sin(dot(st.xy,
vec2(12.9898,78.233)))*
43758.5453123);
}
// Based on Morgan McGuire @morgan3d
// https://www.shadertoy.com/view/4dS3Wd
float noise (in vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);
// Four corners in 2D of a tile
float a = random(i);
float b = random(i + vec2(1.0, 0.0));
float c = random(i + vec2(0.0, 1.0));
float d = random(i + vec2(1.0, 1.0));
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(a, b, u.x) +
(c - a)* u.y * (1.0 - u.x) +
(d - b) * u.x * u.y;
}
#define OCTAVES 8
float fbm ( vec2 st) {
// Initial values
float value = 0.;
float amplitud = .5;
float frequency = 0.;
//
// Loop of octaves
for (int i = 0; i < OCTAVES; i++) {
value += amplitud * noise(st);
st *= 2.1;
amplitud *= .6;
}
return value;
}
float pattern( in vec2 p )
{
vec2 q = vec2( fbm( p + vec2(0.0,0.0) ),
fbm( p + vec2(5.2,1.3) ) );
vec2 r = vec2( fbm( p + 4.0*q + vec2(1.7,9.2) ),
fbm( p + 4.0*q + vec2(8.3,2.8) ) );
return fbm( p + 4.0*r );
}
void main(){
vec2 q;
vec2 r;
vec2 j = vec2(0., 1.);
float p = pattern(pos.xy);
vec4 color = texture2D(texture, vUv + p/5.);
// gl_FragColor = vec4(color.rgb, p);
gl_FragColor = vec4(p);
}
//vertex shader
varying float noise;
void main(){
noise = pattern(position.xy);
//rest of code
}
//fragment shader
varying float noise;
void main(){
//do something with noise value
}
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
uniform float time;
uniform float speed;
varying vec3 pos;
varying vec2 vUv;
varying float mapH;
float pattern( in vec2 p );
void main()
{
vUv = uv + time;
pos = position;
mapH = pattern(pos.xy);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position + normal*mapH*.035, 1.0);
}
varying vec2 vUv;
varying vec3 pos;
varying float mapH;
vec3 HeightToRGB(in float H)
{
float B = abs(H * 5.0 - 3.0) - 1.0;
float G = 2.0 - abs(H * 5.0 - 2.0);
float R = 2.0 - abs(H * 5.0 - 4.0);
return clamp( vec3(R,G,B), 0.0, 1.0 );
}
void main()
{
vec3 color = HeightToRGB( clamp(mapH, 0.0, 1.0) );
gl_FragColor = vec4( color, 1.0 );
}