কীভাবে কোনও টেক্সচারটি সর্বদা ক্যামেরার মুখোমুখি করবেন ..?


10

আপডেট 5

যা প্রত্যাশিত তা দেখতে কেমন হবে তা দেখাতে অন্য একটি ফ্রিডল তৈরি করেছে। একটি অদৃশ্য স্কাইডোম এবং একটি কিউবিকামেরা যুক্ত করা হয় এবং পরিবেশের মানচিত্র ব্যবহৃত হয়; আমার ক্ষেত্রে, এই প্রযুক্তিগুলির কোনওটি ইতিমধ্যে উল্লিখিত কারণে ব্যবহার করা উচিত নয়।


আপডেট 4

গুরুত্বপূর্ণ: দয়া করে নোট করুন জাল পৃষ্ঠার পিছনে একটি প্রতিফলিত বিমান রয়েছে যা পর্যবেক্ষণ করার জন্য যদি টেক্সচারটি জাল পৃষ্ঠকে সঠিকভাবে বেঁধে রাখে, আমি সমাধান করার চেষ্টা করছি এর সাথে এর কোনও সম্পর্ক নেই।


আপডেট 3

প্রত্যাশিত আচরণটি কী নয় তা দেখাতে একটি নতুন ফিজল তৈরি করেছে

  • কোড

হতে পারে আমার প্রশ্নটির পুনঃব্যবহার করা উচিত, তবে আমি কী সমাধান করতে চাইছি সে সম্পর্কে সঠিকভাবে বর্ণনা করার মতো জ্ঞানের অভাব বোধ করছি, দয়া করে সহায়তা করুন .. (প্যানোরামিক-ট্রান্সফর্ম-উইথ টেক্সচার-লিকিং-এ-ডিরেক্টর-লকড-টু-দ্য ক্যামেরা হতে পারে .. ?)


আপডেট 2

(কোড স্নিপেট প্রয়োগ হওয়ার সাথে সাথে হ্রাস করা হয়েছে))


হালনাগাদ

ঠিক আছে .. আমি 3 টি পদ্ধতি যুক্ত করেছি:

  • TransformUvজ্যামিতি এবং ট্রান্সফর্মার পদ্ধতি গ্রহণ করে যা ইউভি-ট্রান্সফর্মকে পরিচালনা করে। কলব্যাক প্রতিটি মুখের জন্য একটি Uvs অ্যারে এবং সংশ্লিষ্ট গ্রহণ Face3এর geometry.faces[]তার পরামিতি হিসেবে।

  • MatcapTransformer ম্যাটক্যাপ রূপান্তর করতে ইউভি-ট্রান্সফর্ম হ্যান্ডলার কলব্যাক।

    এবং

  • fixTextureWhenRotateAroundZAxis এটি যা নাম দিয়েছে তার মতো কাজ করে।

এখনও অবধি কোনও fixTexture..পদ্ধতিই পুরোপুরি কাজ করতে পারে না, তাও fixTextureWhenRotateAroundXAxisবের করা যায় না। সমস্যাটি অমীমাংসিত রয়ে গেছে, আমি আশা করি যে সবেমাত্র যুক্ত হয়েছে তা আমাকে সাহায্য করতে আপনাকে সহায়তা করতে পারে।


আমি জালের টেক্সচারটি সর্বদা একটি সক্রিয় দৃষ্টিভঙ্গি ক্যামেরার মুখোমুখি করার চেষ্টা করছি, আপেক্ষিক অবস্থানগুলি যাই হোক না কেন।

