我想准备着色器组件(用于多采样器tex)
在我目前的状态下,我只使用(激活并绑定)2个纹理图像。
但这一行:
gl_FragColor = textureColor + textureColor1 + textureColor2;
我的纹理视图出现问题,因为纹理我没有绑定纹理。
在着色器中,不可能使用console.log或任何其他标准调试方法。我有兴趣了解有关着色器的更多信息,但我被卡住了。
代码:
...
precision mediump float;
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
uniform sampler2D uSampler;
uniform sampler2D uSampler1;
uniform sampler2D uSampler2;
uniform sampler2D uSampler3;
uniform sampler2D uSampler4;
uniform sampler2D uSampler5;
uniform sampler2D uSampler6;
uniform sampler2D uSampler7;
uniform sampler2D uSampler8;
uniform sampler2D uSampler9;
uniform sampler2D uSampler10;
uniform sampler2D uSampler11;
uniform sampler2D uSampler12;
uniform sampler2D uSampler13;
void main(void) {
vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
vec4 textureColor1 = texture2D(uSampler1, vec2(vTextureCoord.s, vTextureCoord.t));
vec4 textureColor2 = texture2D(uSampler2, vec2(vTextureCoord.s, vTextureCoord.t));
// Need help here
gl_FragColor = textureColor + textureColor1 ;
//gl_FragColor = textureColor + textureColor1 + textureColor2;
//更新的问题
if ( ${numTextures} == 1)
{
gl_FragColor = textureColor;
}
else if (${numTextures} == 2)
{
gl_FragColor = textureColor + textureColor1;
}
else if (${numTextures} == 3)
{
gl_FragColor = textureColor + textureColor1 + textureColor2;
}
//我现在使用简单实用的if else。
//我将值传递给加载时的着色器
//我仍然无法在运行时更新着色器
///////////////////////////////////////
//这是绘制函数的一部分:
for (var t=0;t<object.textures.length;t++) {
eval( " world.GL.gl.activeTexture(world.GL.gl.TEXTURE"+t+"); " )
world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.textures[t]);
world.GL.gl.pixelStorei(world.GL.gl.UNPACK_FLIP_Y_WEBGL, false);
world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MAG_FILTER, world.GL.gl.NEAREST);
world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MIN_FILTER, world.GL.gl.NEAREST);
world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_S, world.GL.gl.CLAMP_TO_EDGE);
world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_T, world.GL.gl.CLAMP_TO_EDGE);
// -- Allocate storage for the texture
//world.GL.gl.texStorage2D(world.GL.gl.TEXTURE_2D, 1, world.GL.gl.RGB8, 512, 512);
//world.GL.gl.texSubImage2D(world.GL.gl.TEXTURE_2D, 0, 0, 0, world.GL.gl.RGB, world.GL.gl.UNSIGNED_BYTE, image);
//world.GL.gl.generateMipmap(world.GL.gl.TEXTURE_2D);
world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, t);
}
...
也许在运行时最好的方法是使用object.textures数组进行操作?!
最后:
答案 0 :(得分:1)
你想要完成什么?
使用大量纹理的普通方法是使用texture atlas底部覆盖的this article
否则,没有办法检测着色器中是否加载了纹理。你需要传递自己的旗帜。例如
uniform bool textureLoaded[NUM_TEXTURES];
或
uniform float textureMixAmount[NUM_TEXTURES];
如果我是你,我会使用纹理图集,除非你真的知道你正在做一些实际上需要14个纹理的独特的东西。
在运行中生成着色器也很常见。几乎所有游戏引擎都这样做。 Three.js也是如此。因此,不是打开和关闭纹理,而是编写一些为N纹理生成着色器的代码。然后当你只有一个纹理生成一个纹理着色器时,当你有2个生成一个2纹理着色器等时,对于GPU而言,这比使用14纹理着色器并试图关闭13个纹理要高效得多。
示例:
// note, I'm not recommending this shader, only showing some code
// that generates a shader
function generateShaderSrc(numTextures) {
return `
// shader for ${numTextures} textures
precision mediump float;
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
uniform sampler2D uSampler[${numTextures}];
uniform float uMixAmount[${numTextures}];
void main() {
vec4 color = vec4(0);
for (int i = 0; i < ${numTextures}; ++i) {
vec4 texColor = texture2D(uSampler[i], vTextureCoord);
color = mix(color, texColor, uMixAmount[i]);
}
gl_FragColor = color;
}
`;
}
log(generateShaderSrc(1));
log(generateShaderSrc(4));
function log(...args) {
const elem = document.createElement("pre");
elem.textContent = [...args].join(' ');
document.body.appendChild(elem);
}
这是一个非常简单的例子。真正的着色器生成器通常会执行更多的字符串操作。
您还应该知道WebGL 1.0仅需要支持8个纹理单元。 According to webglstats about 15% of devices only support 8 texture units所以您可能想要检查用户拥有多少纹理单位,并警告他们如果应用程序的应用程序需求少于您的应用程序,那么该应用程序将无法运行。