将多个纹理映射到3D立方体,但只显示一个

时间:2018-03-04 06:29:56

标签: javascript html webgl textures

我有六个纹理,我试图将其映射到一个3D立方体,每张面都有一张图片。我已将所有6个图像的url存储在一个数组中,并将所有6个图像绑定到webgl。但是,只有我的url数组的第一个图像被映射到所有6个面。我似乎正在正确地增加纹理单位,可能是我为每个面使用相同的纹理坐标?任何帮助表示赞赏。感谢

TexturedCube.js

var gl;
var canvas;
var program;
var points = [];
var colors = [];
var texCoordsArray = [];
var loadedImageCount = 0;

var fs_textureLoc;
var objOffset = 0;
var twoTriangles = 36;

var xAxis = 0;
var yAxis = 1;
var zAxis = 2;
var axis = 0;
var theta = [ 0, 0, 0 ];


var near = 0.3;
var far = 3.0;

var fovy = 45.0;
var aspect;
var VMatrixLoc, PMatrixLoc;
var vs_ViewMatrix, vs_ProjMatrix;

var imageTextures = [
    "https://c1.staticflickr.com/5/4625/26712799268_7c59b1e10e_q.jpg",
    "https://c1.staticflickr.com/5/4665/40543467892_1aef2f9307_q.jpg",
    "https://c1.staticflickr.com/5/4787/40556861052_7982f5ca6e_q.jpg",
    "https://c1.staticflickr.com/5/4756/40543466622_a0f7c22346_q.jpg",
    "https://c1.staticflickr.com/5/4716/38775586080_cc55674d74_q.jpg",
    "https://c1.staticflickr.com/5/4714/39875195484_003850f098_q.jpg"
];

var faceColors = [
    [ 0.0, 0.0, 0.0, 1.0 ],  // black
    [ 1.0, 0.0, 0.0, 1.0 ],  // red
    [ 1.0, 1.0, 0.0, 1.0 ],  // yellow
    [ 0.0, 1.0, 0.0, 1.0 ],  // green
    [ 0.0, 0.0, 1.0, 1.0 ],  // blue
    [ 1.0, 0.0, 1.0, 1.0 ],  // magenta
    [ 0.0, 1.0, 1.0, 1.0 ],  // cyan
    [ 1.0, 1.0, 1.0, 1.0 ]   // white
];

window.onload = function init()
{
    canvas = document.getElementById("gl-canvas");

    gl = WebGLUtils.setupWebGL(canvas);
    if (!gl){ alert("not available."); }

    buildCube();

    gl.viewport(0, 0, canvas.height, canvas.width);
    gl.clearColor(1.0, 1.0, 1.0, 1);
    gl.enable(gl.DEPTH_TEST);

    program = initShaders(gl, "vertex-shader", "fragment-shader");
    gl.useProgram(program);

    document.getElementById( "xButton" ).onclick = function () {
        axis = xAxis;
    };
    document.getElementById( "yButton" ).onclick = function () {
        axis = yAxis;
    };
    document.getElementById( "zButton" ).onclick = function () {
        axis = zAxis;
    };

    initializeImages();
    loadBuffers();
    setViewProjection();
    render();
}

function initializeImages()
{
    loadedImageCount = 0;

    for (var i = 0; i < imageTextures.length; ++i)
    {
        loadImage(program, imageTextures[i], i);
    }
}

function loadImage(program, url, txtUnit)
{
    var texture = gl.createTexture();

    fs_textureLoc = gl.getUniformLocation(program, "fs_texture");

    var image = new Image();

    image.onload = function(){ 
        loadTexture(image, texture, txtUnit);
    };

    image.crossOrigin = "anonymous";
    image.src = url;
}

function loadTexture(image, texture, txtUnit)
{
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);

    gl.activeTexture(gl.TEXTURE0 + txtUnit);
    gl.bindTexture(gl.TEXTURE_2D, texture);

    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.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

    loadedImageCount += 1;
}

function loadBuffers()
{       
    // Load the colors for the triangles and enable the attribute vColor
    var cBuffer = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer );
    gl.bufferData( gl.ARRAY_BUFFER, flatten(colors), gl.STATIC_DRAW );

    var vColor = gl.getAttribLocation( program, "vColor" );
    gl.vertexAttribPointer( vColor, 4, gl.FLOAT, false, 0, 0 );
    gl.enableVertexAttribArray( vColor );

    // Load the vertices for the triangles and enable the attribute vPosition
    var vBuffer = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer );
    gl.bufferData( gl.ARRAY_BUFFER, flatten(points), gl.STATIC_DRAW );

    var vPosition = gl.getAttribLocation( program, "vPosition" );
    gl.vertexAttribPointer( vPosition, 4, gl.FLOAT, false, 0, 0 );
    gl.enableVertexAttribArray( vPosition );

    var tBuffer = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, tBuffer );
    gl.bufferData( gl.ARRAY_BUFFER, flatten(texCoordsArray), gl.STATIC_DRAW );

    var vTexCoord = gl.getAttribLocation( program, "vTexCoord" );
    gl.vertexAttribPointer( vTexCoord, 2, gl.FLOAT, false, 0, 0 );
    gl.enableVertexAttribArray( vTexCoord );
}

function buildCube()
{
    buildFace(1, 0, 3, 2);
    buildFace(2, 3, 7, 6);
    buildFace(3, 0, 4, 7);
    buildFace(6, 5, 1, 2);
    buildFace(4, 5, 6, 7);
    buildFace(5, 4, 0, 1);
}

