CompileShader: примеры (JAVASCRIPT)

Компиляция шейдеров в WebGL с помощью функции compileShader
Раздел: WebGL, Шейдеры
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.

Типичные ошибки

  1. Компиляция до установки исходного кода: Вызов compileShader для объекта, созданного createShader, но без предварительного вызова shaderSource.
  2. const shader = gl.createShader(gl.VERTEX_SHADER);
    gl.compileShader(shader); // Ошибка: исходный код не установлен
    COMPILE_STATUS будет false. Лог ошибки может быть пустым или содержать неинформативное сообщение.
  3. Синтаксические ошибки в коде шейдера: Самый частый случай.
  4. 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"
  5. Использование несуществующего объекта: Передача в функцию значения null или невалидного идентификатора.
  6. gl.compileShader(null); // или gl.compileShader(999);
    Генерируется ошибка WebGL: "INVALID_VALUE".

Изменения в последних версиях

Функция compileShader остается неизменной и стабильной с момента введения WebGL 1.0. В WebGL 2.0 её сигнатура и поведение не изменились, однако появились новые типы шейдеров (например, для вычислений), которые также компилируются этой функцией после создания с соответствующим константным идентификатором (например, gl.COMPUTE_SHADER).

Расширенные примеры

Пример с компиляцией нескольких шейдеров и агрегированной обработкой ошибок:

Пример javascript
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 при ошибке, логируя детали.

Пример с динамической подстановкой констант в исходный код перед компиляцией:

Пример javascript
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" перед компиляцией.

JS compileShader function comments

En
CompileShader Compiles a WebGLShader