ShaderSource: примеры (JAVASCRIPT)
shaderSource(shader: WebGLShader, source: String): undefinedОписание функции shaderSource
Функция shaderSource(shader, source) является методом объекта WebGLRenderingContext. Она связывает исходный код шейдера с объектом шейдера WebGLShader. Используется при настройке конвейера рендеринга WebGL для определения программируемых этапов обработки графики.
Аргументы:
shader- объект типа WebGLShader, созданный функцией createShadersource- строка, содержащая исходный код шейдера на языке GLSL
Возвращаемое значение: Отсутствует (void).
Функция не проверяет синтаксис GLSL, а лишь загружает код. Валидация происходит на этапе компиляции через compileShader.
Базовые примеры использования
Создание вершинного шейдера:
const canvas = document.getElementById('canvas');
const gl = canvas.getContext('webgl');
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
const vertexShaderSource = `
attribute vec4 aPosition;
void main() {
gl_Position = aPosition;
}
`;
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);Шейдер создан, код загружен в объект
Создание фрагментного шейдера:
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
const fragmentShaderSource = `
precision mediump float;
uniform vec4 uColor;
void main() {
gl_FragColor = uColor;
}
`;
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);Фрагментный шейдер готов к компиляции
Похожие функции в JavaScript
createShader - создает пустой объект шейдера, с которым затем используется shaderSource.
compileShader - компилирует шейдер после загрузки кода через shaderSource.
getShaderParameter - позволяет получить статус компиляции шейдера.
attachShader - присоединяет скомпилированный шейдер к программе WebGL.
Все эти функции работают вместе в процессе настройки графического конвейера.
Аналоги в других языках программирования
C/C++ (OpenGL): Используется функция glShaderSource с аналогичной сигнатурой.
GLuint shader = glCreateShader(GL_VERTEX_SHADER);
const char* source = "#version 330 core\nlayout(location=0) in vec3 aPos;\nvoid main(){gl_Position=vec4(aPos,1.0);}";
glShaderSource(shader, 1, &source, NULL);Python (PyOpenGL): Интерфейс практически идентичен C-версии.
from OpenGL.GL import *
shader = glCreateShader(GL_VERTEX_SHADER)
source = '''#version 330 core
layout(location=0) in vec3 aPos;
void main() {
gl_Position = vec4(aPos, 1.0);
}'''
glShaderSource(shader, source)
glCompileShader(shader)В PHP и MySQL аналоги отсутствуют, так как эти технологии не работают с графическим конвейером.
Типичные ошибки
Передача неверного типа объекта:
const gl = canvas.getContext('webgl');
const wrongObject = {};
gl.shaderSource(wrongObject, 'void main() {}');
// Ошибка: WebGL error INVALID_OPERATIONUncaught TypeError: Failed to execute 'shaderSource' on 'WebGLRenderingContext': parameter 1 is not of type 'WebGLShader'.
Использование после удаления шейдера:
const shader = gl.createShader(gl.VERTEX_SHADER);
gl.deleteShader(shader);
gl.shaderSource(shader, 'void main() {}');
// Ошибка: WebGL error INVALID_OPERATIONWebGL: INVALID_OPERATION: shaderSource: shader not from this context
Передача null или undefined вместо строки:
gl.shaderSource(vertexShader, null);WebGL: INVALID_VALUE: shaderSource: source is empty
Изменения в последних версиях
Функция shaderSource остаётся стабильной с момента введения WebGL 1.0 (2011 год). В WebGL 2.0 изменений в API функции не было, однако расширились возможности языка GLSL, которые можно передавать в source.
Современные браузеры поддерживают передачу строк с шаблонными литералами ES6, что упрощает написание многострочных шейдеров.
Расширенные примеры
Динамическая генерация кода шейдера:
function createShaderWithUniforms(gl, uniformCount) {
const shader = gl.createShader(gl.FRAGMENT_SHADER);
let uniformDeclarations = '';
for(let i = 0; i < uniformCount; i++) {
uniformDeclarations += `uniform float uValue${i};\n`;
}
const source = `
precision highp float;
${uniformDeclarations}
void main() {
float sum = 0.0;
${Array.from({length: uniformCount}, (_, i) => `sum += uValue${i};`).join('\n ')}
gl_FragColor = vec4(vec3(sum), 1.0);
}
`;
gl.shaderSource(shader, source);
return shader;
}Загрузка шейдера из внешнего файла:
async function loadShaderFromURL(gl, type, url) {
const response = await fetch(url);
const source = await response.text();
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('Shader compilation error:', gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}Многострочные шейдеры с комментариями:
const complexShaderSource = `// Вершинный шейдер с трансформациями
#version 300 es
in vec4 aVertexPosition;
in vec2 aTextureCoord;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
out vec2 vTextureCoord;
void main() {
// Вычисление конечной позиции
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
vTextureCoord = aTextureCoord;
}`;