আমার দৃশ্যের একটি বাস্তব কেস গঠনের জন্য এবং মিথস্ক্রিয়াটি বেশ জটিল হবে, আমি নিজের অভিপ্রায়টি প্রদর্শনের জন্য একটি ন্যূনতম উদাহরণ তৈরি করেছি।

  • কোড
    var MatcapTransformer=function(uvs, face) {
    	for(var i=uvs.length; i-->0;) {
    		uvs[i].x=face.vertexNormals[i].x*0.5+0.5;
    		uvs[i].y=face.vertexNormals[i].y*0.5+0.5;
    	}
    };
    
    var TransformUv=function(geometry, xformer) {
    	// The first argument is also used as an array in the recursive calls 
    	// as there's no method overloading in javascript; and so is the callback. 
    	var a=arguments[0], callback=arguments[1];
    
    	var faceIterator=function(uvFaces, index) {
    		xformer(uvFaces[index], geometry.faces[index]);
    	};
    
    	var layerIterator=function(uvLayers, index) {
    		TransformUv(uvLayers[index], faceIterator);
    	};
    
    	for(var i=a.length; i-->0;) {
    		callback(a, i);
    	}
    
    	if(!(i<0)) {
    		TransformUv(geometry.faceVertexUvs, layerIterator);
    	}
    };
    
    var SetResizeHandler=function(renderer, camera) {
    	var callback=function() {
    		renderer.setSize(window.innerWidth, window.innerHeight);
    		camera.aspect=window.innerWidth/window.innerHeight;
    		camera.updateProjectionMatrix();
    	};
    
    	// bind the resize event
    	window.addEventListener('resize', callback, false);
    
    	// return .stop() the function to stop watching window resize
    	return {
    		stop: function() {
    			window.removeEventListener('resize', callback);
    		}
    	};
    };
    
    (function() {
    	var fov=45;
    	var aspect=window.innerWidth/window.innerHeight;
    	var loader=new THREE.TextureLoader();
    
    	var texture=loader.load('https://i.postimg.cc/mTsN30vx/canyon-s.jpg');
    	texture.wrapS=THREE.RepeatWrapping;
    	texture.wrapT=THREE.RepeatWrapping;
    	texture.center.set(1/2, 1/2);
    
    	var geometry=new THREE.SphereGeometry(1, 16, 16);
    	var material=new THREE.MeshBasicMaterial({ 'map': texture });
    	var mesh=new THREE.Mesh(geometry, material);
    
    	var geoWireframe=new THREE.WireframeGeometry(geometry);
    	var matWireframe=new THREE.LineBasicMaterial({ 'color': 'red', 'linewidth': 2 });
    	mesh.add(new THREE.LineSegments(geoWireframe, matWireframe));
    
    	var camera=new THREE.PerspectiveCamera(fov, aspect);
    	camera.position.setZ(20);
    
    	var scene=new THREE.Scene();
    	scene.add(mesh);
      
    	{
    		var mirror=new THREE.CubeCamera(.1, 2000, 4096);
    		var geoPlane=new THREE.PlaneGeometry(16, 16);
    		var matPlane=new THREE.MeshBasicMaterial({
    			'envMap': mirror.renderTarget.texture
    		});
    
    		var plane=new THREE.Mesh(geoPlane, matPlane);
    		plane.add(mirror);
    		plane.position.setZ(-4);
    		plane.lookAt(mesh.position);
    		scene.add(plane);
    	}
    
    	var renderer=new THREE.WebGLRenderer();
    
    	var container=document.getElementById('container1');
    	container.appendChild(renderer.domElement);
    
    	SetResizeHandler(renderer, camera);
    	renderer.setSize(window.innerWidth, window.innerHeight);
    
    	var fixTextureWhenRotateAroundYAxis=function() {
    		mesh.rotation.y+=0.01;
    		texture.offset.set(mesh.rotation.y/(2*Math.PI), 0);
    	};
    
    	var fixTextureWhenRotateAroundZAxis=function() {
    		mesh.rotation.z+=0.01;
    		texture.rotation=-mesh.rotation.z
    		TransformUv(geometry, MatcapTransformer);
    	};
    
    	// This is wrong
    	var fixTextureWhenRotateAroundAllAxis=function() {
    		mesh.rotation.y+=0.01;
    		mesh.rotation.x+=0.01;
    		mesh.rotation.z+=0.01;
    
    		// Dun know how to do it correctly .. 
    		texture.offset.set(mesh.rotation.y/(2*Math.PI), 0);
    	};
      
    	var controls=new THREE.TrackballControls(camera, container);
    
    	renderer.setAnimationLoop(function() {
    		fixTextureWhenRotateAroundYAxis();
    
    		// Uncomment the following line and comment out `fixTextureWhenRotateAroundYAxis` to see the demo
    		// fixTextureWhenRotateAroundZAxis();
    
    		// fixTextureWhenRotateAroundAllAxis();
        
    		// controls.update();
    		plane.visible=false;
    		mirror.update(renderer, scene);
    		plane.visible=true; 
    		renderer.render(scene, camera);
    	});
    })();
    body {
    	background-color: #000;
    	margin: 0px;
    	overflow: hidden;
    }
    <script src="https://threejs.org/build/three.min.js"></script>
    <script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>
    
    <div id='container1'></div>

দয়া করে মনে রাখবেন যে জাল নিজেই এই প্রদর্শনীতে ঘোরে, আমার আসল উদ্দেশ্য ক্যামেরাটিকে জালের চারপাশে প্রদক্ষিণ করার মতো করে তুলছে।

চলাচল আরও স্পষ্ট করতে আমি তারের ফ্রেম যুক্ত করেছি। আপনি দেখতে পাচ্ছেন যে আমি fixTextureWhenRotateAroundYAxisএটি সঠিকভাবে করতে ব্যবহার করি তবে এটি কেবল y- অক্ষের জন্য। mesh.rotation.yআমার বাস্তব কোডে ভালো কিছু গণনা করা হয়

var ve=camera.position.clone();
ve.sub(mesh.position);
var rotY=Math.atan2(ve.x, ve.z);
var offsetX=rotY/(2*Math.PI);

তবে কীভাবে fixTextureWhenRotateAroundAllAxisসঠিকভাবে করবেন তা সম্পর্কে আমার জ্ঞান নেই । এটি সমাধানের কিছু বিধিনিষেধ রয়েছে:

  • ক্লায়েন্ট মেশিনগুলির পারফরম্যান্স সমস্যা হতে পারে বলে কিউবক্যামেরা / কিউব্যাপ ব্যবহার করা যাবে না

  • কেবল জাল lookAtক্যামেরা তৈরি করবেন না কারণ শেষ পর্যন্ত তারা কোনও ধরণের জ্যামিতির হয়, কেবলমাত্র গোলকই নয়; একটি ফ্রেমে পছন্দ lookAtএবং পুনরুদ্ধার কৌশলগুলি .quaternionঠিক হবে।

দয়া করে আমাকে ভুল করবেন না যে আমি মালিকানা কোড প্রকাশ করার অধিকার না থাকায় আমি এক্সওয়াই সমস্যা জিজ্ঞাসা করছি বা আমার একটি ন্যূনতম উদাহরণ তৈরির চেষ্টাটি দিতে হবে না :)


আপনি জিএলএসএল শেডার ভাষা জানেন? এই প্রভাবটি অর্জনের একমাত্র উপায় হ'ল একটি কাস্টম শেডার লিখুন যা ইউভি স্থানাঙ্কগুলির ডিফল্ট আচরণকে ওভাররাইড করে।
মারকুইজো

@ মারকুইজো আমি জিএলএসএল-তে কোনও বিশেষজ্ঞ নই, তবে, আমি ওয়েলজিএলরেন্ডারটারেজকিউবের মতো থ্রি.জেসের কিছু সোর্স কোড খনন করেছি; আমি শ্যাডারেটারিয়ালের সাথে জড়িত জিএলএসএলটি দেখতে পাচ্ছি। যেমনটি আমি বলেছি, 'আমার চারপাশে জ্ঞানের অভাব রয়েছে এবং এই মুহুর্তে এটি পান করা খুব বেশি হবে। আমি বিশ্বাস করি যে থ্রি। জেএসএস জিএলএসএলকে যথেষ্ট ভাল জড়িয়ে রেখেছে এবং এটি যথেষ্ট পরিমাণে লাইটওয়েট যা আমি ভেবেছিলাম যে আমরা নিজেরাই জিএলএসএলকে না নিয়েই লাইব্রেরি ব্যবহার করে এই জাতীয় জিনিসগুলি অর্জন করতে পারি।
কেন কিন

