Applying simple texture on a shader material

Using Threejs (67) with a Webgl renderer, I can't seem to get a plane with a shader material to wear its texture. No matter what I do the material would just stay black.

My code at the moment looks quite basic :

var grassT = new Three.Texture(grass); // grass is an already loaded image.
grassT.wrapS = grassT.wrapT = Three.ClampToEdgeWrapping;
grassT.flipY = false;
grassT.minFilter = Three.NearestFilter;
grassT.magFilter = Three.NearestFilter;
grassT.needsUpdate = true;

var terrainUniforms = {
  grassTexture : { type: "t", value: grassT},
}

Then I just have this revelant part in the vertexShader :

vUv = uv;

And on the fragmentShader side :

gl_FragColor = texture2D(grassTexture, vUv);

This results in :

  • Black material.
  • No error in console.
  • gl_FragColor value is always (0.0, 0.0, 0.0, 1.0).
  • What I tryed / checked:

  • Everything works fine if I just apply custom plain colors.
  • All is ok if I use vertexColors with plain colors too.
  • My texture width / height is indeed a power of 2.
  • The image is on the same server than the code.
  • Tested others images with same result.
  • The image is actually loading in the browser debugger.
  • UVS for the mesh are corrects.
  • Played around with wrapT, wrapS, minFilter, magFilter
  • Adapted the mesh size so the texture has a 1:1 ratio.
  • Preloaded the image with requirejs image plugin and created the texture from THREE.Texture() instead of using THREE.ImageUtils();
  • Played around with needsUpdate : true;
  • Tryed to add defines['USE_MAP'] during material instanciation.
  • Tryed to add material.dynamic = true.
  • I have a correct rendering loop (interraction with terrain is working).
  • What I still wonder :

  • It's a multiplayer game using a custom port with express + socket.io. Am I hit by any Webgl security policy ?
  • I have no lights logic at the moment, is that a problem ?
  • Maybe the shader material needs other "defines" at instanciation ?
  • I guess I'm overlooking something simpler, this is why I'm asking... Thanks.


    I am applying various effects on the same shader. I have a custom API that merge all different effects uniforms simply by using Three.UniformsUtils.merge() However this function is calling the clone() method on the texture and this is causing to reset needsUpdate to false before the texture reach the renderer.

    It appears that you should set your texture needsUpdate property to true when reaching the material level. On the texture level, if the uniform you set get merged, and therefore cloned, later in the process, it'll lose its needsUpdate property.

    The issue is also detailled here: https://github.com/mrdoob/three.js/issues/3393

    In my case the following wasn't working ( grassT is my texture):

    grassT.needsUpdate = true
    

    while the following is running perfectly later on in the code:

    material.uniforms.grassTexture.value.needsUpdate = true;
    

    Image loading is asynchronous. Most likely, you are rendering your scene before the texture image loads.

    You must set the texture.needsUpdate flag to true after the image loads. three.js has a utility that will do that for you:

    var texture = THREE.ImageUtils.loadTexture( "texture.jpg" );
    

    Once rendered, the renderer sets the texture.needsUpdate flag back to false .

    three.js r.68

    链接地址: http://www.djcxy.com/p/33986.html

    上一篇: 如何使用qt和qglwidget将两个纹理传递给opengl着色器

    下一篇: 在着色器材质上应用简单的纹理