CompileShader: примеры (JAVASCRIPT)
compileShader(shader: WebGLShader): undefinedФункция compileShader является частью WebGL API и используется для компиляции исходного кода шейдера (вершинного или фрагментного) в бинарную форму, пригодную для выполнения на графическом процессоре. Вызывается после создания объекта шейдера с помощью createShader и установки его исходного кода через shaderSource.
Аргументы и возвращаемые значения
Функция принимает один обязательный аргумент:
- shader (WebGLShader) - объект шейдера, который необходимо скомпилировать.
Функция не возвращает значения. Успешность компиляции проверяется отдельно через getShaderParameter(shader, gl.COMPILE_STATUS). При неудачной компиляции информацию об ошибках можно получить с помощью getShaderInfoLog(shader).
Примеры использования
Базовый пример компиляции вершинного шейдера:
const gl = canvas.getContext('webgl');
const vertexShaderSource = `
attribute vec4 aPosition;
void main() {
gl_Position = aPosition;
}
`;
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
// Проверка статуса компиляции
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
console.error('Ошибка компиляции шейдера:', gl.getShaderInfoLog(vertexShader));
gl.deleteShader(vertexShader);
}
// Если код корректен, функция завершится без вывода ошибок. // В случае синтаксической ошибки в консоль будет выведен лог, например: // "ERROR: 0:3: '=' : syntax error"
Похожие функции в JavaScript
Прямых аналогов compileShader в стандартном JavaScript нет, так как это специфичная функция WebGL. Однако в контексте этапа работы с шейдерами можно рассмотреть:
- createShader - создает пустой объект шейдера заданного типа (вершинный или фрагментный). Всегда используется перед
compileShader. - shaderSource - связывает исходный код шейдера с созданным объектом. Это обязательный шаг перед компиляцией.
- createProgram и linkProgram - функции для создания и линковки шейдерной программы из скомпилированных шейдеров.
compileShaderявляется подготовительным этапом для них.
Аналоги в других языках
Функция compileShader специфична для графических API. Прямых аналогов в серверных или системных языках не существует. Однако концепция компиляции исполняемого кода (шейдера) присутствует в других графических API:
- OpenGL (C/C++): Используется функция
glCompileShader(GLuint shader), идентичная по назначению и использованию.
// Пример на C с использованием OpenGL
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
const char* vertexShaderSource = "...";
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// Проверка статуса
GLint success;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
// Принцип работы и последовательность вызовов идентичны WebGL.
Типичные ошибки
- Компиляция до установки исходного кода: Вызов
compileShaderдля объекта, созданногоcreateShader, но без предварительного вызоваshaderSource. - Синтаксические ошибки в коде шейдера: Самый частый случай.
- Использование несуществующего объекта: Передача в функцию значения
nullили невалидного идентификатора.
const shader = gl.createShader(gl.VERTEX_SHADER);
gl.compileShader(shader); // Ошибка: исходный код не установлен
COMPILE_STATUS будет false. Лог ошибки может быть пустым или содержать неинформативное сообщение.
const source = `void main() { gl_Position = wrongVariable; }`;
const shader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(shader, source);
gl.compileShader(shader);
COMPILE_STATUS = false. Лог: "ERROR: 0:1: 'wrongVariable' : undeclared identifier"
gl.compileShader(null); // или gl.compileShader(999);
Генерируется ошибка WebGL: "INVALID_VALUE".
Изменения в последних версиях
Функция compileShader остается неизменной и стабильной с момента введения WebGL 1.0. В WebGL 2.0 её сигнатура и поведение не изменились, однако появились новые типы шейдеров (например, для вычислений), которые также компилируются этой функцией после создания с соответствующим константным идентификатором (например, gl.COMPUTE_SHADER).
Расширенные примеры
Пример с компиляцией нескольких шейдеров и агрегированной обработкой ошибок:
function createAndCompileShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
const status = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!status) {
const log = gl.getShaderInfoLog(shader);
const shaderType = type === gl.VERTEX_SHADER ? 'Вершинный' : 'Фрагментный';
console.error(`Ошибка компиляции ${shaderType} шейдера:\n${log}`);
gl.deleteShader(shader);
return null;
}
return shader;
}
// Использование
const vs = createAndCompileShader(gl, gl.VERTEX_SHADER, vertexSource);
const fs = createAndCompileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
if (vs && fs) {
// Оба шейдера скомпилированы успешно, можно создавать программу
const program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
}
Функция возвращает объект шейера при успехе или null при ошибке, логируя детали.
Пример с динамической подстановкой констант в исходный код перед компиляцией:
function compileShaderWithDefines(gl, type, sourceCode, defines) {
let finalSource = '';
for (const [key, value] of Object.entries(defines)) {
finalSource += `#define ${key} ${value}\n`;
}
finalSource += sourceCode;
const shader = gl.createShader(type);
gl.shaderSource(shader, finalSource);
gl.compileShader(shader);
return shader;
}
const shader = compileShaderWithDefines(gl, gl.FRAGMENT_SHADER,
`void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * float(USE_MODIFIER);
}`,
{ USE_MODIFIER: 1 }
);
В исходный код шейдера будет добавлена строка "#define USE_MODIFIER 1" перед компиляцией.