簡體   English   中英

提高Threejs /着色器幾何圖形的UV線質量

[英]Improve UV line quality of threejs/shader geometry

我正在使用threejs圓環的uv輸出在圓環上創建移動線。 它有效,但看起來不清晰。

如何改善線路質量? 我嘗試將材料制作為雙面,並增加線的寬度,但是質量並沒有太大改善。

我還沒有嘗試在Threejs之外完全復制圓環,但這超出了我的舒適范圍。

我希望有辦法改變片段着色器的邏輯以產生更清晰的線條。 有任何建議,我將不勝感激。

Codepen

/* Scene Initialization */
var startTime = Date.now();
var scene = new THREE.Scene();
var width = window.innerWidth;
var height = window.innerHeight;
var canvas = document.getElementById('canvas');
var camera = new THREE.PerspectiveCamera(75, 1, 1, 1200);
// var camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 1, 1200 );

camera.position.set(0, -420, 600);
camera.lookAt(new THREE.Vector3(0, 0, 0));

var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth * .2, window.innerWidth * .2);
renderer.setClearColor( 0xffffff, 1);
canvas.appendChild(renderer.domElement);

var geometry = new THREE.TorusGeometry(200, 200, 260, 260); 
material = new THREE.ShaderMaterial( {
        uniforms: {time: { type: "f", value: Date.now() - startTime}, },
        vertexShader: `attribute vec3 center;
            varying vec3 vCenter;
      varying vec2 vUv;
            void main() {
                vCenter = center;
        vUv = uv;
                gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
            }`,
        fragmentShader: `varying vec3 vCenter;
      varying vec2 vUv;
      uniform float time;
      uniform sampler2D tDiffuse;
            void main() {
        float sh = 0.005;
        float PI = 3.1415926535897932384626433832795;
        // float linesX = mod(time + vUv.x, 0.03);
        float linesX = sin((time + vUv.x) * PI * 30.)/30.;
        // float linesY = mod(time + vUv.y, 0.05);
        float linesY = sin((time + vUv.y) * PI * 20.)/20.;
        float smoothX =
        smoothstep( 0.0 - sh, 0.0, linesX) -
          smoothstep( 0.0, 0.0 + sh, linesX);
        float smoothY =
        smoothstep( 0.0 - sh, 0.0, linesY) -
          smoothstep( 0.0, 0.0 + sh, linesY);

        float uvOutput = smoothX + smoothY;
        gl_FragColor.rgb = vec3(1.0, 0, 0);
        gl_FragColor.a = uvOutput;
        // gl_FragColor = vec4(1.,0,0,1.)

            }`
      } );
//material.extensions.derivatives = true;

material.side = THREE.DoubleSide;

material.transparent = true;

//material.blending = THREE.Add;
material.depthTest = false;

var torus = new THREE.Mesh(geometry, material);
var geom = torus.geometry;
geometry.sortFacesByMaterialIndex();
torus.position.x = 0;

scene.add(torus);

/* Request Animation Frame */
function animation() {
  camera.lookAt(new THREE.Vector3(0, 0, 0));
  renderer.render(scene, camera);
  material.uniforms.time.value = (Date.now() - startTime)/20000;
  requestAnimationFrame(animation);
}

animation();
setupDraggableEvents();

function setupDraggableEvents() {
  var hammer = new Hammer(document.getElementsByTagName('canvas')[0]);
  hammer.on('pan', function(event) {
    torus.rotation.y += event.velocityX / 10;
    torus.rotation.x += event.velocityY / 10;
  });
}

我建議定義兩個方向的線數,並根據UV坐標計算到線的距離:

float t = time;

vec2 noLines = vec2(30.0, 20.0);
vec2 floorUV = floor((t + vUv) * noLines);
vec2 distUV  = t + vUv - (floorUV+0.5) / noLines;

在線條的粗細和一半粗細之間平滑地插值(“ smoothstep ),以計算“飽和度”。 這導致該行始終在中間始終具有完整的“強度”(當然,您可以嘗試使用此sh*0.66 ,例如sh*0.66sh*0.33 ):

float sh = 0.005;
vec2 lineUV = smoothstep(sh, sh*0.5, abs(distUV));

alpha通道是兩個方向的最大“飽和​​度”值:

float uvOutput = max(lineUV.x, lineUV.y);
gl_FragColor = vec4(1.0, 0.0, 0.0, uvOutput);

請參見示例,其中我將建議的更改應用於原始代碼:

 /* Scene Initialization */ var startTime = Date.now(); var scene = new THREE.Scene(); var width = window.innerWidth; var height = window.innerHeight; var canvas = document.getElementById('canvas'); var camera = new THREE.PerspectiveCamera(75, 1, 1, 1200); camera.position.set(0, -420, 600); camera.lookAt(new THREE.Vector3(0, 0, 0)); orbitControls = new THREE.OrbitControls(camera); var renderer = new THREE.WebGLRenderer({antialias: true}); renderer.setSize(window.innerWidth * .2, window.innerWidth * .2); renderer.setClearColor( 0xffffff, 1); canvas.appendChild(renderer.domElement); var geometry = new THREE.TorusGeometry(200, 200, 260, 260); material = new THREE.ShaderMaterial( { uniforms: {time: { type: "f", value: Date.now() - startTime}, }, vertexShader: `attribute vec3 center; varying vec3 vCenter; varying vec2 vUv; void main() { vCenter = center; vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); }`, fragmentShader: `varying vec3 vCenter; varying vec2 vUv; uniform float time; uniform sampler2D tDiffuse; void main() { float t = time; vec2 noLines = vec2(30.0, 20.0); vec2 floorUV = floor((t + vUv) * noLines); vec2 distUV = t + vUv - (floorUV+0.5) / noLines; float sh = 0.005; vec2 lineUV = smoothstep(sh, sh*0.5, abs(distUV)); float uvOutput = max(lineUV.x, lineUV.y); gl_FragColor = vec4(1.0, 0.0, 0.0, uvOutput); }`, transparent: true } ); //material.extensions.derivatives = true; material.side = THREE.DoubleSide; material.transparent = true; //material.blending = THREE.Add; material.depthTest = false; var torus = new THREE.Mesh(geometry, material); var geom = torus.geometry; geometry.sortFacesByMaterialIndex(); torus.position.x = 0; scene.add(torus); /* Request Animation Frame */ function animation() { camera.lookAt(new THREE.Vector3(0, 0, 0)); renderer.render(scene, camera); material.uniforms.time.value = (Date.now() - startTime)/20000; requestAnimationFrame(animation); } resize(); window.onresize = resize; animation(); setupDraggableEvents(); function setupDraggableEvents() { var hammer = new Hammer(document.getElementsByTagName('canvas')[0]); hammer.on('pan', function(event) { torus.rotation.y += event.velocityX / 10; torus.rotation.x += event.velocityY / 10; }); } function resize() { var aspect = window.innerWidth / window.innerHeight; renderer.setSize(window.innerWidth, window.innerHeight); camera.aspect = aspect; camera.updateProjectionMatrix(); } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/100/three.min.js"></script> <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script> <div id="canvas"></div> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM