我正在尝试通过使用RepeatWrapping在非常大的平面(1000x1000,它也会缩放10倍)上应用纹理。使用MeshBasicMaterial时看起来不错,但是使用ShaderMaterial时会闪烁。以下是我的代码。
<!DOCTYPE html>
<html>
<head>
<title>MeshShaderMaterialExample</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0, shrink-to-fit=no">
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<script src="https://unpkg.com/three@0.85.0/examples/js/controls/TrackballControls.js"></script>
<script src="js/TWEEN.js"></script>
<style type="text/css">
body {
width: 100%;
height: 100%;
background-color: #000;
color: #fff;
margin: 0px;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<script>
var camera, scene, renderer;
var container, mesh, geometry;
var controls, effect;
var tweenUpdate="false";
var tweenOver="true";
var textureData=
{
"texture_0":
{
"img":"gman.png"
},
"texture_1":
{
"img":"gman.png"
}}
var magicPosition = { magicTrans:0 };
var magicTarget = { magicTrans:1 };
var magicTween = new TWEEN.Tween(magicPosition).to(magicTarget, 1000);
magicTween.easing(TWEEN.Easing.Linear.None);
var currentTexture=0;
var nextTexture=0;
var uniforms = {
textures: {
value: []
},
repeat: {
type: 'f',
value: 100
},
transition: {
value: 0
},
currentUniform: {
value: 0
},
nextUniform: {
value: 0
}
};
var textureLoader = new THREE.TextureLoader();
var pics=[];
for (var i = 0; i < Object.keys(textureData).length; i++) {
var ass="texture_"+i;
pics[i]= textureData[ass].img;
console.log(pics[i]);
}
pics.forEach((p, idx)=>{
textureLoader.load(p, function(tex){
tex.needsUpdate = true;
uniforms.textures.value[idx] = tex;
uniforms.textures.value[idx].needsUpdate = true;
// console.log(tex);
uniforms.textures.value[idx].minFilter = THREE.LinearFilter;
})
});
var vertShader = `
varying vec2 vUv;
uniform float repeat;
void main()
{
vUv = repeat * uv;
vec4 mvPosition = modelViewMatrix * vec4(position, 1 );
gl_Position = projectionMatrix * mvPosition;
}
`;
var fragShader = `
uniform sampler2D textures[` + pics.length + `];
uniform float transition;
uniform float currentUniform;
uniform float nextUniform;
varying vec2 vUv;
vec4 getTexture(int index){
for(int i = 0; i < ` + pics.length + `; i++){
if (i == index){ return texture2D(textures[i],vUv); }
}
}
void main()
{
float chunk = 1. / ` + 1 + `.; // amount of transitions = 1
float t = floor(transition / chunk);
int idx0 = int(currentUniform);
int idx1 = int(nextUniform);
gl_FragColor = mix(
getTexture(idx0),
getTexture(idx1),
(transition - (float(t) * chunk)) * ` + 1 + `.
);
}
`;
window.onload=function()
{
init();
animate();
}
function init(){
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
controls = new THREE.TrackballControls( camera,renderer.domElement );
camera.position.z = 500;
console.log(camera.fov);
scene = new THREE.Scene();
scene.add(camera);
var magicPlaneMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vertShader,
fragmentShader: fragShader,
side: THREE.DoubleSide
});
for (var i = 0; i < Object.keys(textureData).length; i++) {
uniforms.textures.value[i].wrapS = uniforms.textures.value[i].wrapT = THREE.RepeatWrapping;
uniforms.textures.value[i].needsUpdate = true;
}
// for (var i = 0; i < Object.keys(textureData).length; i++) {
// uniforms.textures.value[i].wrapS = uniforms.textures.value[i].wrapT = THREE.RepeatWrapping;
// uniforms.textures.value[i].needsUpdate = true;
// }
var magicPlaneGeometry = new THREE.PlaneBufferGeometry(1000, 1000, 16, 16);
var magicPlaneMesh = new THREE.Mesh(magicPlaneGeometry, magicPlaneMaterial);
magicPlaneMesh.position.y = -500;
magicPlaneMesh.rotation.x = Math.PI / 2;
magicPlaneMesh.scale.x=10;
magicPlaneMesh.scale.y=10;
scene.add(magicPlaneMesh);
changeMagicPlane(currentTexture);
document.addEventListener( 'wheel', onDocumentMouseWheel, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseWheel( event ) {
var fov = camera.fov + event.deltaY * 0.05;
camera.fov = THREE.Math.clamp( fov, 10, 75 );
console.log(camera.fov);
camera.updateProjectionMatrix();
}
function animate() {
if(tweenUpdate=="true")
{
TWEEN.update();
}
renderer.render( scene, camera );
controls.update();
requestAnimationFrame( animate );
}
function changeMagicPlane(asset){
var assNum= parseInt(asset);
nextTexture = assNum;
uniforms.nextUniform.value = nextTexture;
console.log("Cuurent: "+currentTexture);
console.log("Next: "+nextTexture);
magicTween.start();
tweenUpdate="true";
tweenOver="false";
}
magicTween.onUpdate(function(){
uniforms.transition.value = magicPosition.magicTrans;
});
magicTween.onComplete(function(){
tweenUpdate="false";
tweenOver="true";
clicked="false";
//console.log("Am i complete?");
magicPosition.magicTrans=0;
currentTexture=nextTexture;
uniforms.currentUniform.value = currentTexture;
console.log("Current: "+currentTexture);
});
</script>
</body>
</html>
我正在尝试使用ShaderMaterial来实现交叉渐变效果。我的纹理图像是256 * 256像素。
工作片段。从此处(http://learningthreejs.com/blog/2011/08/17/tweenjs-for-smooth-animation/)开始使用Tween.js。 gman.png来自这里(https://i.imgur.com/ZKMnXce.png)
答案 0 :(得分:1)
通过将纹理最小化功能(trilinear texture)设置为值THREE.LinearFilter
,您已禁用mipmaps过滤(.minFilter
):
uniforms.textures.value[idx].minFilter = THREE.LinearFilter;
这会导致Moire effects。
通过THREE.LinearMipMapLinearFilter
激活trilinear texture过滤(默认):
uniforms.textures.value[idx].minFilter = THREE.LinearMipMapLinearFilter;
无论如何,您的(片段)着色器代码具有未定义的行为,并且mip映射将不起作用:
vec4 getTexture(int index){ for(int i = 0; i < ` + pics.length + `; i++){ if (i == index){ return texture2D(textures[i],vUv); } } } void main() { // .... gl_FragColor = mix( getTexture(idx0), getTexture(idx1), (transition - (float(t) * chunk)) * ` + 1 + `. );
请参见OpenGL ES Shading Language 1.00 Specification - 13 Acknowledgements;第107页:
5个数组,向量和矩阵的索引
[...]
Samplers
GLSL ES 1.00支持采样器数组和包含采样器的结构数组。在这两种情况下,对于ES 2.0,都要求支持使用constant-index-expression进行索引,但不要求支持使用其他值进行索引。
[...]
6个纹理访问权限
在非均匀条件块的主体内访问mip映射的纹理会给出不确定的值。条件非均匀块是无法在编译时确定执行的块。
在main的块范围内进行纹理查找,并使用 constant-index-expression 作为纹理采样器数组的索引:
例如
float a = transition - float(t) * chunk;
gl_FragColor = mix(texture2D(textures[0], vUv), texture2D(textures[1], vUv), a);