Three.js - 顶点着色器 UV 变量 return 只有 0,0
Three.js - Vertex Shader UV variable return only 0,0
我用 OBJLoader 加载了一个对象。我想使用带有纹理的着色器材质。我将我的纹理传递给材质的制服参数。
我将 UV 变量从顶点着色器传递到片段着色器。
但是当我使用 uv 坐标来映射我的纹理时,我得到的总是 0,0 或至少这是它看起来的样子。整个对象用纹理的左下像素着色。
这是我的着色器:
<script type='x-shader/x-vertex' id='vertex-shader'>
uniform float u_time;
varying vec2 vUv;
void main() {
vUv = uv;
vec4 pos = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
gl_Position = pos;
}
</script>
<script type='x-shader/x-fragment' id='fragment-shader'>
precision highp float;
uniform float u_time;
uniform vec2 u_resolution;
uniform sampler2D texture;
varying vec2 vUv;
void main(){
vec2 st = vUv;
vec4 tex = texture2D(texture, st);
gl_FragColor = tex;
}
</script>
这是我加载对象和分配材质的方式
var loader = new THREE.OBJLoader();
loader.load(
'assets/standing.obj',
function (object){
main.man = object;
main.man.position.set(0,-600,400);
main.texture = new THREE.TextureLoader().load( 'assets/na_00004c.jpg' );
main.texture_needsUpdate = true;
var uniforms = {
u_time:{type:'f', value:0.0},
u_mouse:{type:'v2', value: new THREE.Vector2()},
u_resolution: {type: 'v2', value: {x:2048.,y:1024.}},
texture: {type: 't', value: main.texture}
}
main.material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertex-shader').textContent,
fragmentShader: document.getElementById('fragment-shader').textContent,
transparent: true
});
main.material.needsUpdate = true;
main.material.side = THREE.DoubleSide;
main.man.traverse(function(child){
if(child instanceof THREE.Mesh){
child.material = main.material;
child.material.needsUpdate = true;
child.geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );
child.geometry.computeVertexNormals();
child.geometry.elementsNeedUpdate = true;
child.geometry.mergeVertices();
child.verticesNeedUpdate = true;
child.normalsNeedUpdate = true;
child.uvsNeedUpdate = true;
child.material.flatShading = THREE.SmoothShading;
}
});
main.scene.add(main.man);
},
function (xhr){
console.log((xhr.loaded/xhr.total*100)+'% loaded');
},
function (error){
console.log(error,'An error happened');
}
);
这里有完整的例子
http://cmt.re/dev/na/
这是我想用作纹理的图像
http://cmt.re/dev/na/assets/na_00004c.jpg
有人知道为什么会这样吗?
非常感谢。
您的代码工作正常,但您的 *.obj
文件不包含任何纹理坐标。 Wavefront OBJ 文件(.obj 文件)是一个文本文件,纹理坐标是带有关键字 vt
的条目,如果缺少此条目,则网格没有任何纹理坐标。
您的代码工作正常,请参阅示例,其中我将您的原始代码与一个简单的模型一起使用:
var main = new function(){
this.init = function(){
this.initThree();
}
this.initThree = function(){
main.scene = new THREE.Scene();
main.scene.background = new THREE.Color(0xCCCCCC);
var aspectRatio = window.innerWidth / window.innerHeight;
main.camera = new THREE.PerspectiveCamera(75, aspectRatio, 0.1, 100000);
//main.camera.position.set(-40, 0, 512);
main.camera.position.set(1,2,0);
main.renderer = new THREE.WebGLRenderer({antialias: true});
main.renderer.setPixelRatio(window.devicePixelRatio);
main.renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(main.renderer.domElement);
main.controls = new THREE.OrbitControls(main.camera, main.renderer.domElement);
main.controls.enableDamping = true;
main.controls.dampingFactor = 0.1;
main.controls.screenSpacePanning = false;
var helper = new THREE.GridHelper(2000, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
main.scene.add(helper);
var axis = new THREE.AxesHelper();
main.scene.add(axis);
makeTextFile = function (text) {
var data = new Blob([text], {type: 'text/plain'});
var textFile = window.URL.createObjectURL(data);
return textFile;
}
var textbox_obj = document.getElementById('plane_obj');
var obj_url = makeTextFile(textbox_obj.value);
var loader = new THREE.OBJLoader();
loader.load(
obj_url,
function (object){
main.man = object;
//main.man.position.set(0,-600,400);
main.man.position.set(0,0,0);
main.texture = new THREE.TextureLoader().load( 'https://raw.githubusercontent.com/Rabbid76/graphics-snippets/master/resource/texture/Gominolas.png' );
main.texture_needsUpdate = true;
var uniforms = {
u_time:{type:'f', value:0.0},
u_mouse:{type:'v2', value: new THREE.Vector2()},
u_resolution: {type: 'v2', value: {x:2048.,y:1024.}},
texture: {type: 't', value: main.texture}
}
main.material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertex-shader').textContent,
fragmentShader: document.getElementById('fragment-shader').textContent,
transparent: true
});
main.material.needsUpdate = true;
main.material.side = THREE.DoubleSide;
// main.material = new THREE.MeshNormalMaterial();
main.man.traverse(function(child){
if(child instanceof THREE.Mesh){
child.material = main.material;
child.material.needsUpdate = true;
child.geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );
child.geometry.computeVertexNormals();
child.geometry.elementsNeedUpdate = true;
child.geometry.mergeVertices();
child.verticesNeedUpdate = true;
child.normalsNeedUpdate = true;
child.uvsNeedUpdate = true;
child.material.flatShading = THREE.SmoothShading;
}
});
main.scene.add(main.man);
},
function (xhr){
console.log((xhr.loaded/xhr.total*100)+'% loaded');
},
function (error){
console.log(error,'An error happened');
}
);
window.onresize = main.onResize;
this.render();
}
this.render = function(){
var time = Date.now();
main.controls.update();
requestAnimationFrame(main.render);
main.renderer.render(main.scene, main.camera);
}
this.onResize = function(event) {
main.renderer.setSize(window.innerWidth, window.innerHeight);
main.camera.aspect = window.innerWidth / window.innerHeight;
main.camera.updateProjectionMatrix();
}
}
main.init();
<script src="https://cdn.jsdelivr.net/npm/three@0.115/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.115/examples/js/controls/OrbitControls.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/OBJLoader.js"></script>
<textarea id="plane_obj" style="display:none;">
v -1.000000 0.000000 1.000000
v 1.000000 0.000000 1.000000
v -1.000000 0.000000 -1.000000
v 1.000000 0.000000 -1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 1.000000
vn 0.0000 1.0000 0.0000
f 1/1/1 2/2/1 4/4/1 3/3/1
</textarea>
<script type='x-shader/x-vertex' id='vertex-shader'>
uniform float u_time;
varying vec2 vUv;
void main() {
vUv = uv;
vec4 pos = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
gl_Position = pos;
}
</script>
<script type='x-shader/x-fragment' id='fragment-shader'>
precision highp float;
uniform float u_time;
uniform vec2 u_resolution;
uniform sampler2D texture;
varying vec2 vUv;
void main(){
vec2 st = vUv;
vec4 tex = texture2D(texture, st);
gl_FragColor = tex;
}
</script>
我用 OBJLoader 加载了一个对象。我想使用带有纹理的着色器材质。我将我的纹理传递给材质的制服参数。 我将 UV 变量从顶点着色器传递到片段着色器。
但是当我使用 uv 坐标来映射我的纹理时,我得到的总是 0,0 或至少这是它看起来的样子。整个对象用纹理的左下像素着色。
这是我的着色器:
<script type='x-shader/x-vertex' id='vertex-shader'>
uniform float u_time;
varying vec2 vUv;
void main() {
vUv = uv;
vec4 pos = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
gl_Position = pos;
}
</script>
<script type='x-shader/x-fragment' id='fragment-shader'>
precision highp float;
uniform float u_time;
uniform vec2 u_resolution;
uniform sampler2D texture;
varying vec2 vUv;
void main(){
vec2 st = vUv;
vec4 tex = texture2D(texture, st);
gl_FragColor = tex;
}
</script>
这是我加载对象和分配材质的方式
var loader = new THREE.OBJLoader();
loader.load(
'assets/standing.obj',
function (object){
main.man = object;
main.man.position.set(0,-600,400);
main.texture = new THREE.TextureLoader().load( 'assets/na_00004c.jpg' );
main.texture_needsUpdate = true;
var uniforms = {
u_time:{type:'f', value:0.0},
u_mouse:{type:'v2', value: new THREE.Vector2()},
u_resolution: {type: 'v2', value: {x:2048.,y:1024.}},
texture: {type: 't', value: main.texture}
}
main.material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertex-shader').textContent,
fragmentShader: document.getElementById('fragment-shader').textContent,
transparent: true
});
main.material.needsUpdate = true;
main.material.side = THREE.DoubleSide;
main.man.traverse(function(child){
if(child instanceof THREE.Mesh){
child.material = main.material;
child.material.needsUpdate = true;
child.geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );
child.geometry.computeVertexNormals();
child.geometry.elementsNeedUpdate = true;
child.geometry.mergeVertices();
child.verticesNeedUpdate = true;
child.normalsNeedUpdate = true;
child.uvsNeedUpdate = true;
child.material.flatShading = THREE.SmoothShading;
}
});
main.scene.add(main.man);
},
function (xhr){
console.log((xhr.loaded/xhr.total*100)+'% loaded');
},
function (error){
console.log(error,'An error happened');
}
);
这里有完整的例子 http://cmt.re/dev/na/
这是我想用作纹理的图像 http://cmt.re/dev/na/assets/na_00004c.jpg
有人知道为什么会这样吗?
非常感谢。
您的代码工作正常,但您的 *.obj
文件不包含任何纹理坐标。 Wavefront OBJ 文件(.obj 文件)是一个文本文件,纹理坐标是带有关键字 vt
的条目,如果缺少此条目,则网格没有任何纹理坐标。
您的代码工作正常,请参阅示例,其中我将您的原始代码与一个简单的模型一起使用:
var main = new function(){
this.init = function(){
this.initThree();
}
this.initThree = function(){
main.scene = new THREE.Scene();
main.scene.background = new THREE.Color(0xCCCCCC);
var aspectRatio = window.innerWidth / window.innerHeight;
main.camera = new THREE.PerspectiveCamera(75, aspectRatio, 0.1, 100000);
//main.camera.position.set(-40, 0, 512);
main.camera.position.set(1,2,0);
main.renderer = new THREE.WebGLRenderer({antialias: true});
main.renderer.setPixelRatio(window.devicePixelRatio);
main.renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(main.renderer.domElement);
main.controls = new THREE.OrbitControls(main.camera, main.renderer.domElement);
main.controls.enableDamping = true;
main.controls.dampingFactor = 0.1;
main.controls.screenSpacePanning = false;
var helper = new THREE.GridHelper(2000, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
main.scene.add(helper);
var axis = new THREE.AxesHelper();
main.scene.add(axis);
makeTextFile = function (text) {
var data = new Blob([text], {type: 'text/plain'});
var textFile = window.URL.createObjectURL(data);
return textFile;
}
var textbox_obj = document.getElementById('plane_obj');
var obj_url = makeTextFile(textbox_obj.value);
var loader = new THREE.OBJLoader();
loader.load(
obj_url,
function (object){
main.man = object;
//main.man.position.set(0,-600,400);
main.man.position.set(0,0,0);
main.texture = new THREE.TextureLoader().load( 'https://raw.githubusercontent.com/Rabbid76/graphics-snippets/master/resource/texture/Gominolas.png' );
main.texture_needsUpdate = true;
var uniforms = {
u_time:{type:'f', value:0.0},
u_mouse:{type:'v2', value: new THREE.Vector2()},
u_resolution: {type: 'v2', value: {x:2048.,y:1024.}},
texture: {type: 't', value: main.texture}
}
main.material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertex-shader').textContent,
fragmentShader: document.getElementById('fragment-shader').textContent,
transparent: true
});
main.material.needsUpdate = true;
main.material.side = THREE.DoubleSide;
// main.material = new THREE.MeshNormalMaterial();
main.man.traverse(function(child){
if(child instanceof THREE.Mesh){
child.material = main.material;
child.material.needsUpdate = true;
child.geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );
child.geometry.computeVertexNormals();
child.geometry.elementsNeedUpdate = true;
child.geometry.mergeVertices();
child.verticesNeedUpdate = true;
child.normalsNeedUpdate = true;
child.uvsNeedUpdate = true;
child.material.flatShading = THREE.SmoothShading;
}
});
main.scene.add(main.man);
},
function (xhr){
console.log((xhr.loaded/xhr.total*100)+'% loaded');
},
function (error){
console.log(error,'An error happened');
}
);
window.onresize = main.onResize;
this.render();
}
this.render = function(){
var time = Date.now();
main.controls.update();
requestAnimationFrame(main.render);
main.renderer.render(main.scene, main.camera);
}
this.onResize = function(event) {
main.renderer.setSize(window.innerWidth, window.innerHeight);
main.camera.aspect = window.innerWidth / window.innerHeight;
main.camera.updateProjectionMatrix();
}
}
main.init();
<script src="https://cdn.jsdelivr.net/npm/three@0.115/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.115/examples/js/controls/OrbitControls.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/OBJLoader.js"></script>
<textarea id="plane_obj" style="display:none;">
v -1.000000 0.000000 1.000000
v 1.000000 0.000000 1.000000
v -1.000000 0.000000 -1.000000
v 1.000000 0.000000 -1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 1.000000
vn 0.0000 1.0000 0.0000
f 1/1/1 2/2/1 4/4/1 3/3/1
</textarea>
<script type='x-shader/x-vertex' id='vertex-shader'>
uniform float u_time;
varying vec2 vUv;
void main() {
vUv = uv;
vec4 pos = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
gl_Position = pos;
}
</script>
<script type='x-shader/x-fragment' id='fragment-shader'>
precision highp float;
uniform float u_time;
uniform vec2 u_resolution;
uniform sampler2D texture;
varying vec2 vUv;
void main(){
vec2 st = vUv;
vec4 tex = texture2D(texture, st);
gl_FragColor = tex;
}
</script>