Javascript WebGL:使用单独的纹理渲染两个对象

Javascript WebGL:使用单独的纹理渲染两个对象,javascript,webgl,textures,Javascript,Webgl,Textures,我目前正在WebGL中进行一个简单的项目,该项目要求渲染多个2D对象,并在其上设置简单的图像纹理。实际项目生成随机数量的对象,通常在5到9之间,在画布周围为它们设置顶点数据以将它们分开,并且应该进行渲染,但是一次只渲染一个对象(通常是最后一个,但我可以在gl.activeTexture周围更改以显示阵列中的其他对象)。我尝试在着色器中使用一个关于纹理数组的on here,但没有效果,因此我创建了一个非常简单的测试程序,它只尝试加载两个对象和纹理,一个在画布的左侧,另一个在右侧 从这里开始,我尝试

我目前正在WebGL中进行一个简单的项目,该项目要求渲染多个2D对象,并在其上设置简单的图像纹理。实际项目生成随机数量的对象,通常在5到9之间,在画布周围为它们设置顶点数据以将它们分开,并且应该进行渲染,但是一次只渲染一个对象(通常是最后一个,但我可以在gl.activeTexture周围更改以显示阵列中的其他对象)。我尝试在着色器中使用一个关于纹理数组的on here,但没有效果,因此我创建了一个非常简单的测试程序,它只尝试加载两个对象和纹理,一个在画布的左侧,另一个在右侧

从这里开始,我尝试将所有操作完全分开,甚至为每个对象提供它们自己的着色器、程序、缓冲区和所有内容,然后在为每个对象调用gl.drawElements之前,为每个对象绑定draw调用中的所有内容。这仍然没有告诉我正确的结果,只有第二个纹理出现,但是它确实让我发现了我认为正在发生的事情。通过注释第二个纹理的绑定和绘制调用,第一个纹理将显示,但它显示在第二个纹理的位置,而不是其顶点应放置的位置。因此,我假设在这个程序(和我的项目代码)中发生的事情是,它实际上正在绘制这两个,但出于某种原因,将最后绘制的顶点应用于所有顶点,从而堆叠它们,并仅显示顶部(或最后绘制的顶点)

我也尝试过对下面的代码进行大量的调整,只使用一个程序,使用相同的索引、纹理坐标,还有一些注释掉的行,它们试图以不同的顺序调用。任何被注释掉的东西并不意味着我一定认为它是错的或是对的,只是从我在这一点上漫无目的地尝试过的各种事情来看

我曾与OpenGL合作过一段时间,用它们自己的纹理绘制多个对象几乎没有问题,我知道WebGL在某些方面与OpenGL的工作方式不同,包括纹理,但我不知道我在哪里创建了这个问题。我相信这是一件非常简单的事情,任何指导都将不胜感激

很抱歉,代码太长了,我觉得只要把我认为需要的东西都直接打出来就行了,不需要走捷径。initShaders调用来自我在教科书中使用的WebGL js文件,不是我写的东西,loadImage调用只是从html代码中加载一个
。据我所知,正确加载图像没有问题。我只包括第一个顶点和片段着色器,因为其他两个都是相同的id保存

<script id="vertex-shader1" type="x-shader/x-vertex">
        attribute vec4 vPosition;
        attribute vec2 vTexCoord;

        varying vec2 fTexCoord;

        void main() {
            fTexCoord = vTexCoord;
            gl_Position = vPosition;
        }

    </script>

    <script id="fragment-shader1" type="x-shader/x-fragment">
        precision mediump float;

        varying vec2 fTexCoord;

        uniform sampler2D texture;

        void main() {
            gl_FragColor = texture2D(texture, fTexCoord);
        }
    </script>

首先,你的代码不能工作。它调用函数
loadImages
,然后立即使用图像。图像在浏览器中异步加载,因此您需要在加载图像时进行回调,或者使用异步函数

这是你的代码。首先,我制作了一个
loadImage
,返回一个承诺。然后我创建了一个名为
loadImages
的异步函数,它使用该函数加载所有图像并等待它们加载。然后我创建了另一个异步函数,名为
main
what,首先等待
loadImages
,然后调用
init

