कैसे एक बनावट हमेशा कैमरे का सामना करने के लिए ..?


10

अद्यतन ५

उम्मीद की जा रही है दिखाने के लिए एक और बेला बनाया जाएगा। एक अदृश्य स्काइडोम और एक क्यूबेकेरा जोड़ा जाता है और पर्यावरण मानचित्र का उपयोग किया जाता है; मेरे मामले में, इनमें से किसी भी तकनीक का उपयोग पहले से ही वर्णित कारणों के लिए नहीं किया जाना चाहिए।


अद्यतन ४

महत्वपूर्ण: कृपया ध्यान दें कि लक्ष्य जाल के पीछे एक चिंतनशील विमान है जो देखने के लिए है कि क्या बनावट मेष की सतह को सही ढंग से बांधती है, इसका कोई लेना देना नहीं है कि मैं क्या हल करने की कोशिश कर रहा हूं।


अपडेट ३

अपेक्षित व्यवहार नहीं है, यह दिखाने के लिए एक नया फिडल बनाया गया है

  • कोड

हो सकता है कि मुझे अपने प्रश्न को फिर से लिखना चाहिए, लेकिन मुझे इस बात की सही जानकारी नहीं है कि मैं क्या हल करने की कोशिश कर रहा हूं, कृपया मदद करें। शायद .. ?)


अपडेट २

(जैसे कोड स्निपेट लागू किया गया है


अपडेट करें

ठीक है .. मैंने 3 विधियाँ जोड़ी हैं:

  • TransformUvएक ज्यामिति, और एक ट्रांसफार्मर विधि को स्वीकार करता है जो uv- परिवर्तन को संभालता है। कॉलबैक प्रत्येक चेहरे और इसके मापदंडों के अनुरूप Face3के लिए एक uvs सरणी स्वीकार करता है 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सही तरीके से करने के लिए ज्ञान की कमी है। इसे हल करने के कुछ प्रतिबंध हैं:

  • CubeCamera / CubeMap का उपयोग नहीं किया जा सकता क्योंकि ग्राहक मशीनों में प्रदर्शन समस्याएं हो सकती हैं

  • केवल जाली lookAtको कैमरा न बनाएं क्योंकि वे अंततः किसी भी प्रकार के ज्यामिति के हैं, न केवल गोले; एक फ्रेम में जैसे lookAtऔर पुनर्स्थापित .quaternionकरना ठीक होगा।

कृपया मुझे गलत न समझें कि मैं एक XY समस्या पूछ रहा हूँ क्योंकि मुझे मालिकाना कोड को उजागर करने का अधिकार नहीं है या मुझे न्यूनतम उदाहरण बनाने के प्रयास का भुगतान नहीं करना पड़ेगा :)


क्या आप GLSL shader भाषा जानते हैं? इस आशय को प्राप्त करने का एकमात्र तरीका एक कस्टम शेडर लिखना है जो यूवी निर्देशांक के डिफ़ॉल्ट व्यवहार को ओवरराइड करता है।
मार्किज़ो

@Marquizzo मैं GLSL में कोई विशेषज्ञ नहीं हूँ, हालाँकि, मैंने कुछ स्रोत कोड खोले हैं। जैसे कि WebGLRenderTargetCube; मैं ShaderMaterial के साथ लिपटा GLSL पा सकते हैं। जैसा कि मैंने बताया है, 'मुझे इसके चारों ओर ज्ञान की कमी है और यह इस समय पीने के लिए बहुत अधिक होगा। मेरा मानना ​​है कि तीन.जेएस ने जीएलएसएल को अच्छी तरह से लपेटा है और यह भी काफी हल्का है कि मुझे लगा कि हम खुद जीएलएसएल से निपटने के बिना लाइब्रेरी का उपयोग करके इस तरह की चीजें हासिल कर सकते हैं।
केन किन

2
क्षमा करें, लेकिन एकमात्र तरीका मैं ऐसा करने के बारे में सोच सकता हूं GLSL के माध्यम से, क्योंकि बनावट हमेशा छायादार में खींची जाती है, और आप बनावट की स्थिति की गणना करने के डिफ़ॉल्ट तरीके को बदलने की कोशिश कर रहे हैं। आपके पास इस प्रकार के "कैसे" प्रवचन
।threejs.org

