Webgl 如何仅重复纹理的一部分?

Webgl 如何仅重复纹理的一部分?,webgl,webgl2,Webgl,Webgl2,我有纹理的图像 我只想重复这个纹理的一部分。 例如,第一行中从[0.5,0]到[0.75,0.25]的第三个矩形。(棕色的那个) 在Webgl 2中有什么方法可以做到这一点吗 另外,也许可以使用纹理偏移和其他方法来完成 谢谢大家! 要重复纹理的一部分,可以在着色器中通过设置定义要重复的纹理部分的一致性来完成 // uniform that defines the x, y (top left) and width and height of repeat uniform vec4 repeat;

我有纹理的图像

我只想重复这个纹理的一部分。 例如,第一行中从[0.5,0]到[0.75,0.25]的第三个矩形。(棕色的那个)

在Webgl 2中有什么方法可以做到这一点吗

另外,也许可以使用纹理偏移和其他方法来完成


谢谢大家!

要重复纹理的一部分,可以在着色器中通过设置定义要重复的纹理部分的一致性来完成

// uniform that defines the x, y (top left) and width and height of repeat
uniform vec4 repeat; // x, y, w, h  
然后可以按如下所示重复纹理

gl_FragColor = vec4(texture2D(tex, mod(uv, vec2(1)) * repeat.zw + repeat.xy));
当您使用未设置为
最近的
的纹理时,会出现一个问题,因为插值会将边缘处的像素压缩为出血。这将导致纹理重复处出现不需要的可见接缝

最简单的修复方法是将重复图案大小减少一个像素,将图案开始位置减少半个像素

// example for 256 texture size

const pixel = 1 / 256;
const repeat = [0.5 + pixel / 2, 0.0 + pixel / 2 ,0.25 - pixel, 0.25 - pixel];
例子 示例创建一个纹理(右侧的图像),然后在左侧的画布中渲染该文本的随机部分。重复设置为每个新渲染的随机数量

const着色器={
vs:`
属性向量2垂直;
可变vec2紫外线;
void main(){
uv=垂直;
gl_位置=向量4(垂直,0.0,1.0);
}`, 
fs:`精密中泵浮动;
均匀采样2d-tex;
可变vec2紫外线;
均匀vec4重复;
均匀的vec2瓷砖;
void main(){
gl_FragColor=vec4(纹理2d(tex,mod(uv*tiles,vec2(1))*repeat.zw+repeat.xy));
}`
};
const colors=“#ff0000,#ff8800,#ffff00,#88ff00,#00ff00,#00ff88,#00f0f0,#0088ff,#0000ff,#8800ff,#ff00ff,#ff0088”。拆分(“,”;
const randCol=(cols=colors)=>cols[Math.random()*cols.length|0];
常量F32A=a=>新的浮点32数组(a),UI16A=a=>新的UINT16数组(a);
const GLBuffer=(数据,类型=gl.ARRAY\u BUFFER,use=gl.STATIC\u DRAW,buf)=>(gl.bindBuffer(类型,buf=gl.createBuffer()),gl.bufferData(类型,数据,使用),buf);
constgllocs=(shr,type,…names)=>names.reduce((o,name)=>(o[name]=(gl[`get${type}Location`])(shr,name),o),{});
常量GLShader=(prg,source,type=gl.FRAGMENT\u着色器,shr)=>{
gl.shaderSource(shr=gl.createShader(类型),源);
总帐编辑主任(shr);
总承包商附件(prg,shr);
}
函数纹理(gl,图像,{min=“LINEAR”,mag=“LINEAR”}={}){
常量纹理=gl.createTexture();
目标=gl.TEXTURE_2D;
gl.bindTexture(目标、纹理);
gl.texParameteri(目标,gl.TEXTURE_MIN_过滤器,gl[MIN]);
gl.texParameteri(目标,gl.TEXTURE\u MAG\u过滤器,gl[MAG]);
gl.texImage2D(目标,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_字节,图像);
返回纹理;
}
常量bindTexture=(纹理,单位=0)=>{gl.activeTexture(gl.TEXTURE0+单位);gl.bindTexture(gl.texture\u 2D,纹理)}
const createTag=(tag,props={})=>Object.assign(document.createElement(tag),props);
const appendEl=(par,…sibs)=>sibs.reduce((p,sib)=>(p.appendChild(sib),p),par);
函数createTexture(宽度=256,高度=256){
const-tex=createTag(“画布”{宽度、高度、类名:“纹理”});
附录(document.body,tex);
const ctx=tex.getContext(“2d”);
变量x=4,y=4,计数=0;
const xStep=宽度/x,yStep=高度/y;
ctx.font=(yStep*0.95 | 0)+“px arial”;
ctx.textAlign=“中心”;
ctx.textb基线=“中间”;
而(y--){
x=4;
而(x-){
ctx.fillStyle=randCol();
ctx.fillRect(x*xStep,y*yStep,xStep,yStep);
ctx.fillStyle=“#000”;
ctx.fillText((count++).toString(16.toUpperCase(),(x+0.5)*xStep,(y+0.5)*yStep);
}
}
setTransform(1,0,0,-1,0,高度);
ctx.globalCompositeOperation=“复制”;
ctx.drawImage(tex,0,0);
bindTexture(纹理(gl,tex));
ctx.drawImage(tex,0,0);
}
var-W;
const gl=canvas.getContext(“webgl”);
请求动画帧(renderRandom);
addEventListener(“调整大小”,renderRandom);
const prog=gl.createProgram();
GLShader(prog、shaders.vs、gl.VERTEX_着色器);
GLShader(prog,shaders.fs);
总账链接程序(prog);
德国劳埃德船级社使用计划(prog);
const locs=GLLocs(prog,“统一”、“重复”、“平铺”);
常量attIdxs=GLLocs(prog,“Attrib”,“vert”);
GLBuffer(F32A([-1,-1,1,-1,1]);
GLBuffer(UI16A([1,2,3,0,1,3]),gl.ELEMENT\u ARRAY\u BUFFER);
gl.EnableVertexAttributeArray(attIdxs.vert);
gl.VertexAttribute指针(attIdxs.vert,2,gl.FLOAT,false,0,0);
createTexture();
函数renderRandom(){
gl.viewport(0,0,W=canvas.width=Math.min(innerWidth,innerHeight),canvas.height=W);
常量textPxSize=1/256;
常数x=(Math.random()*4 | 0)/4+textPxSize/2;
常数y=(Math.random()*4 | 0)/4+textPxSize/2;
常数tiles=Math.random()*8+1 | 0;
gl.uniform4fv(位置重复,F32A([x,y,0.25-textPxSize,0.25-textPxSize]);
gl.uniform2fv(局部瓷砖,F32A([瓷砖,瓷砖]);
总帐付款人(总帐三角形,6,总帐无符号_短,0);
设置超时(renderRandom,4000);
}
画布{
边框:2件纯黑;
}
.texture{宽度:128px;高度:128px;}

mod
紫外线在阴影中,请您再解释一下。过去几天我试图找到解决办法。有人说这是不可能的。我没有找到任何例子。如果你能提供任何信息在这种情况下,我会很高兴!