THREE.JS ShaderMaterial превосходит мою сетку - PullRequest
0 голосов
/ 18 сентября 2018

У меня есть классическая сетка, состоящая из THREE.PlaneGeometry и материала.Если я добавлю THREE.MeshNormalMaterial(), вот результат, который я получу:

enter image description here

Пока все хорошо.Но когда я называю свою THREE.ShaderMaterial(), используя внешнюю текстуру, размер моей сетки полностью меняется:

enter image description here

Я всегда получаю это странное соотношение дажеесли - как на скриншоте - моя текстура квадратная (512x512).Я просто хочу, чтобы мой MaterialShader вписался в мою геометрию.

Вот код моего MaterialShader:

var material = new THREE.ShaderMaterial( {
   uniforms: uniforms,
   vertexShader: document.getElementById( 'vertexShader' ).textContent,
   fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
} );

var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );

Я не вижу, что мне не хватает.У кого-нибудь есть идея?Большое спасибо.

ОБНОВЛЕНИЕ: Вот полный код моего ShaderMaterial:

material = new THREE.ShaderMaterial({
    uniforms:{
        u_time: { type: "f", value: 1.0 },
        u_resolution: { type: "v2", value: new THREE.Vector2() },
        u_mouse: { type: "v2", value: new THREE.Vector2() },
        texture1: { type: "t", value: texture }
    },
    vertexShader:`
        void main() {
            gl_Position = vec4( position, 1.0 );
        }
    `,
    fragmentShader:`
        #ifdef GL_ES
            precision highp float;
            precision highp int;
        #endif

        uniform vec2 u_resolution;
        uniform vec2 u_mouse;
        uniform float u_time;

        uniform sampler2D texture1;

        void main(){

            float pyt=3.1415926*2./3.;
            float m=-1e10;
            vec4 mv= vec4(0.);

            vec2 xy = gl_FragCoord.xy/u_resolution.xy;

            int ic=0;

            for (int i=0;i<30;i++){
                vec2 np=vec2(xy.x+float(i)/u_resolution.x*sin(3.14/2.)  * 4.,xy.y+float(i)/u_resolution.y*cos(3.14/2.) * 4.);


                float jTime = u_time*1.618;  
                vec4 tk=texture2D(texture1,np);
                float t=tk.r*sin(jTime)+tk.g*sin(jTime+pyt)+tk.b*sin(jTime+2.*pyt)-.01*float(i);

                if (t>m){m=t; mv=tk;ic=i;}
            }
            float sc=float(ic)/30.;
            vec4 tk=texture2D(texture1,xy);
            mv=sc*tk+(1.-sc)*mv;
            gl_FragColor = vec4(mv.r,mv.g,mv.b,1.0);
        }
    `
});

ОБНОВЛЕНИЕ2: Я изменил свой вершинный шейдер, но ничего не изменилось.

Я мог быесть инициатива: я думаю, что это связано с настройками моей камеры.Я изменил их, и у меня есть лучший результат.Теперь моя текстура вписывается в мою квадратную сетку.

К сожалению, масштаб не очень хорош.Поскольку моя текстура также является квадратом, я хочу, чтобы она имела точно такой же размер, что и моя сетка, а пока она увеличена.

Как я могу управлять размером моей текстуры?Должен ли я сделать это внутри моего vertexShader?

Вот мои настройки текстуры на данный момент:

texture = new THREE.TextureLoader().load( "test5.jpg");
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;

ОБНОВЛЕНИЕ 3:

Я нашел этот код, чтобы применить текстуру и сделать еевписывается в мою сетку: https://bl.ocks.org/duhaime/c8375f1c313587ac629e04e0253481f9

Это работает, но как только я изменяю свой пример шейдера fragement, у меня нет ошибок, но шейдеры становятся одним уникальным цветом.Я не понимаю, чего мне не хватает ...

1 Ответ

0 голосов
/ 18 сентября 2018

Попробуйте этот код вершинного шейдера:

void main() {
  gl_Position = projectionMatrix *
                modelViewMatrix *
                vec4(position,1.0);
}

Ссылка

Просто передайте UV-координаты из вершинного шейдера во фрагментный шейдер и используйте их там.

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 5);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x404040);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var iResolution = new THREE.Vector2();

var planeGeo = new THREE.PlaneBufferGeometry(5, 5);
var planeMat = new THREE.ShaderMaterial({
  uniforms: {
    texture: {
      value: null
    },
    iResolution: {
      value: iResolution
    },
    iTime: {
      value: 0
    }
  },
  vertexShader: `
    varying vec2 vUv;
    void main() {
      vUv = uv;
      gl_Position = projectionMatrix *
                    modelViewMatrix *
                    vec4(position,1.0);
    }
  `,
  fragmentShader: `
    uniform sampler2D texture;
    uniform float iTime;
    uniform vec2 iResolution;
    
    varying vec2 vUv;
    
    void main() {
      float pyt=3.1415926*2./3.;
      float m=-1e10;//very negitive start value for maximisation algorithm.
      vec4 mv= vec4(0.);//lank starting value of max so far

      vec2 xy = vUv;
      int ic=0;//stores smear distance
      for (int i=0;i<30;i++){
          //point offset on a circle
          vec2 np=vec2(xy.x+float(i)/iResolution.x*sin(iTime),xy.y+float(i)/iResolution.y*cos(iTime));
          //colour cycles faster than position
          float jTime = iTime*1.618;  
          //get neerby point
        vec4 tk=texture2D(texture,np);
          // and if its colourfull enough, use that
          float t=tk.r*sin(jTime)+tk.g*sin(jTime+pyt)+tk.b*sin(jTime+2.*pyt)-.01*float(i);
          if (t>m){m=t; mv=tk;ic=i;}
      }
      //mix smeared with background depending ondistance
      float sc=float(ic)/30.;
      vec4 tk=texture2D(texture,xy);
      mv=sc*tk+(1.-sc)*mv;
      gl_FragColor = vec4(mv.rgb,1.0);
    }
  `
});

var textureLoader = new THREE.TextureLoader();
textureLoader.load("https://threejs.org/examples/textures/UV_Grid_Sm.jpg", tex => {
  planeMat.uniforms.texture.value = tex;
  planeMat.uniforms.texture.value.needsUpdate = true;
  iResolution.set(tex.image.width, tex.image.height);
  planeMat.needsUpdate = true;
  console.log(texture);
});

var plane = new THREE.Mesh(planeGeo, planeMat);
scene.add(plane);

var clock = new THREE.Clock();
var time = 0;

render();

function render() {
  requestAnimationFrame(render);
  time += clock.getDelta();
  planeMat.uniforms.iTime.value = time;
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
...