第二个问题是,在WebGL1中,属性是全局状态。这意味着您需要在渲染时而不是在初始化时设置它们,以便调用转到
gl.enableVertexAttribArray
gl.vertexAttribPointer
需要在渲染时使用适当的值来渲染您正在渲染的特定对象
gl.vertexattributepointer
将当前
ARRAY\u BUFFER
绑定复制到该属性

您可能会发现有帮助,尤其是,这可能会帮助您可视化WebGL内部发生的事情

“严格使用”;
常量vec2=(…args)=>[…args];
常量vec4=(…args)=>[…args];
const flatte=a=>新的Float32Array(a.flat());
常数WebGLUtils={
setupWebGL:(canvas)=>{return canvas.getContext('webgl');},
};
const initShaders=(gl,vs,fs)=>twgl.createProgram(gl[vs,fs]);
const requestAnimFrame=requestAnimationFrame;
var-gl;
var图像=[];
var程序1;
var程序2;
var-texture1;
var-texture2;
var vBuff1;
var vBuff2;
iBuff1变种;
iBuff2变种;
var-tBuff1;
var-tBuff2;
var vPos1;
var vPos2;
变量fTexCoord1;
变量fTexCoord2;
var采样器1;
var采样器2;
变量vertices1=[
vec4(-0.8,0.1,0.0,1.0),
vec4(-0.8,0.3,0.0,1.0),
vec4(-0.6,0.3,0.0,1.0),
vec4(-0.6,0.1,0.0,1.0)
];
变量vertices2=[
vec4(0.1,0.1,0.0,1.0),
vec4(0.1,0.3,0.0,1.0),
vec4(0.3,0.3,0.0,1.0),
vec4(0.3,0.1,0.0,1.0)
];
变量指标1=[
0, 1, 2,
0, 2, 3
];
变量指标2=[
0, 1, 2,
0, 2, 3
];
变量tcs1=[
vec2(0,0),
vec2(0,1),
vec2(1,1),
vec2(1,0)
];
变量tcs2=[
vec2(0,0),
vec2(0,1),
vec2(1,1),
vec2(1,0)
];
函数init(){
var canvas=document.getElementById(“gl画布”);
gl=WebGLUtils.setupWebGL(画布);
如果(!gl){alert(“WebGL不可用”);}
总图视口(0,0,canvas.width,canvas.height);
gl.clearColor(0.0,0.0,0.0,1.0);
program1=初始着色器(gl,“顶点着色器1”、“片段着色器1”);
总账使用计划(计划1);
vBuff1=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vBuff1);
总账缓冲数据(总账数组缓冲、展平(垂直1)、总账静态绘图);
vPos1=gl.GetAttriblLocation(程序1,“vPosition”);
iBuff1=gl.createBuffer();
gl.bindBuffer(gl.ELEMENT\u ARRAY\u BUFFER,iBuff1);
总账缓冲数据(总账元素\数组\缓冲区、新UINT8数组(指示1)、总账静态\绘图);
tBuff1=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,tBuff1);
总账缓冲数据(总账数组缓冲、展平(tcs1)、总账静态绘图);
fTexCoord1=gl.GetAttriblLocation(程序1,“vTexCoord”);
采样器1=gl.getUniformLocation(程序1,“纹理”);
纹理
"use-strict"

var gl;

var images = [];

var program1;
var program2;
var texture1;
var texture2;

var vBuff1;
var vBuff2;
var iBuff1;
var iBuff2;
var tBuff1;
var tBuff2;

var vPos1;
var vPos2;
var fTexCoord1;
var fTexCoord2;

var sampler1;
var sampler2;

var vertices1 = [
    vec4(-0.8, 0.1, 0.0, 1.0),
    vec4(-0.8, 0.3, 0.0, 1.0),
    vec4(-0.6, 0.3, 0.0, 1.0),
    vec4(-0.6, 0.1, 0.0, 1.0)
];

var vertices2 = [
    vec4(0.1, 0.1, 0.0, 1.0),
    vec4(0.1, 0.3, 0.0, 1.0),
    vec4(0.3, 0.3, 0.0, 1.0),
    vec4(0.3, 0.1, 0.0, 1.0)
];

var indices1 = [
    0, 1, 2,
    0, 2, 3
];

var indices2 = [
    0, 1, 2,
    0, 2, 3
];

var tcs1 = [
    vec2(0, 0),
    vec2(0, 1),
    vec2(1, 1),
    vec2(1, 0)
];

