THREE.JS,动态着色器无法编译

时间:2014-10-23 14:04:41

标签: javascript three.js glsl webgl shader

我试图用粒子来显示3D场景中飘落的雪花。 我不想在HTML页面中创建着色器,因为我的项目不允许添加特定脚本,并且许多其他脚本都是动态加载的,不包括在<script src=''>的HTML页面中。

我收到了下一个错误(简称:http://pastebin.com/KqiZze49,已满:http://pastebin.com/LZHhCnuh):

THREE.WebGLShader: Shader couldn't compile. three.min.js:592(anonymous function) 
three.min.js:592(anonymous function) three.min.js:588initMaterial three.min.js:566z
three.min.js:488renderBuffer three.min.js:544v three.min.js:483render 
three.min.js:556Rekod3DBuildings.Engine.renderScene rekod3d-new.js:668
(anonymous function) new-index.html:71
THREE.WebGLShader: gl.getShaderInfoLog() ERROR: 0:68: 'gl_FragColor' : undeclared identifier
ERROR: 0:68: 'assign' :  cannot convert from '4-component vector of float' to 'float'
ERROR: 0:68: 'gl_PointCoord' : undeclared identifier
ERROR: 0:68: 'texture2D' : no matching overloaded function found

你可以告诉我&#34;男人,看看控制台,你在控制台中得到了所有错误,只是google。&#34; 但是,奇怪的是,如果使用相同的着色器,这些着色器在JavaScript中动态生成,但在HTML页面中用作准备好的部分,则没有错误,结果是:

enter image description here

正如您在上面的屏幕截图中所示,如果着色器包含在HTML页面中,则没有错误。 当然,从逻辑上讲,你想告诉我,显然我在JavaScript中没有正确地创建着色器,但也有一些奇怪的东西,让我们看看:

1)。我如何在JavaScript中生成着色器?

http://pastebin.com/HncUKMUL

Rekod3DBuildings.Engine.prototype.createVertexShaderForSnowParticles = function( scriptId ) {
    if ( typeof scriptId === 'string' ) {
        var script = document.createElement( 'script' );
        script.id = scriptId;
        script.type = 'x-shader/x-vertex';
        script.textContent = '\
                attribute float size;\
                attribute float time;\
                attribute vec3 customColor;\
                uniform float globalTime;\
                varying vec3 vColor;\
                varying float fAlpha;\
                \
                void main() {\
                    vColor = customColor;\
                    vec3 pos = position;\
                    float localTime = time + globalTime;\
                    float modTime = mod( localTime, 1.0 );\
                    float accTime = modTime * modTime;\
                    pos.x += cos( modTime * 8.0 + ( position.z ) ) * 70.0;\
                    pos.z += sin( modTime * 6.0 + ( position.x ) ) * 100.0;\
                    fAlpha = ( pos.z ) / 1800.0;\
                    vec3 animated = vec3( pos.x, pos.y * accTime, pos.z );\
                    vec4 mvPosition = modelViewMatrix * vec4( animated, 1.0 );\
                    gl_PointSize = min( 150.0, size * ( 150.0 / length( mvPosition.xyz ) ) );\
                    gl_Position = projectionMatrix * mvPosition;\
                }';
        document.head.appendChild( script );        
        return script;
    }
    else
        console.error( 'Script id for the vertex shader isn\'t a type of `string`.' );
};
Rekod3DBuildings.Engine.prototype.createFragmentShaderForSnowParticles = function( scriptId ) {
    if ( typeof scriptId === 'string' ) {
        var script = document.createElement( 'script' );
        script.id = scriptId;
        script.type = 'x-shader/x-fragment';
        script.textContent = '\
                uniform vec3 color;\
                uniform sampler2D texture;\
                varying vec3 vColor;\
                varying float fAlpha;\
                \
                void main() {\
                    gl_FragColor = vec4( color * vColor, fAlpha );\
                    gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );\
                }';
        document.head.appendChild( script );        
        return script;
    }
    else
        console.error( 'Script id for the fragment shader isn\'t a type of `string`.' );
};

2)。创建它们之后,我们是否添加了它们的检查?

查看屏幕截图,成功添加了着色器:

enter image description here

