WebGL纹理颜色编辑:如何修改立方体纹理指定像素
嘿,这个需求超有意思!要在你现有的双色棋盘格纹理上叠加眼睛、嘴巴这类彩色图案,核心思路其实很简单——在生成纹理像素的循环里,给特定区域的像素单独设置彩色值就行。我结合你提供的代码,给你拆解具体的实现步骤:
具体实现步骤
1. 先确定图案的位置与颜色
你的纹理尺寸是256x256,所以像素坐标范围是0~255(x和y方向)。先想好你要画的图案位置:比如把眼睛放在纹理上半部分,嘴巴放在中间偏下的位置,再给它们指定鲜艳的颜色(比如眼睛用深蓝色,嘴巴用红色)。
2. 修改纹理生成代码,加入图案逻辑
你现在生成棋盘格纹理的image1循环里,已经有了给每个像素设置灰度值的逻辑。我们只需要在这个基础上,增加区域判断:如果当前像素落在眼睛/嘴巴的区域内,就覆盖成对应的彩色值。
修改后的image1生成代码如下:
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; // -------------- 新增图案判断逻辑 -------------- // 左眼:x在80-100,y在100-120,蓝色(0,0,255) if (i >= 80 && i <= 100 && j >= 100 && j <= 120) { image1[4*i*texSize+4*j] = 0; // R通道 image1[4*i*texSize+4*j+1] = 0; // G通道 image1[4*i*texSize+4*j+2] = 255; // B通道 } // 右眼:x在156-176,y在100-120,蓝色 else if (i >= 156 && i <= 176 && j >= 100 && j <= 120) { image1[4*i*texSize+4*j] = 0; image1[4*i*texSize+4*j+1] = 0; image1[4*i*texSize+4*j+2] = 255; } // 嘴巴:x在100-156,y在160-170,红色(255,0,0) else if (i >= 100 && i <= 156 && j >= 160 && j <= 170) { image1[4*i*texSize+4*j] = 255; image1[4*i*texSize+4*j+1] = 0; image1[4*i*texSize+4*j+2] = 0; } // 非图案区域,沿用棋盘格灰度值 else { image1[4*i*texSize+4*j] = c; image1[4*i*texSize+4*j+1] = c; image1[4*i*texSize+4*j+2] = c; } // Alpha通道保持不透明 image1[4*i*texSize+4*j+3] = 255; } }
小提示:画更复杂的形状
如果想要圆形眼睛这类不是矩形的图案,可以用距离公式判断:比如判断当前像素到圆心的距离是否小于半径,示例代码如下:
// 圆形左眼:圆心(90,110),半径10 const centerX = 90, centerY = 110, radius = 10; const distance = Math.sqrt(Math.pow(i - centerX, 2) + Math.pow(j - centerY, 2)); if (distance <= radius) { // 设置蓝色 image1[4*i*texSize+4*j] = 0; image1[4*i*texSize+4*j+1] = 0; image1[4*i*texSize+4*j+2] = 255; }
3. 可选:动态修改纹理(实时更新图案)
如果之后想要动态调整图案(比如让眼睛变色、嘴巴动起来),不用每次重新生成整个纹理,直接修改image1中对应像素的值,再用gl.texSubImage2D更新纹理的局部区域即可,性能会更好:
function updateLeftEyeColor(newR, newG, newB) { // 遍历左眼区域的像素,修改颜色 for (let i = 80; i <= 100; i++) { for (let j = 100; j <= 120; j++) { const index = 4*i*texSize + 4*j; image1[index] = newR; image1[index+1] = newG; image1[index+2] = newB; } } // 绑定纹理,更新局部区域 gl.bindTexture(gl.TEXTURE_2D, texture1); // 参数说明:纹理类型、层级、起始x、起始y、宽度、高度、格式、数据类型、像素数据 gl.texSubImage2D(gl.TEXTURE_2D, 0, 80, 100, 21, 21, gl.RGBA, gl.UNSIGNED_BYTE, image1.subarray(4*80*texSize + 4*100, 4*(80+21)*texSize + 4*(100+21))); // 如果开启了mipmap,需要重新生成 gl.generateMipmap(gl.TEXTURE_2D); } // 调用示例:把左眼改成绿色 updateLeftEyeColor(0, 255, 0);
这样修改后,你的立方体纹理上就会出现你想要的彩色图案啦,你可以根据自己的喜好调整区域坐标和颜色~
内容的提问来源于stack exchange,提问作者KiririIG
相关产品推荐
相关产品推荐