2
দুঃখিত, তবে আমি এটি করার একমাত্র উপায় হ'ল জিএলএসএল এর মাধ্যমে, যেহেতু সবসময় শ্যাডারে টেক্সচারগুলি আঁকা থাকে এবং আপনি টেক্সচারের অবস্থানটি গণনা করার জন্য ডিফল্টভাবে পরিবর্তন করার চেষ্টা করছেন। আপনি ভাল ভাগ্য এ প্রশ্ন "কীভাবে" এই ধরনের জিজ্ঞাসা থাকতে পারে discourse.threejs.org
Marquizzo

আমি নিশ্চিত করতে পারি, এটি পিক্সেল শেডার দ্বারা জিপিইউ পাইপলাইনে সমাধানযোগ্য
মোসেই রাগুজনি

উত্তর:


7

ক্যামেরার মুখোমুখি হ'ল:

এখানে চিত্র বর্ণনা লিখুন

বা, আরও ভাল, যেমন এই প্রশ্নের হিসাবে , যেখানে বিপরীত ফিক্স জিজ্ঞাসা করা হয়:

এখানে চিত্র বর্ণনা লিখুন

এটি অর্জন করতে, আপনাকে একটি সাধারণ টুকরা শেডার সেটআপ করতে হবে (ওপি যেমন দুর্ঘটনাক্রমে করেছিল):

ভার্টেক্স শ্যাডার