मैं पुष्टि कर सकता हूं, कि एक पिक्सेल shader द्वारा GPU पाइपलाइन में
सॉल्व

जवाबों:


7

कैमरे का सामना करना पड़ेगा जैसा:

यहां छवि विवरण दर्ज करें

या, और भी बेहतर, जैसा कि इस प्रश्न में है , जहां विपरीत फिक्स पूछा जाता है:

यहां छवि विवरण दर्ज करें

इसे प्राप्त करने के लिए, आपको एक साधारण टुकड़ा shader सेटअप करना होगा (जैसा कि OP गलती से किया था):

वर्टेक्स shader

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);
}

तीन के साथ shader का एक काम करने वाला मजाक

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>
  

एक व्यवहार्य विकल्प: घन मानचित्रण

यहाँ मैंने क्यूब मैपिंग के बारे में एक jsfiddle को संशोधित किया है , हो सकता है कि आप क्या देख रहे हों:

https://jsfiddle.net/v8efxdo7/

क्यूब अंतर्निहित वस्तु पर अपने चेहरे की बनावट को प्रोजेक्ट करता है और यह कैमरे को देख रहा है।

नोट: रोशनी रोटेशन के साथ बदलती है क्योंकि प्रकाश और आंतरिक वस्तु निश्चित स्थिति में होती है, जबकि कैमरा और प्रोजेक्शन क्यूब दृश्य के केंद्र के चारों ओर घूमता है।

यदि आप ध्यान से उदाहरण के लिए देखते हैं, तो यह तकनीक सही नहीं है, लेकिन आप क्या देख रहे हैं (एक बॉक्स पर लागू किया गया है) मुश्किल है, क्योंकि क्यूब की बनावट का यूवी अनट्रैप क्रॉस-आकार का है, जो स्वयं यूवी को घूर्णन नहीं करेगा प्रभावी हो और प्रक्षेपण तकनीकों का उपयोग करने में इसकी कमियां भी हैं, क्योंकि प्रोजेक्टर ऑब्जेक्ट आकार और प्रक्षेपण विषय आकार मायने रखता है।

बस बेहतर समझ के लिए: वास्तविक दुनिया में, आप बॉक्स में 3 डी स्पेस में इस प्रभाव को कहां देखते हैं? मेरे दिमाग में आने वाला एकमात्र उदाहरण एक 3D सतह पर एक 2D प्रक्षेपण (जैसे दृश्य डिजाइन में प्रक्षेपण मानचित्रण) है।


1
पूर्व का अधिक। क्या आप कृपया इसे करने के लिए तीन.js का उपयोग करेंगे? मैं GLSL से परिचित नहीं हूँ। और मैं उत्सुक हूं कि यदि आपके द्वारा दिखाए गए पहले एनीमेशन में क्यूब एक ही समय में प्रत्येक अक्ष के चारों ओर घूमता है तो क्या होगा? जब आप अपने कार्यान्वयन को तीन.js का उपयोग करके प्रदान करते हैं, तो मैं कोशिश करूँगा और देखूंगा कि क्या मेरा प्रश्न हल हो गया है। होनहार लग रहा है :)
केन किन

1
हाय दोस्त, मैंने एक सरल डेमो के साथ एक कोडपेन जोड़ा है जो आपको ज़रूरत के अनुसार शेडर को पुन: पेश करता है।
मोसु रागुजिनी

मुझे यह जांचने के लिए कुछ समय चाहिए कि यह मेरे मामले के लिए काम करता है या नहीं।
केन किन

1
यह मॉर्फिंग को नहीं खोता है, अगर बनावट हमेशा कैमरे का सामना करती है, तो प्रभाव हमेशा एक सादे बनावट का होगा, अगर एनवी में कोई रोशनी नहीं है या सामग्री छाया नहीं डालती है। स्थिति जैसी विशेषताएं और वर्दी ज्यामिति और बफरग्रोमेट्री द्वारा प्रदान की जाती हैं, ताकि आपको उन्हें अन्य स्थानों पर पुनः प्राप्त न करना पड़े। तीन.js
मोस रागुजिनी

1
कृपया संशोधित एक के jsfiddle.net/7k9so2fr पर एक नज़र डालें । मैं कहता हूँ कि बनावट बंधन का यह व्यवहार वह नहीं है जिसे मैं प्राप्त करने की कोशिश कर रहा हूँ :( ..
केन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.