Opengl 如何在.obj模型上正确重复纹理?

Opengl 如何在.obj模型上正确重复纹理?,opengl,webgl,Opengl,Webgl,当我将此图片加载到沙发模型上时: 我明白了: 我的纹理参数如下所示: 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

当我将此图片加载到沙发模型上时:

我明白了:

我的纹理参数如下所示:

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.CLAMP_更改为gl.REPEAT时

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
即使这张f图是2的幂,我也得到了同样的模糊图像

这是正常的行为吗?我想看到这个F在模型上重复。例如:


您需要显示.OBJ加载代码

在THREE.js中加载相同的文件并应用相同的纹理

我使用了底部的示例,然后在加载模型后,我遍历了所有节点并像这样应用了纹理

        const loader = new THREE.TextureLoader();
        const texture = loader.load('resources/images/f-texture.png');
        texture.wrapS = THREE.RepeatWrapping;
        texture.wrapT = THREE.RepeatWrapping;
        root.traverse((node) => {
          if (node.material) {
            if (Array.isArray(node.material)) {
              node.material.forEach((m) => {
                m.map = texture;
              });
            } else {
              node.material.map = texture;
            }
          }
        });
我还写了自己的.OBJ加载器

“严格使用”;
常数vs=`
均匀mat4 u_世界视图投影;
属性向量4位置;
属性向量2 texcoord;
可变矢量2 v_texCoord;
void main(){
v_texCoord=texCoord;
gl_位置=u_世界视图投影*位置;
}
`;
常数fs=`
精密中泵浮子;
可变矢量2 v_texCoord;
均匀二维u_扩散;
void main(){
gl_FragColor=纹理2D(u_漫反射,v_texCoord);
}
`;
函数loadTextFile(url){
返回fetch(url).then(req=>req.text());
}
函数addModel(上下文){
if(context.faces){
const{faces,modelName,materialName}=context;
context.models.push({
面、模型名、材质名、,
});
context.faces=未定义;
}
}
函数addDataFn(名称){
返回函数(上下文、参数){
addModel(上下文);
const{data}=上下文;
如果(!数据[名称]){
数据[名称]={
numComponents:args.length,
数据:[],
};
}
data[name].data.push(…args.map(parseFloat));
};
}
函数addPropFn(名称){
返回函数(上下文、参数){
上下文[名称]=args.join(“”);
};
}
函数addFace(上下文,参数){
如果(!context.faces){
context.faces=[];
}
context.faces.push(args.map((垂直)=>{
返回垂直拆分('/').map(v=>v.length?parseInt(v):未定义);
}));
}
函数noop(){
}
常数objHandlers={
mtllib:addPropFn('mtllib'),
v:addDataFn(“位置”),
vn:addDataFn('normal'),
vt:addDataFn('texcoord'),
g:addPropFn('modelName'),
o:addPropFn('modelName'),
usemtl:addPropFn('materialName'),
s:不,
f:addFace,
};
函数parseObj(objText){
常量上下文={
数据:{},
型号:[],
};
objText.split('\n').forEach((origLine,lineNo)=>{
常量noCommentLine=原始线。替换(/#.*/,'');
const line=noCommentLine.trim();
如果(行==''){
返回;
}
const parts=line.split(/\s+/);
常量代码=parts.shift();
常量fn=对象句柄[代码];
如果(!fn){
console.error('未知代码:',代码'at line',lineNo+1',:',line);
}否则{
fn(上下文、部分);
}
});
addModel(上下文);
常量数组={};
常数指数=[];
设numVerts=0;
常数vertIds={};
const arrayNames=Object.keys(context.data);
for(Object.entries(context.data)的常量[name,src]{
数组[名称]={
numComponents:src.numComponents,
数据:[],
};
}
//对于f语句
//f v/vt/vn->位置/texcoord/正常
const channelNames=[
“位置”,
“texcoord”,
“正常”,
];
函数addVertex(顶点扩展){
常量部分=[];
vertexpartitions.forEach((partNdx,ndx)=>{
if(partNdx!==未定义){
零件。推送(ndx,零件ndx);
}
});
const vId=parts.join(',');
设vertNdx=vertIds[vId];
if(vertNdx==未定义){
vertNdx=numVerts++;
vertIds[vId]=vertNdx;
vertexpartitions.forEach((partNdx,ndx)=>{
if(partNdx==未定义){
返回;
}
const name=channelNames[ndx];
const data=context.data[name];
const start=(partNdx-1)*data.numComponents;
const end=start+data.numComponents;
if(end>data.data.length){
调试器;
}
常量值=data.data.slice(开始、结束);
如果(values.length!==3){
调试器;
}
数组[name].data.push(…值);
});
}
返回vertNdx;
}
for(context.models的常量模型){
用于(模型面的常数面){
const numVerts=面长度;
如果(numVerts<3){
抛出新错误(“面的numVerts不至少为3”);
}
如果(numVerts>4){
调试器;
}
常量vNdx0=添加顶点(面[0]);
for(设i=1;i65535?UINT32阵列:UINT16阵列)(索引),
};
返回阵列;
}
异步函数main(){
const objText=wait loadTextFile('models/obj/sofa/ROUND sofa.obj');
常量数组=parseObj(objText);
常数m4=twgl.m4;
const gl=twgl.getContext(document.querySelector(“#c”);
const programInfo=twgl.createProgramInfo(gl[vs,fs]);
const bufferInfo=twgl.createBufferInfoFromArrays(gl,arrays);
常量tex=twgl.createTexture(gl{
src:'images/f-texture.png',
弗利皮:是的,
});
警察制服={
u_扩散:tex,
};
函数渲染(时间){
时间*=0.001;
twgl.resizeCanvasToDisplaySize(总图画布);
总图视口(0,0,总图画布宽度,总图画布高度);
总帐启用(总帐深度测试);
总账启用(总账消隐面);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
常数fov=30*Math.PI/180;
const aspect=gl.canvas.clientWidth/gl.canvas.clientHeight;
常数zNear=1;
常数zFar=10000;
常量投影=m4.透视图(视野、纵横比、zNear、zFar);
常数眼=[5002000,-3000];
常量目标=[0400,0];
const up=[0,1,0];
常量摄影机=m4。注视(眼睛、目标、向上);
常量视图=m4。反向(摄像头);
常量视图投影=m