var tcs2 = [
    vec2(0, 0),
    vec2(0, 1),
    vec2(1, 1),
    vec2(1, 0)
];

window.onload = function init() {
    var canvas = document.getElementById("gl-canvas");
    gl = WebGLUtils.setupWebGL(canvas);
    if (!gl) { alert("WebGL isn't available"); }

    gl.viewport(0, 0, canvas.width, canvas.height);
    gl.clearColor(0.0, 0.0, 0.0, 1.0);

    loadImages();

    program1 = initShaders(gl, "vertex-shader1", "fragment-shader1");
    gl.useProgram(program1);

    vBuff1 = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vBuff1);
    gl.bufferData(gl.ARRAY_BUFFER, flatten(vertices1), gl.STATIC_DRAW);

    vPos1 = gl.getAttribLocation(program1, "vPosition");
    gl.vertexAttribPointer(vPos1, 4, gl.FLOAT, false, 0, 0);
    //gl.enableVertexAttribArray(vPos1);

    iBuff1 = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, iBuff1);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array(indices1), gl.STATIC_DRAW);

    tBuff1 = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, tBuff1);
    gl.bufferData(gl.ARRAY_BUFFER, flatten(tcs1), gl.STATIC_DRAW);

    fTexCoord1 = gl.getAttribLocation(program1, "vTexCoord");
    gl.vertexAttribPointer(fTexCoord1, 2, gl.FLOAT, false, 0, 0);
    //gl.enableVertexAttribArray(fTexCoord1);

    sampler1 = gl.getUniformLocation(program1, "texture");

    texture1 = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture1);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, images[0]);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

    gl.bindTexture(gl.TEXTURE_2D, null);

///////////////////////////////////////////////////////////////////////////////////////
/*
    program2 = initShaders(gl, "vertex-shader2", "fragment-shader2");
    gl.useProgram(program2);
*/
    vBuff2 = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vBuff2);
    gl.bufferData(gl.ARRAY_BUFFER, flatten(vertices2), gl.STATIC_DRAW);

    vPos2 = gl.getAttribLocation(program1, "vPosition");
    gl.vertexAttribPointer(vPos2, 4, gl.FLOAT, false, 0, 0);
    //gl.enableVertexAttribArray(vPos2);

    iBuff2 = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, iBuff2);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array(indices2), gl.STATIC_DRAW);

    tBuff2 = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, tBuff2);
    gl.bufferData(gl.ARRAY_BUFFER, flatten(tcs2), gl.STATIC_DRAW);

    fTexCoord2 = gl.getAttribLocation(program1, "vTexCoord");
    gl.vertexAttribPointer(fTexCoord2, 2, gl.FLOAT, false, 0, 0);
    //gl.enableVertexAttribArray(fTexCoord2);

    sampler2 = gl.getUniformLocation(program1, "texture");

    texture2 = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture2);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, images[1]);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

    gl.bindTexture(gl.TEXTURE_2D, null);

    render();
};

function render() {
    gl.clear(gl.COLOR_BUFFER_BIT);

    gl.useProgram(program1);

    gl.bindBuffer(gl.ARRAY_BUFFER, vBuff1);
    gl.enableVertexAttribArray(vPos1);
    gl.enableVertexAttribArray(fTexCoord1);

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture1);

    gl.uniform1i(sampler1, 0);

//  gl.bindBuffer(gl.ARRAY_BUFFER, vBuff1);
//  gl.enableVertexAttribArray(vPos1);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, iBuff1);
    gl.drawElements(gl.TRIANGLES, indices1.length, gl.UNSIGNED_BYTE, 0);

    //gl.bindTexture(gl.TEXTURE_2D, null);

//  gl.useProgram(program2);

    gl.bindBuffer(gl.ARRAY_BUFFER,vBuff2);
    gl.enableVertexAttribArray(vPos2);
    gl.enableVertexAttribArray(fTexCoord2);

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture2);

    gl.uniform1i(sampler2, 0);

//  gl.bindBuffer(gl.ARRAY_BUFFER, vBuff2);
//  gl.enableVertexAttribArray(vPos2);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, iBuff2);

    gl.drawElements(gl.TRIANGLES, indices2.length, gl.UNSIGNED_BYTE, 0);

    requestAnimFrame(render);
}