Предопределенные шейдерные атрибуты/униформа
Я начал с 3DJS WebGL рендеринга после выполнения некоторого "обычного" WebGL без дополнительных библиотек + шейдеров GLSL. Я пытаюсь написать пользовательские шейдеры сейчас в моей программе ThreeJS, и я заметил, что ThreeJS заботится о многих стандартных вещах, таких как матрица проекции и модели/представления. Теперь мой простой шейдерный шейдер выглядит следующим образом:
// All of these seem to be predefined:
// vec3 position;
// mat4 projectionMatrix;
// mat4 modelViewMatrix;
// mat3 normalMatrix;
// vec3 normal;
// I added this
varying vec3 vNormal;
void main() {
vNormal = normalMatrix * vec3(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
Мой вопрос: какие другие переменные (я предполагаю, что они являются общими) предопределены для шейдеров вершин и фрагментов, которые я мог бы использовать? Может ли ThreeJS справляться со светлыми векторами/светлым цветом (например, предположив, что я добавил один или несколько огней в мою сцену ThreeJS)?
Обновление (9 октября 2014 года): этот вопрос получил довольно много просмотров, и пользователь Киллах отметил, что существующие ответы больше не приводят к решению проблемы с текущей версией Three.js. Я добавил и принял свой собственный ответ, см. Ниже.
Ответы
Ответ 1
Этот вопрос получил довольно много просмотров, и пользователь Киллах сказал, что существующие ответы больше не приводят к решению с текущей версией three.js.
Вот почему я снова попытался решить проблему, и я хотел бы выделить несколько вариантов, которые я нашел:
-
Самый быстрый и простой способ (хотя и не очень элегантный) - просто поместить случайную ошибку в ваш шейдер. Вы получите консольную ошибку со всем кодом шейдера, включая все, что добавляет three.js.
-
Лучшим решением является вывод источника шейдера из того, где он был скомпилирован, а именно THREE.WebGLShader(с текущей версии three.js, r68). Я сделал быструю копию и вставку, которая должна выводить все шейдерные источники до их компиляции.
Добавьте это после включения three.js и перед вашим собственным кодом:
THREE.WebGLShader = ( function () {
var addLineNumbers = function ( string ) {
var lines = string.split( '\n' );
for ( var i = 0; i < lines.length; i ++ ) {
lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
}
return lines.join( '\n' );
};
return function ( gl, type, string ) {
var shader = gl.createShader( type );
console.log(string);
gl.shaderSource( shader, string );
gl.compileShader( shader );
if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) {
console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' );
}
if ( gl.getShaderInfoLog( shader ) !== '' ) {
console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', gl.getShaderInfoLog( shader ) );
console.warn( addLineNumbers( string ) );
}
return shader;
};
} )();
Обратите внимание, что этот фрагмент просто скопирован (и очень немного изменен) из источников three.js и должен быть удален до фактического использования кода. Просто для отладки!
-
Есть еще один вариант, который менее инвазивен: вы можете проверить свой ShaderMaterial после создания и рендеринга его хотя бы один раз, например:
var material = new THREE.ShaderMaterial({
uniforms: {
uColorMap: { type: 't', value: THREE.ImageUtils.loadTexture('./img/_colors.png') },
uSpecularMap: { type: 't', value: THREE.ImageUtils.loadTexture('./img/_spec.png') },
uNormalMap: { type: 't', value: THREE.ImageUtils.loadTexture('./img/_normal.png') }
},
vertexShader: document.getElementById('vShader').innerText,
fragmentShader: document.getElementById('fShader').innerText
});
Затем, после рендеринга объекта хотя бы один раз:
console.log(material.program.attributes);
console.log(material.program.uniforms);
Надеюсь, это поможет всем! Не стесняйтесь добавлять свои комментарии, если вы знаете больше и/или более эффективные способы получить свой шейдерный код.
Ответ 2
Для униформ короткий ответ таков:
В вершинном шейдере
"uniform mat4 modelMatrix;",
"uniform mat4 modelViewMatrix;",
"uniform mat4 projectionMatrix;",
"uniform mat4 viewMatrix;",
"uniform mat3 normalMatrix;",
"uniform vec3 cameraPosition;",
и в шейдере фрагмента
"uniform mat4 viewMatrix;",
"uniform vec3 cameraPosition;",
Для получения полного ответа, включающего униформы и атрибуты, ваши пользовательские шейдеры имеют строковые переменные prefixVertex
и prefixFragment
, предварительно добавленные.
var vertexGlsl = prefixVertex + vertexShader;
var fragmentGlsl = prefixFragment + fragmentShader;
var glVertexShader = THREE.WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
var glFragmentShader = THREE.WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
Определения переменных prefixVertex
и prefixFragment
можно найти в WebGLProgram.js
или в недопустимой версии three.js
.
EDIT: обновлено до трёх .js r.73
Ответ 3
Форма, которую вы можете использовать в ваших шейдерах, зависит от того, как вы настраиваете свой материал: включили ли вы свет? цвета вершин? скининг?...
Three JS создает программу, которая сильно зависит от некоторых определений (#ifdef в коде), которые вводятся в верхней части программы в зависимости от параметров, о которых я говорил выше.
Я нашел лучший способ узнать, что происходит, это напечатать шейдеры, которые генерируют три JS: как вы уже знаете GLSL, вы легко поймете, что означает код и какую форму вы можете использовать. Найдите buildProgram
в трех источниках JS, затем (r57):
var glFragmentShader = getShader( "fragment", prefix_fragment + fragmentShader );
var glVertexShader = getShader( "vertex", prefix_vertex + vertexShader );
После этих строк добавьте:
console.log("fragment shader:", prefix_fragment + fragmentShader);
console.log("vertex shader:", prefix_vertex + vertexShader);
И вы сможете увидеть содержимое шейдеров.
[EDIT]
Перечитывая свой вопрос, я понимаю, что немного ответил, когда вы создаете свои собственные шейдеры...
Вы можете взглянуть на строки 6463 и 6490 WebGLRenderer (https://github.com/mrdoob/three.js/blob/master/src/renderers/WebGLRenderer.js#L6463): вы увидите стандартные униформы/атрибуты, которые три JS вводят в ваши шейдеры. Вы можете взглянуть на Wiki, где у вас есть запись об этом (https://github.com/mrdoob/three.js/wiki - Какие атрибуты/униформы/изменения по умолчанию доступны в пользовательских шейдерах?), Но это направляет вас к строкам, указанным выше.
Ответ 4
Ответ на этот вопрос теперь можно найти в документации по трем .js: https://threejs.org/docs/#api/renderers/webgl/WebGLProgram