void main() {
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

টুকরা শেডার

uniform vec2 size;
uniform sampler2D texture;

void main() {
  gl_FragColor = texture2D(texture, gl_FragCoord.xy / size.xy);
}

থ্রি.জেএস সহ শেডারটির একটি কার্যকরী উপহাস

function main() {
  // Uniform texture setting
  const uniforms = {
    texture1: { type: "t", value: new THREE.TextureLoader().load( "https://threejsfundamentals.org/threejs/resources/images/wall.jpg" ) }
  };
  // Material by shader
   const myMaterial = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: document.getElementById('vertexShader').textContent,
        fragmentShader: document.getElementById('fragmentShader').textContent
      });
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas});

  const fov = 75;
  const aspect = 2;  // the canvas default
  const near = 0.1;
  const far = 5;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.z = 2;

  const scene = new THREE.Scene();

  const boxWidth = 1;
  const boxHeight = 1;
  const boxDepth = 1;
  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);

  const cubes = [];  // just an array we can use to rotate the cubes
  
  const cube = new THREE.Mesh(geometry, myMaterial);
  scene.add(cube);
  cubes.push(cube);  // add to our list of cubes to rotate

  function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }
    return needResize;
  }

  function render(time) {
    time *= 0.001;
    
    if (resizeRendererToDisplaySize(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }

    cubes.forEach((cube, ndx) => {
      const speed = .2 + ndx * .1;
      const rot = time * speed;
      
      
      cube.rotation.x = rot;
      cube.rotation.y = rot;      
    });
   

    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main();
body {
  margin: 0;
}
#c {
  width: 100vw;
  height: 100vh;
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script>
<script id="vertexShader" type="x-shader/x-vertex">
  void main() {
    gl_Position =   projectionMatrix * 
                    modelViewMatrix * 
                    vec4(position,1.0);
  }
</script>

<script id="fragmentShader" type="x-shader/x-fragment">
  uniform sampler2D texture1;
  const vec2  size = vec2(1024, 512);
  
  void main() {
    gl_FragColor = texture2D(texture1,gl_FragCoord.xy/size.xy); 
  }
</script>
<canvas id="c"></canvas>
  

একটি কার্যকর বিকল্প: কিউব ম্যাপিং

এখানে আমি কিউব ম্যাপিং সম্পর্কে একটি জিসফিল পরিবর্তন করেছি , সম্ভবত আপনি যা খুঁজছেন তা হ'ল:

https://jsfiddle.net/v8efxdo7/

কিউব অন্তর্নিহিত বস্তুতে তার মুখের গঠনটি প্রজেক্ট করে এবং এটি ক্যামেরার দিকে তাকিয়ে থাকে।

দ্রষ্টব্য: আলো ঘোরার সাথে পরিবর্তিত হয় কারণ আলো এবং অভ্যন্তরীণ বস্তু স্থির স্থানে থাকে, যখন ক্যামেরা এবং প্রজেকশন কিউব উভয় দৃশ্যের কেন্দ্রের চারদিকে ঘোরে।

আপনি যদি সাবধানতার সাথে উদাহরণটির দিকে নজর দেন তবে এই কৌশলটি নিখুঁত নয়, তবে আপনি যা খুঁজছেন (একটি বাক্সে প্রয়োগ করা হয়েছে) তা জটিল, কারণ ঘনকটির টেক্সচারের UV মোড়কটি ক্রস আকারের, নিজেই UV ঘোরানো হবে না প্রজেক্টর অবজেক্ট শেপ এবং প্রজেকশন সাবজেক্ট শেপ বিষয়টিকে কার্যকর করে তোলে এবং প্রজেকশন কৌশলগুলি ব্যবহার করার ক্ষেত্রেও এর অপূর্ণতা রয়েছে।

কেবল আরও ভাল বোঝার জন্য: বাস্তব বিশ্বে আপনি বাক্সগুলিতে 3 ডি স্পেসে এই প্রভাবটি কোথায় দেখছেন? আমার মনে যে একমাত্র উদাহরণ আসে তা হ'ল 3 ডি পৃষ্ঠের 2D প্রক্ষেপণ (ভিজ্যুয়াল ডিজাইনে প্রজেকশন ম্যাপিংয়ের মতো)।


1
প্রাক্তনটির আরও বেশি। আপনি কি দয়া করে এটি করতে থ্রি.জে ব্যবহার করবেন? আমি জিএলএসএল এর সাথে পরিচিত নই। এবং আমি কৌতূহল করছি যে আপনি যে প্রথম অ্যানিমেশন দেখান তাতে কিউব একই সাথে প্রতিটি অক্ষের চারদিকে ঘুরালে কী হবে? আপনি থ্রি.জেএস ব্যবহার করে আপনার বাস্তবায়ন সরবরাহ করার পরে, আমি চেষ্টা করব এবং দেখব যে আমার প্রশ্নটির সমাধান হয়েছে। প্রতিশ্রুতিবদ্ধ মনে হচ্ছে :)
কেন কিন

1
হাই সাথী, আমি আপনার প্রয়োজনীয় শেডারটির পুনরুত্পাদন করার জন্য একটি সাধারণ ডেমো সহ একটি কোডপেন যুক্ত করেছি।
মোসাদ রাগুজনি

এটি আমার ক্ষেত্রে কার্যকর কিনা তা খতিয়ে দেখার জন্য আমার কিছু সময় প্রয়োজন need
কেন কিন

1
এটি মর্ফিংটি হারাবে না, যদি টেক্সচারটি সর্বদা ক্যামেরার মুখোমুখি হয় তবে প্রভাবটি সর্বদা সরল টেক্সচারের হবে, যদি এনভির কোনও আলো না থাকে বা উপাদান ছায়া ফেলে না দেয়। অবস্থানের মতো বৈশিষ্ট্য এবং ইউনিফর্মগুলি জ্যামিতি এবং বাফার জ্যামিতি দ্বারা সরবরাহ করা হয় যাতে আপনাকে এগুলি অন্য জায়গায় পুনরুদ্ধার করতে না হয়। : Three.js এর ডক্স এটি সম্পর্কে একটি চমৎকার অধ্যায় আছে threejs.org/docs/#api/en/renderers/webgl/WebGLProgram
Mose Raguzzini

1
দয়া করে সংশোধিতটির jsfiddle.net/7k9so2fr একবার দেখুন । আমি বলব টেক্সচার বাইন্ডিংয়ের এই আচরণটি আমি অর্জন করার চেষ্টা করছি না :( ..
কেন কিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.