【问题标题】:Threejs - Applying simple texture on a shader materialThreejs - 在着色器材质上应用简单纹理
【发布时间】:2014-09-26 00:50:10
【问题描述】:

将 Threejs (67) 与 Webgl 渲染器结合使用,我似乎无法让带有着色器材质的平面佩戴其纹理。无论我做什么,材料都会保持黑色。

目前我的代码看起来很基础:

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},
}

然后我就在 vertexShader 中有这个相关的部分:

vUv = uv;

在fragmentShader方面:

gl_FragColor = texture2D(grassTexture, vUv);

这会导致:

  • 黑色材料。
  • 控制台没有错误。
  • gl_FragColor 值始终为 (0.0, 0.0, 0.0, 1.0)。

我尝试/检查的内容:

  • 如果我只应用自定义纯色,一切都会正常工作。
  • 如果我也使用纯色的 vertexColors,一切都可以。
  • 我的纹理宽度/高度确实是 2 的幂。
  • 图片与代码在同一台服务器上。
  • 用相同的结果测试了其他图像。
  • 图片实际上是在浏览器调试器中加载的。
  • 网格的 UVS 是正确的。
  • 玩过 wrapT、wrapS、minFilter、magFilter
  • 调整了网格大小,使纹理具有 1:1 的比例。
  • 使用 requirejs 图像插件预加载图像并从 THREE.Texture() 而不是使用 THREE.ImageUtils() 创建纹理;
  • 玩过 needsUpdate : true;
  • 在材质实例化期间尝试添加定义['USE_MAP']。
  • 尝试添加material.dynamic = true。
  • 我有一个正确的渲染循环(与地形的交互工作正常)。

我仍然想知道:

  • 这是一款多人游戏,使用带有 express + socket.io 的自定义端口。我是否受到任何 Webgl 安全策略的影响?
  • 我目前没有灯光逻辑,有问题吗?
  • 也许着色器材质在实例化时需要其他“定义”?

我想我忽略了一些更简单的东西,这就是我问的原因...... 谢谢。

【问题讨论】:

  • 如果没有你的所有代码,调试起来有点困难——但我肯定会建议在你的场景中添加一个 AmbientLight 来检查模型是否真的有纹理。我发现你通常可以有一个纹理渲染(即草)并且看起来是正确的,只是意识到你做错了并且它忽略了照明。 :)
  • 非常感谢您的建议。我检查了灯亮着,并没有更好。我取得了一些进展,但是我的手弄脏了渲染器代码。我发现由于某种原因将 texture.needsUpdate 属性设置为 false !如果我删除第 26278 行的条件检查 -setTexture 函数 - 纹理将被渲染。
  • 因此新的问题是:纹理的 needsUpdate 属性在哪里以及为什么可以从 true 设置为 false。

标签: three.js glsl


【解决方案1】:

图像加载是异步的。很可能,您是在纹理图像加载之前渲染场景。

您必须在图像加载之后将texture.needsUpdate 标志设置为true。。 three.js 有一个实用程序可以为您做到这一点:

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

渲染后,渲染器将texture.needsUpdate 标志设置回false。

three.js r.68

【讨论】:

  • 谢谢你。我尝试了同样的结果。图像在代码运行时实际加载。问题来自其他地方:我在同一个着色器上应用了各种效果。我有一个自定义 API,只需使用以下命令即可合并所有不同的效果制服: Three.UniformsUtils.merge();然而,这个函数在纹理上调用 clone() 方法,这导致在纹理到达渲染器之前将 needsUpdate 重置为 false !!
  • 看来您应该在达到材质级别时将您的纹理需求更新属性设置为 true,因为在纹理级别上,如果您设置的制服在该过程的后期被合并(并因此被克隆),它'将失去它的 needsUpdate 属性!在我的情况下,这不起作用(grassT 是我的纹理):grassT.needsUpdate = true 而以下运行完美:material.uniforms.grassTexture.value.needsUpdate = true;
  • 嘿韦斯特兰利!毕竟这对你来说很熟悉:我刚刚被击中:github.com/mrdoob/three.js/issues/3393
  • 请在原帖中提供回答问题所需的所有信息。
  • 我一定会的。我需要再等 3 个小时,因为我的声誉太低了。不到 10 分我们只能在 8 小时后回复自己。
【解决方案2】:

我在同一个着色器上应用了各种效果。我有一个自定义 API,只需使用 Three.UniformsUtils.merge() 即可合并所有不同的效果制服但是此函数在纹理上调用 clone() 方法,这导致在纹理到达渲染器之前将 needsUpdate 重置为 false。

看来您应该在达到 ma​​terial 级别时将纹理 needsUpdate 属性设置为 true。在纹理级别上,如果您设置的制服被合并并因此被克隆,在此过程的后期,它将失去其needsUpdate 属性。

这里也详细说明了这个问题:https://github.com/mrdoob/three.js/issues/3393

在我的情况下,以下 不 工作(grassT 是我的纹理):

grassT.needsUpdate = true

虽然稍后在代码中完美运行以下内容:

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

【讨论】:

    猜你喜欢
    • 2015-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-05
    • 2012-11-20
    • 1970-01-01
    • 2019-03-01
    • 2015-02-16
    相关资源
    最近更新 更多