源代码,正在准备粒子(http://pastebin.com/HgLHJWFu):

Rekod3DBuildings.Engine.prototype.setSnowParticles = function() {
    var map = THREE.ImageUtils.loadTexture( 'images/textures/snowflake.png' );

    var attributes = {
        size:        { type: 'f', value: [] },
        customColor: { type: 'c', value: [] },
        time:        { type: 'f', value: [] },
    };

    this.snowUniforms = {
        color:      { type: "c", value: new THREE.Color( 0x777777 ) },
        texture:    { type: "t", value: 0, texture: map },
        globalTime: { type: "f", value: 0.0 },
    };

    var shaderMaterial = new THREE.ShaderMaterial( {
        uniforms:       this.snowUniforms,
        attributes:     attributes,
        vertexShader:   document.getElementById( 'fragmentshader-airplane' ).textContent,
        fragmentShader: document.getElementById( 'vertexshader-airplane' ).textContent,
        blending:       THREE.AdditiveBlending,
        depthTest:      false,
        transparent:    true,
    });

    var geometry = new THREE.Geometry();

    for ( var i = 0; i < 10000; i++ )
        geometry.vertices.push( new THREE.Vector3( Math.random() * 18000 - 1500, -5000, Math.random() * 18000 ) );

    var particles = new THREE.PointCloud( geometry, shaderMaterial );
    particles.position.x = -5000; 
    particles.position.y = 5000;
    particles.position.z = -5000;

    var vertices = particles.geometry.vertices;
    var values_size = attributes.size.value;
    var values_color = attributes.customColor.value;
    var values_time = attributes.time.value;

    for( var v = 0; v < vertices.length; v++ ) {
        values_size[ v ] = 50 + Math.random() * 80;
        values_color[ v ] = new THREE.Color( 0xffffff );
        values_time[ v ] = Math.random();
    }

    this.scene.add( particles );
};

那么,出了什么问题?

请帮我提一些建议。

2 个答案:

答案 0 :(得分:2)

在屏幕截图中读取代码片段,您将片段着色器文本加载到顶点着色器中,反之亦然,因此来自着色器编译器的gl_FragColor错误。我很确定逆转这些将有很大帮助。 : - )

答案 1 :(得分:0)

你真的需要通过DOM吗?

我可以用这种方式动态创建着色器

THREE.SlicedBoxGeometry.prototype.GetVertexShader = function()  {
    var r = "";

    r+= "uniform vec4 uClipPlane1;              \n";
    r+= "uniform vec4 uClipPlane2;              \n";
    r+= "uniform vec4 uClipPlane3;              \n";
    r+= "varying vec3 vPos;                     \n";


    r+= "void main()                                                \n";
    r+= "{                                                  \n";
    r+= "   vec3 newPosition = position;                            \n";

    r+= "   if (position.x == " + this.width_half.toFixed(2) + " ) {            \n";
    r+= "       newPosition.x = - uClipPlane1.w / uClipPlane1.x;        \n";
    r+= "   }                                                   \n";
    r+= "   if (position.y == " + this.height_half.toFixed(2) + ") {            \n";
    r+= "       newPosition.y = - uClipPlane2.w / uClipPlane2.y;        \n";
    r+= "   }                                                   \n";
    r+= "   if (position.z == " + this.depth_half.toFixed(2) + ") {         \n";
    r+= "       newPosition.z = - uClipPlane3.w / uClipPlane3.z;        \n";
    r+= "   }                                                   \n";
    r+= "   gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );\n";
    r+= "   vPos = newPosition; \n";
    r+= "}\n";

    return r;
}

可能不是更好的方法,但它有效...

将着色器放在DOM中的唯一原因就在于

<script type="something-not-javascript" id="someId">
shader code goes here
</script>

然后您可以使用

检索它
var shaderSource = document.getElementById("someId").text

你把它放在DOM中,因为你可以编辑它而不必用引号括起每一行......

否则,如果您要将它放在JavaScript中,那么上面的格式或类似的内容也可以使用

THREE.SlicedBoxGeometry.prototype.GetVertexShader = function()  {
  return [  
    "uniform vec4 uClipPlane1;              ",
    "uniform vec4 uClipPlane2;              ",
    "uniform vec4 uClipPlane3;              ",
    "varying vec3 vPos;                     ",
    "",
    "",
    "void main()                                                ",
    "{                                                  ",
    "   vec3 newPosition = position;                            ",

    "   if (position.x == " + this.width_half.toFixed(2) + " ) {            ",
    "       newPosition.x = - uClipPlane1.w / uClipPlane1.x;        ",
    "   }                                                   ",
    "   if (position.y == " + this.height_half.toFixed(2) + ") {            ",
    "       newPosition.y = - uClipPlane2.w / uClipPlane2.y;        ",
    "   }                                                   ",
    "   if (position.z == " + this.depth_half.toFixed(2) + ") {         ",
    "       newPosition.z = - uClipPlane3.w / uClipPlane3.z;        ",
    "   }                                                   ",
    "   gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );",
    "   vPos = newPosition; ",
    "}",
  ].join("¥n");
};