RawShaderMaterial — это материал в Three.js, позволяющий
полностью управлять шейдерами без добавления автоматических uniform и
макросов, которые присутствуют в стандартных материалах, таких как
ShaderMaterial. В отличие от ShaderMaterial,
RawShaderMaterial не внедряет стандартные uniform вроде
projectionMatrix, modelViewMatrix и других,
что даёт полный контроль над графическим конвейером.
Применение этого материала оправдано, когда необходима строгая кастомизация шейдеров, использование нестандартных матриц, уникальных вычислений или оптимизация под специфические задачи рендеринга.
Создание материала требует определения двух основных шейдеров:
вершинного (vertexShader) и фрагментного
(fragmentShader).
import * as THREE from 'three';
const material = new THREE.RawShaderMaterial({
vertexShader: `
precision highp float;
attribute vec3 position;
uniform mat4 myCustomMatrix;
void main() {
gl_Position = myCustomMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
precision highp float;
uniform vec3 color;
void main() {
gl_FragColor = vec4(color, 1.0);
}
`,
uniforms: {
myCustomMatrix: { value: new THREE.Matrix4() },
color: { value: new THREE.Color(0xff0000) }
}
});
Ключевые моменты:
precision highp float; необходим в каждом шейдере для
корректной работы с плавающей точкой.RawShaderMaterial не добавляет стандартные переменные,
такие как modelViewMatrix или
projectionMatrix.В RawShaderMaterial нет автоматических
атрибутов. Для передачи данных вершин необходимо
использовать:
position — координаты вершин (обычно
BufferGeometry содержит этот атрибут).normal — нормали, если требуется освещение.uv — координаты текстур.Все дополнительные данные необходимо передавать вручную через
uniforms или создавать свои BufferAttribute
для geometry:
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([
-1, -1, 0,
1, -1, 0,
0, 1, 0
]);
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
В отличие от ShaderMaterial,
RawShaderMaterial не предоставляет автоматические
матрицы:
modelViewMatrixprojectionMatrixnormalMatrixЕсли необходимо использовать трансформации сцены, их следует передавать вручную через uniform:
const customMatrix = new THREE.Matrix4();
mesh.updateMatrixWorld();
customMatrix.multiplyMatrices(camera.projectionMatrix, mesh.matrixWorld);
material.uniforms.myCustomMatrix.value.copy(customMatrix);
Это даёт полный контроль над тем, какие матрицы и в каком порядке применяются к вершинам.
Для реализации освещения вручную необходимо передавать нормали и позиции источников света через uniform:
uniforms: {
lightPosition: { value: new THREE.Vector3(10, 10, 10) },
normalMatrix: { value: new THREE.Matrix3() }
}
В вершинном шейдере нормали преобразуются с помощью
normalMatrix:
vec3 transformedNormal = normalize(normalMatrix * normal);
Во фрагментном шейдере можно вычислить диффузное освещение:
float diffuse = max(dot(transformedNormal, normalize(lightPosition - fragPosition)), 0.0);
gl_FragColor = vec4(diffuse * color, 1.0);
Работа с текстурами полностью ручная. Необходимо объявлять uniform
sampler2D и передавать координаты uv через
атрибут:
uniform sampler2D myTexture;
varying vec2 vUv;
void main() {
vec4 texColor = texture2D(myTexture, vUv);
gl_FragColor = texColor;
}
Передача текстуры из Jav * aScript:
material.uniforms.myTexture = { value: new THREE.TextureLoader().load('texture.png') };
highp,
mediump) в шейдерах.BufferGeometry для передачи любых
атрибутов.RawShaderMaterial является идеальным инструментом для
проектов, где требуется максимальная кастомизация рендеринга и отказ от
стандартных uniform Three.js, создавая полностью контролируемый
графический конвейер.