Grü*_*üse 24 shader glsl three.js
在完成一些没有额外库+ GLSL着色器的"常规"WebGL之后,我开始使用ThreeJS的WebGL渲染器.我正在尝试在我的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场景添加了一个或多个灯光)?
更新(2014年10月9日):这个问题已经得到了不少观点,用户Killah提到现有的答案不再导致当前版本的three.js的解决方案.我添加并接受了我自己的答案,见下文.
Wes*_*ley 23
对于制服,简短的回答如下:
在顶点着色器中
"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.
编辑:更新为three.js r.73
Pop*_*pov 11
您可以在着色器中使用的制服都取决于您设置材料的方式:您是否启用了灯光?顶点颜色?剥皮?...
三个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);
您将能够看到着色器的内容.
[编辑]重读你的问题,我意识到我回答了一点,因为你创建了自己的着色器......
您可以查看WebGLRenderer的第6463和6490行(https://github.com/mrdoob/three.js/blob/master/src/renderers/WebGLRenderer.js#L6463):您将看到标准制服/属性三个JS注入你的着色器.您可以查看Wiki中有关于该条目的条目(https://github.com/mrdoob/three.js/wiki - 自定义着色器中有哪些默认属性/制服/变换?)但它会指导您到我上面概述的那些.
这个问题已经获得了相当多的意见,用户 Killah 提到现有的答案并没有导致使用当前版本的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);
希望这对大家有帮助!如果您了解更多和/或更好的获取着色器代码的方法,请随时添加您的评论。