【问题标题】:Editing texture colors - WebGL编辑纹理颜色 - WebGL
【发布时间】:2018-05-29 22:37:05
【问题描述】:

我使用 WebGL 在一个简单的立方体上应用了纹理。纹理是一个有 2 种颜色的棋盘;这是结果:

我想知道如何只为某些像素编辑纹理的颜色,以便使用不同的颜色在这个立方体上获得眼睛或嘴巴之类的东西。

这是我用来构建检查板的代码:

var colorsArray = [];

var vertexColors = [
                    vec4( 1.0, 0.0, 1.0, 1.0 ),  //
                    vec4( 1.0, 1.0, 1.0, 1.0 ),  //
                    vec4( 1.0, 0.0, 1.0, 1.0 ),  //
                    vec4( 1.0, 1.0, 1.0, 1.0 ),  //
                    vec4( 1.0, 0.0, 1.0, 1.0 ),  //
                    vec4( 1.0, 1.0, 1.0, 1.0 ),  //
                    vec4( 1.0, 1.0, 1.0, 1.0 ),  //
                    vec4( 1.0, 1.0, 1.0, 1.0 )   //
                    ];

var move_forward = false;

// TEXTURE
var texSize = 256;
var numChecks = 8;
var c;

var image1 = new Uint8Array(4*texSize*texSize);

for ( var i = 0; i < texSize; i++ ) {
    for ( var j = 0; j <texSize; j++ ) {
        var patchx = Math.floor(i/(texSize/numChecks));
        var patchy = Math.floor(j/(texSize/numChecks));
        if(patchx%2 ^ patchy%2) c = 255;
        else c = 0;
        //c = 255*(((i & 0x8) == 0) ^ ((j & 0x8)  == 0))
        image1[4*i*texSize+4*j] = c;
        image1[4*i*texSize+4*j+1] = c;
        image1[4*i*texSize+4*j+2] = c;
        image1[4*i*texSize+4*j+3] = 255;
    }
}

var image2 = new Uint8Array(4*texSize*texSize);

// Create a checkerboard pattern
for ( var i = 0; i < texSize; i++ ) {
    for ( var j = 0; j <texSize; j++ ) {
        image2[4*i*texSize+4*j] = 127+127*Math.sin(0.1*i*j);
        image2[4*i*texSize+4*j+1] = 127+127*Math.sin(0.1*i*j);
        image2[4*i*texSize+4*j+2] = 127+127*Math.sin(0.1*i*j);
        image2[4*i*texSize+4*j+3] = 255;
    }
}

var texture1, texture2;
var t1, t2;

var texCoordsArray = [];

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

function configureTexture() {
    texture1 = gl.createTexture();
    gl.bindTexture( gl.TEXTURE_2D, texture1 );
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize, texSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, image1);
    gl.generateMipmap( gl.TEXTURE_2D );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER,
                     gl.NEAREST_MIPMAP_LINEAR );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

    texture2 = gl.createTexture();
    gl.bindTexture( gl.TEXTURE_2D, texture2 );
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize, texSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, image2);
    gl.generateMipmap( gl.TEXTURE_2D );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER,
                     gl.NEAREST_MIPMAP_LINEAR );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
}

【问题讨论】:

    标签: webgl textures


    【解决方案1】:

    这个问题有多种解决方案。

    1. (最佳选项)使用着色器将您加载的面部图像分层到棋盘顶部。如果您愿意,这甚至可以让您完全避免使用棋盘格的纹理。这是最好的选择,因为学习着色器对于任何图形情况都是必须的。

    2. 加载面部图像并将其融合到纹理中。

    3. (不好的选择,但有效)使用一些花哨的数学在纹理上绘制人脸。

    每一项都需要一些知识来完成:

    1. Shaders

    2. Loading textures from a file

    第三种方法是最棘手的,但在没有太多额外知识的情况下最容易实现。我不知道你想要的脸有多复杂,任何比卡通眼睛和嘴巴更复杂的东西都是不可能的。

    一般的想法是编写一个函数,使一条曲线(例如在Desmos 中)跨越 2 个点。这是我的等式:x(x-30)*0.03。在 JS 中,只需为 0 到 30 创建一个 for 循环,然后评估该函数,这将是眼睛底部的高度(相对于起点)。您也可以否定该功能以获得最佳效果。然后你可以为学生画一个圆圈。然后重复另一只眼睛。这只是我的看法,你真的需要玩它并发挥创造力。

    祝你好运!

    【讨论】:

    • 感谢您的帮助,这些都是很好的解决方案,不幸的是我无法使用其他着色器来完成此任务并且我无法加载其他图像,我需要更改 2 个小方块的颜色检查板画眼睛:例如 3 行 - 第 3 列和第 7 列;其他人则指着嘴。
    • 只需更改图像数组中的一些值。类似image1.set([255, 255, 255, 255], 4*(y*texSize+x)) 的东西(使用set 一次分配多个元素)。或者您可以使用单独的 2d 画布绘制脸部,然后将其用作纹理数据。
    猜你喜欢
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    • 2016-08-28
    • 2011-10-04
    相关资源
    最近更新 更多