function buildFace(a, b, c, d)
{
    var verts = [
        vec4( -0.5, -0.5,  0.5, 1.0),
        vec4( -0.5,  0.5,  0.5, 1.0),
        vec4(  0.5,  0.5,  0.5, 1.0),
        vec4(  0.5, -0.5,  0.5, 1.0),
        vec4( -0.5, -0.5, -0.5, 1.0),
        vec4( -0.5,  0.5, -0.5, 1.0),
        vec4(  0.5,  0.5, -0.5, 1.0),
        vec4(  0.5, -0.5, -0.5, 1.0)        
    ];

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

    let indices = [a, b, c, a, c, d];
    let texIndices = [1, 0, 3, 1, 3, 2];
    for (var i = 0; i < indices.length; ++i)
    {
        points.push(verts[indices[i]]);
        texCoordsArray.push(texCoord[texIndices[i]]);
        numVertices += 1;
        colors.push(faceColors[7]);
    }
}

function setViewProjection()
{
    VMatrixLoc = gl.getUniformLocation(program, "vs_ViewMatrix");
    PMatrixLoc = gl.getUniformLocation(program, "vs_ProjMatrix");   

    if (!VMatrixLoc || !PMatrixLoc){ console.log("failed"); }

    eyePt = vec3(0, 0, 5);
    atPt = vec3(0, 0, 0);
    upVec = vec3(0, 1, 0);

    vs_ViewMatrix = lookAt(eyePt, atPt, upVec);

    vs_ViewMatrix = mult(vs_ViewMatrix, rotate(theta[xAxis], [1, 0, 0]));
    vs_ViewMatrix = mult(vs_ViewMatrix, rotate(theta[yAxis], [0, 1, 0]));
    vs_ViewMatrix = mult(vs_ViewMatrix, rotate(theta[zAxis], [0, 0, 1]));

    fovy = 50;
    aspect = canvas.width/canvas.height;
    near = 1;
    far = 100;

    vs_ProjMatrix = perspective(fovy, aspect, near, far);

    gl.uniformMatrix4fv(VMatrixLoc, false, flatten(vs_ViewMatrix));
    gl.uniformMatrix4fv(PMatrixLoc, false, flatten(vs_ProjMatrix));
}

function render()
{
    gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    gl.clearColor(0.0, 0.0, 0.0, 0.1);

    theta[axis] += 2.0;

    objOffSet = 0;

    if (loadedImageCount == imageTextures.length)
    {
        for (var txtUnit = 0; txtUnit < 6; ++txtUnit)
        {
            gl.uniform1i(fs_textureLoc, txtUnit);
            gl.drawArrays(gl.TRIANGLES, objOffSet, twoTriangles);
            objOffset += twoTriangles;
        }
    }

    requestAnimFrame( render );
}

TexturedCube.html

<!DOCTYPE html>
<html>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute  vec4 vPosition;
attribute  vec4 vColor;
attribute  vec2 vTexCoord;

varying    vec2 fTexCoord;
varying    vec4 fColor;

uniform mat4 vs_ViewMatrix;
uniform mat4 vs_ProjMatrix;

void main()
{       
    fColor = vColor;
    fTexCoord = vTexCoord;
    gl_Position = vs_ProjMatrix * vs_ViewMatrix * vPosition;
}

</script>
<script id="fragment-shader" type="x-shader/x-fragment">

precision mediump float;

varying vec4 fColor;
varying vec2 fTexCoord;

uniform sampler2D fs_texture;
void main()
{
    gl_FragColor = fColor * texture2D(fs_texture, fTexCoord);
}
</script>

<script type="text/javascript" src="../Common/webgl-utils.js"></script>
<script type="text/javascript" src="../Common/initShaders.js"></script>
<script type="text/javascript" src="../Common/MV.js"></script>
<script type="text/javascript" src="TexturedCube.js"></script>

<body>
<canvas id="gl-canvas" width="512" height="512">
Oops ... your browser doesn't support the HTML5 canvas element
</canvas>

<br/>
<button id= "xButton">Rotate X</button>
<button id= "yButton">Rotate Y</button>
<button id= "zButton">Rotate Z</button>

<input id="eyesliderx" type="range" min="-5"   max="5"   value="0" class="slider">
<input id="eyeslidery" type="range" min="-5"   max="5"   value="0" class="slider">
<input id="eyesliderz" type="range" min="-5"   max="5"   value="2" class="slider">
<input id="atsliderx"  type="range" min="-5"   max="5"   value="0" class="slider">
<input id="atslidery"  type="range" min="-5"   max="5"   value="0" class="slider">
<input id="atsliderz"  type="range" min="-100" max="100" value="0" class="slider">
<input id="upsliderx"  type="range" min="-1"   max="1"   value="0" class="slider">
<input id="upslidery"  type="range" min="-1"   max="1"   value="1" class="slider">
<input id="upsliderz"  type="range" min="-1"   max="1"   value="0" class="slider">

</body>
</html>

1 个答案:

答案 0 :(得分:1)

36是多维数据集的所有6个边的索引数。 6将是2个三角形的索引数。

更改var

var twoTriangles = 36;

var twoTriangles = 6;

但这不是唯一的问题。可能你从6变为36,因为twoTriangles = 6只能看到立方体的第一面。这是因为循环中出现了一个区分大小写的拼写错误,它会绘制多维数据集的6个边:

objOffset = 0; // <------ "objOffset" instead of "objOffSet"

for (var txtUnit = 0; txtUnit < 6; ++txtUnit)
{
    gl.uniform1i(fs_textureLoc, txtUnit);
    gl.drawArrays(gl.TRIANGLES, objOffset, twoTriangles);
    objOffset += twoTriangles;
}