}
12.6. Гранит
С помощью шума легко имитировать практически любой материал. В данном примере сымитирован серый каменистый материал с небольшими черными вкраплениями. Чтобы создать относительно высокочастотную текстуру шума, используется только четвертый компонент (с наивысшей частотой). Он масштабируется с определенным коэффициентом, чтобы получить определенный уровень интенсивности, а затем это значение подставляется для всех остальных компонентов (красного, зеленого и синего). Результат приведен в листинге 12.7 - так создается поверхность, похожая на гранит (см. цветной рис. 20).
Листинг 12.7. Фрагментный шейдер гранитной поверхности
varying float Lightlntensity; varying vec3 MCposition;
uniform sampler3D Noise: uniform float NoiseScale:
void main(void)
{
vec4 noisevec = texture3D(Noise, NoiseScale * MCposition): float intensity = min(1.0, noisevec[3] * 18.0): vec3 color = vec3 (intensity * Lightlntensity): gl_FragColor = vec4 (color. 1.0):
12.7.2. Фрагментный шейдер
В листинге 12.8 приведен фрагментный шейдер деревянной поверхности. Листинг 12.8. Фрагментный шейдер деревянной поверхности
varying float Lightlntensity; varying vec3 MCposition;
uniform sampler3D Noise;
uniform vec3 LightWood: uniform vec3 QarkWood: uniform float RingFreq: uniform float LightGrains: uniform float DarkGrains: uniform float GrainThreshold; uniform vec3 NoiseScale: uniform float Noisiness: uniform float GrainScale;
void main(void)
{
vec3 noisevec = vec3 (texture3D(Noise. MCposition * NoiseScale) *
Noisiness); vec3 location = MCposition + noisevec:
float dist = sqrtdocation.x * location.x + location.z * location.z): dist *= RingFreq:
float r = fract(dist + noisevec[0] + noisevec[i] + noisevec[2]) * 2.0:
if (r > 1.0) r = 2.0 - r;
vec3 color - mix(LightWood, DarkWood, r);
r = fract((MCposition.x + MCposition,z) * GrainScale + 0.5): noisevec[2] *= r; if (r < GrainThreshold)
color += LightWood * LightGrains * noisevec[2]: else
color -= LightWood * DarkGrains * noisevec[2];
color *= Lightlntensity: gl_FragColor = vec4 (color. 1.0);
}
Как видно из листинга, несколько параметров, заданных с помощью uniform-переменных, помогают манипулировать видом поверхности из приложения. Как и в большинстве процедурных шейдеров, здесь для наложения текстуры используются координаты объекта. В данном случае координаты объекта умножаются на Noi seScal е (переменная типа vec3, с помощью которой можно масштабировать изображение отдельно в направлениях х, у и z), а результат становится индексом в заданной трехмерной текстуре шума. Значения шума, полученные из текстуры, масштабируются по значению Noi si ness, что позволяет увеличить или уменьшить влияние шума на изображение.
Здесь дерево будет считаться последовательностью чередующихся темных и светлых концентрических колец. Чтобы поверхность выглядела более реалистично, нужно добавить к координатам объекта вектор шума. Первая (низкочастотная) октава добавляется к дг-координате, третья октава добавляется к 2-коор-динате (а г/-координата вообще не используется). В результате получатся кольца, которые будут несколько отличаться по ширине и расстоянию от центра дерева.