Trzy predefiniowane atrybuty shader / Uniform
Zacząłem od renderera Threejs 'a po wykonaniu jakiegoś "zwykłego" Webgla bez dodatkowych bibliotek + shaderów GLSL. Próbuję teraz pisać własne shadery w moim programie ThreeJS i zauważyłem, że ThreeJS zajmuje się wieloma standardowymi rzeczami, takimi jak projekcja i matryce model / widok. Mój simple vertex shader wygląda teraz tak:
// 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);
}
Moje pytanie brzmi: które inne zmienne (zakładam, że są uniformami) są predefiniowane dla wierzchołków i shaderów fragmentów, które Przydałoby mi się? Czy ThreeJS pomaga na przykład wektorom światła / kolorze światła (oczywiście zakładając, że dodałem jedno lub więcej świateł do mojej sceny ThreeJS)?
Update (Oct. 9, 2014): to pytanie zostało coraz sporo odsłon, a użytkownik Killah wspomniał, że istniejące odpowiedzi nie doprowadziły do rozwiązania już z aktualną wersją trzech.js. Dodałem i zaakceptowałem własną odpowiedź, zobacz ją poniżej.
4 answers
W przypadku mundurów krótka odpowiedź jest następująca:
In the vertex shader
"uniform mat4 modelMatrix;",
"uniform mat4 modelViewMatrix;",
"uniform mat4 projectionMatrix;",
"uniform mat4 viewMatrix;",
"uniform mat3 normalMatrix;",
"uniform vec3 cameraPosition;",
I w Shader fragmentu
"uniform mat4 viewMatrix;",
"uniform vec3 cameraPosition;",
Aby uzyskać pełną odpowiedź, obejmującą uniformy i atrybuty, Twoje niestandardowe shadery mają wstępnie dodane zmienne łańcuchowe prefixVertex
i 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 );
Definicje zmiennych prefixVertex
i prefixFragment
można znaleźć w WebGLProgram.js
lub w nie-minifikowanej wersji three.js
.
EDIT: Updated to three.js R. 73
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-24 06:07:00
Mundury, których możesz użyć w swoich shaderach, zależą od tego, jak skonfigurujesz swój materiał: czy włączyłeś światła ? kolory wierzchołków ? skinning ? ...
Three js tworzy program, który w dużej mierze zależy od niektórych definicji (#ifdef w kodzie), które są wstrzykiwane u góry programu w zależności od parametrów, o których mówiłem powyżej.
Znalazłem najlepszy sposób, aby dowiedzieć się, co się dzieje, To wydrukować shadery generowane przez trzy JS: jak już znasz GLSL, zrozumiesz łatwo co oznacza kod i jakie mundury można użyć. Poszukaj buildProgram
w trzech źródłach JS, następnie (r57):
var glFragmentShader = getShader( "fragment", prefix_fragment + fragmentShader );
var glVertexShader = getShader( "vertex", prefix_vertex + vertexShader );
Po tych liniach dodaj:
console.log("fragment shader:", prefix_fragment + fragmentShader);
console.log("vertex shader:", prefix_vertex + vertexShader);
I będziesz mógł zobaczyć zawartość shaderów.
[edytuj] Czytając ponownie twoje pytanie, zdaję sobie sprawę, że odpowiedziałem trochę dziwnie, gdy tworzysz własne shadery...
Możesz spojrzeć na linie 6463 i 6490 WebGLRenderer ( https://github.com/mrdoob/three.js/blob/master/src/renderers/WebGLRenderer.js#L6463 ): zobaczysz standardowe uniformy / atrybuty, które trzy JS wstrzykują w twoje shadery. Możesz zajrzeć do Wiki gdzie masz wpis o tym ( https://github.com/mrdoob/three.js/wiki - które domyślne atrybuty / uniformy / varyingi są dostępne w niestandardowych shaderach?), ale kieruje cię do linii, które opisałem powyżej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-27 17:07:59
To pytanie zyskało sporo odsłon, a użytkownik Killah wspomniał, że istniejące odpowiedzi nie doprowadziły już do rozwiązania z obecną wersją trzech.js. Dlatego próbowałem ponownie rozwiązać problem i chciałbym przedstawić kilka opcji, które znalazłem: {]}
Najszybszym i najłatwiejszym sposobem (choć niezbyt eleganckim) jest po prostu umieszczenie przypadkowego błędu w shaderze. Pojawi się błąd konsoli z całym kodem shader, w tym wszystkim, co trzy.js dodaje.
-
Lepszym rozwiązaniem jest wyjście źródła shadera z miejsca jego kompilacji, czyli trzech.WebGLShader (od obecnych 3.wersja js, r68). Zrobiłem szybkie kopiowanie i wklejanie, które powinny wyprowadzać wszystkie źródła shaderów przed ich kompilacją.
Dodaj to po włączeniu trzech.js i przed własnym kodem:
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; }; } )();
Zauważ, że ten fragment jest po prostu skopiowany (i bardzo nieznacznie zmieniony) z trzech.źródła js i powinny być usunięte przed faktycznie używając kodu. Tylko do debugowania!
-
Jest jeszcze jedna opcja, która jest mniej inwazyjna: możesz sprawdzić swój ShaderMaterial po utworzeniu i renderowaniu go przynajmniej raz, w ten sposób:
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 });
Następnie, Po renderowanie obiektu przynajmniej raz:
console.log(material.program.attributes); console.log(material.program.uniforms);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-09 16:18:48
Odpowiedź na to pytanie można teraz znaleźć w trzech.dokumentacja js: https://threejs.org/docs/#api/renderers/webgl/WebGLProgram
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-27 22:49:48